<!--
  上传组件（向后端服务器获取表单形式， 直传到oss）

  @author terrfly
  @site https://www.jeequan.com
  @date 2022/01/14 12:14
-->
<template>
  <div style="">
    <!--  capture=undefined ： 手机可选择本地图片，     删除该属性，则手机上传无法读取相册 ， 直接调起相机。 https://github.com/vueComponent/ant-design-vue/issues/5986  -->
    <a-upload
      v-model:fileList="vdata.fileList"
      :action="vdata.action"
      :beforeUpload="beforeUploadFunc"
      :headers="vdata.headers"
      :data="vdata.formParams"
      :list-type="vdata.listType"
      :showUploadList="props.showUploadList"
      :multiple="props.multiple"
      :accept="vdata.accept"
      :capture="undefined"
      @preview="previewFileFunc"
      @change="handleChange"
    >
      <div
        v-if="!props.showUploadList || vdata.fileList.length <= 0"
        class="ant-upload-list ant-upload-list-picture"
        style="cursor: pointer"
      >
        <span v-if="listType == 'picture'"><div
          class="ant-upload-list-item ant-upload-list-item-undefined ant-upload-list-item-list-type-picture"
          style="padding-top: 20px"
        >
          <upload-outlined />上传
        </div></span>
        <div v-else>
          <plus-outlined />
          <div class="ant-upload-text">Upload</div>
        </div>
      </div>
    </a-upload>

    <!-- ！！！ 本地测试！！！  -->
    <!-- <button @click="() => emit('update:src', 'https://jeepaypublic.oss-cn-beijing.aliyuncs.com/applyment/4f0f1ae8-d3e5-46b0-a75e-7d49b31827b1.jpg')">测试</button> -->
  </div>
</template>

<script setup lang="ts">
import { Upload } from 'ant-design-vue'
import appConfig from '@/config/appConfig'
import storage from '@/utils/jeepayStorageWrapper'
import {reactive, defineProps, getCurrentInstance, onMounted, watch } from 'vue'
import { API_URL_UPLOAD_SINGLE_FILE_URL, $getUploadFormParams, $orcScan } from '@/api/manage'
import { sm4DecryptByResData } from '@/utils/encryptUtil'
const { $infoBox, $viewerApi } = getCurrentInstance()!.appContext.config.globalProperties

// 定义 父组件传参
const props = defineProps({
  showUploadList: { type: Boolean, default: true }, // 是否显示上传的列表， 一般都需要显示，  比如头像需要自定义的话那么则不需要显示，并且按钮常显
  src: { type: String, default: '' }, // 双向绑定  文件地址
  bizType: { type: String, default: '' }, // 业务类型
  fileType: { type: String, default: 'img' }, // img or file
  accept: { type: String, default: null }, // 上传文件的accept
  uploadMode: { type: String, default: 'formRedirect' }, // 上传方式： formRedirect 先获取form表单地址直传oss,  file：上上传到本地后端服务器在上传到oss方式。
  ocrType: { type: String, default: null }, // orc类型如果存在值则上传成功后自动调起ORC识别功能
  imgSize: { type: Number, default:  localStorage.getItem('uploadImgSize') || 2 }, // 上传图片大小限制  优先获取本地存储 
  listType: { type: String, default: 'picture' }, // 上传列表的内建样式 默认picture
  multiple: { type: Boolean, default: false }, // 上传列表的内建样式 默认picture
})

// 父组件通讯函数
const emit = defineEmits(['update:src', 'change', 'ocrScan'])

// 定义响应式数据
const vdata: any = reactive({
  action: '', // 文件form表单请求地址
  fileList: [], // 全部文件集合
  formParams: {}, // 上传参数
  headers: {}, // 放入token
  formReqFileUrl: '', // 第一次的form请求的图片数据， 如果存在则使用该地址， 否则使用文件上传的响应地址。
  accept: null, //上传文件的accept
  listType: '' // 上传列表的内建样式
})

onMounted(() => {
  if (props.src) {
    vdata.fileList = [{ url: props.src, name: getFileName(props.src) }]
  }

  if (props.listType) {
    vdata.listType = props.listType
  }

  // 处理 accept
  if (!props.accept && props.fileType == 'img') {
    vdata.accept = 'image/*' // 所有的图片格式
  } else {
    vdata.accept = props.accept
  }
  
})

// // 监听变化
watch(
  () => props.src,
  (newVal, oldVal) => {
    if (newVal) {
      vdata.fileList = [{ url: newVal, name: getFileName(newVal) }]
    } else {
      vdata.fileList = []
    }
  }
)

function getFileName(name) {
  if (!name) {
    return name
  }

  return name.substring(name.lastIndexOf('/') + 1)
}

// 上传回调
function handleChange(info) {
  if (info.file.status === 'uploading') {
    // console.log('上传中')
  }
  if (info.file.status === 'done') {
    // 上传完成

    let fileList = Object.assign([], vdata.fileList)

    vdata.fileList = [] // 通过watch 更改文件集合

    // 如果包含code 并且 不是0 ： 本系统返回的错误信息。
    if (info.file.response.code && info.file.response.code != 0) {
      return $infoBox.message.error(info.file.response.msg)
    }

    // 上传成功
    let successImgUrl = vdata.formReqFileUrl

    // 读取响应结果的值
    if (!successImgUrl) {
      successImgUrl = info.file.response.encryptData
        ? sm4DecryptByResData(info.file.response.encryptData)
        : info.file.response.data
    }
    emit('update:src', successImgUrl)
    emit('change', successImgUrl, fileList)
    ocrFunc(successImgUrl) // ORC识别
  } else if (info.file.status === 'error') {
    // 上传异常
    vdata.fileList = []
    $infoBox.message.error('上传异常')
  } else if (info.file.status === 'removed') {
    // 文件被删除
    vdata.formReqFileUrl = ''
    emit('update:src', vdata.formReqFileUrl)
    emit('change', vdata.formReqFileUrl, [])
  }
}

// 上传图片前的校验
function beforeUploadFunc(file) {

  // 拦截操作 如果传入imgSize 会对图片大小进行校验
  if (props.bizType === 'applyment') {
    const flag = file.size / 1024 / 1024 <  (getLocationImgSize() ||  props.imgSize)
    //隐藏图片大小
    // if (!flag) {
    //   $infoBox.message.error(`上传图片大小不能超过${ getLocationImgSize() || props.imgSize}M`)
    //   return flag || Upload.LIST_IGNORE
    // }
  }
  if (props.uploadMode == 'formRedirect') {
    // form表单方式
    // 请求获取form参数
    return $getUploadFormParams(file, props.bizType).then((res) => {
      console.log(res,'resresres')
      if (res.formActionUrl == 'LOCAL_SINGLE_FILE_URL') {
        // 本地方式
        localUploadResetInfo()
      } else {
        vdata.action = res.formActionUrl // action
        vdata.formParams = res.formParams //表单组件
        vdata.formReqFileUrl = res.ossFileUrl
      }
    }).catch(() => {
      return Upload.LIST_IGNORE
    })
  }

  // file文件方式
  return Promise.resolve((params) => {
    localUploadResetInfo()
  })
}

// 预览图片
function previewFileFunc(file) {

  if (props.fileType == 'img') {
    $viewerApi({ images: [props.src] })
  }
}

// 本地上传的方式，需要设置的form和header等信息
function localUploadResetInfo() {
  //action
  vdata.action = API_URL_UPLOAD_SINGLE_FILE_URL

  // token
  vdata.headers[appConfig.ACCESS_TOKEN_NAME] = storage.getToken()

  // params
  vdata.formParams = { bizType: props.bizType }
}

function ocrFunc(url) {
  if (!props.ocrType) {
    return false
  }

  $orcScan(url, props.ocrType).then((res) => {
    $infoBox.message.success('图片识别成功，已自动回填内容，请检查核对')
    emit('ocrScan', res)
  })
}
// 移动端 地址栏传参解析
function getLocationImgSize() {
  let params = {} as any
  let href = window.location.href
  href = href.substring(href.indexOf('?') + 1)
  let arr = href.split('&')
  arr.forEach(item => {
    let a = item.split('=')
    params[a[0]] = a[1]
  })
  console.log('params.uploadImgSize',params.uploadImgSize)
  console.log('href',href)
  
 if(params.uploadImgSize) return  params.uploadImgSize
 return false
}
// 自定义请求

</script>
<style scoped lang="less">
/deep/ .ant-upload-list-item-name {
  flex: auto !important;
}
</style>
