<!-- @format -->

<template>
  <div>
    <p v-if="value && showFile">
      <a download="" target="_blank" :href="value">{{ downloadName }}</a>
      <!-- <span class="close">
        <ns-icon name="close" @click="remove" />
      </span> -->
    </p>
    <div class="clearfix container">
      <!--:multiple="showCount != 1"-->
      <!--:showUploadList="false"-->
      <a-upload
        :accept="acceptFileType.join()"
        :before-upload="beforeUpload"
        :customRequest="selfUpload"
        :showUploadList="false">
        <a-button>
          <upload-outlined />
          上传文件
        </a-button>
        <div class="upload-tips">
          <!--上传提示信息-->
          <p v-if="acceptType && acceptType.length > 0"> 支持扩展名:{{ acceptType.join(' ') }} </p>
          <p v-if="fixedFileName && fixedFileName.length > 0">
            仅支持文件:{{ fixedFileName.join(' ') }}
          </p>
        </div>
      </a-upload>
    </div>
    <!-- 提示 -->
    <div class="err-msg">
      <p :style="{ color: 'red' }" v-if="error">{{ error }}</p>
    </div>
    <p v-if="!error" :style="{ color: uploadResult === '上传成功' ? '#51b97b' : '#323232' }">
      {{ fileName }} {{ uploadResult }}
    </p>
    <!-- 提示 -->
  </div>
</template>
<script lang="ts">
  import {
    UploadOutlined,
    LoadingOutlined,
    EyeOutlined,
    DeleteOutlined,
  } from '@ant-design/icons-vue';
  import { defineComponent, ref, computed, reactive, PropType } from 'vue';
  // import {http} from '/nerv-lib/util/http';
  import { NsMessage } from '../../message';
  import { NSAxios } from '/nerv-lib/util/http/axios';
  import { get, isArray } from 'lodash-es';

  interface FileItem {
    uid: string;
    type: string;
    size: number;
    name?: string;
    status?: string;
    response?: string;
    percent?: number;
    url?: string;
    preview?: string;
    originFileObj?: any;
  }

  interface FileInfo {
    file: FileItem;
    fileList: FileItem[];
  }

  // 转base64
  function getBase64(file: File) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result);
      reader.onerror = (error) => reject(error);
    });
  }

  export interface sizeItem {
    fileType: Array<string>;
    maxSize: number;
    errorTip?: string;
  }

  export default defineComponent({
    name: 'NsUploadFileV2',
    components: {
      UploadOutlined,
      LoadingOutlined,
      DeleteOutlined,
      EyeOutlined,
    },
    props: {
      // 上传的地址
      url: {
        type: String,
        require: true,
      },
      // 上传的图片大小
      maxSize: {
        type: Number || (Array as PropType<Array<sizeItem>>), // [  { 'maxSize':512488000,'fileType': ['jpg', 'png']  } ]
        default: 524288000,
      },
      // 上传的图片类型
      fileType: {
        type: Array,
        default: () => {
          return ['.jpg', '.png', '.jpeg'];
        },
      },
      //弹窗限制的类型
      acceptFileType: {
        type: Array,
        default: () => {
          return ['jpg', 'png', 'jpeg'];
        },
      },
      // 固定限制的文件名称
      fixedFileName: {
        type: Array,
      },
      //随file添加固定传参
      params: {
        type: [Object],
      },
      // 展示图片数量
      showCount: {
        type: Number,
        default: 1,
      },
      // 上传文件类型,0-证书,1-图片,2-身份证件
      uploadType: {
        type: Number,
        default: 1,
      },
      //是否显示下载附件
      showFile: {
        type: Boolean,
        default: false,
      },
      //传入数据数据源
      dataSouce: {
        type: Object,
      },
      //处理传入数据用于触发change事件
      setDataSouce: {
        type: Function,
      },
      //获取下载链接
      getUrlOrName: {
        type: Function,
      },
      //设置取值字段
      valueField: {
        type: String,
        default: 'data.httpUrl',
      },
      value: {
        type: String || Object,
      },
      downloadName: {
        type: String || Object,
        default: '下载文件',
      },
    },
    emits: ['change'],
    setup(props, { attrs, emit }) {
      function createHttp() {
        /** todo  临时去除超时时间 */
        return new NSAxios({
          headers: { 'Content-Type': 'application/json;charset=UTF-8' },
          withCredentials: true,
        });
      }
      const uploadHttp = createHttp();
      const previewVisible = ref<boolean>(false);
      const error = ref<string>('');
      const uploadResult = ref<string>('');
      const previewImage = ref<string | undefined>('');
      const fileName = ref<string | undefined>('');
      const fileList = ref<FileItem[]>([]);
      const currentImg = ref<string[]>([]);
      const maskShow = ref<boolean[]>([]);
      let data = reactive({});
      let tempData = ref({});
      const acceptType = computed(() =>
        props.fileType.map((item: String) => {
          return item;
        }),
      );
      const beforeUpload = (file: FileItem) => {
        if (!file) {
          return;
        }
        fileName.value = file.name;
        /** 1.判断类型和大小 */
        error.value = '';
        uploadResult.value = '';
        // 文件类型
        const type = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
        if (acceptType.value && acceptType.value.length > 0) {
          // 限定文件类型
          if (acceptType.value.includes(type)) {
            error.value = '';
          } else {
            error.value = `请选择${props.fileType.join(',')}文件`;
            return false;
          }
        } else if (props.fixedFileName) {
          // 固定文件名称
          const fixedFileName = props.fixedFileName;
          if (fixedFileName && fixedFileName.includes(file.name)) {
            error.value = '';
          } else {
            console.log(props.fixedFileName.join(','));
            error.value = `请选择${props.fixedFileName.join(',')}的文件`;
            return false;
          }
        }
        // 文件大小
        let valid = true;
        error.value = '';
        if (isArray(props.maxSize)) {
          props.maxSize.some((el) => {
            if (el.fileType.includes(type)) {
              valid = file.size <= el.maxSize;
              error.value = valid
                ? ''
                : el['errorTip'] || `  请选择${el.maxSize / 1024 / 1024}M内的文件`;
              return true;
            }
          });
        } else if (file.size > props.maxSize) {
          error.value = `  请选择${props.maxSize / 1024 / 1024}M内的文件`;
          valid = false;
        }
        if (!valid) return valid;
        return error.value == '';
      };

      const selfUpload = async ({ file }) => {
        currentImg.value.unshift(await getBase64(file));
        const params = {
          // uploadType: props.uploadType,
        };
        const formData = new FormData();
        formData.append('file', file);
        const config = {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
          params: params,
        };
        Object.keys(props.params).map((item) => {
          formData.append(item, props.params[item]);
        });
        uploadResult.value = '上传中...';
        uploadHttp
          .post(props.url, formData, config)
          .then((res) => {
            error.value = '';
            uploadResult.value = '上传成功';
            data = res;
            tempData.value = res.data;
            if (attrs['fieldMap']) {
              emit('change', data);
            } else {
              emit('change', get(data, props.valueField));
            }
          })
          .catch((err) => {
            console.log('err', err);
            uploadResult.value = '';
            error.value = `${file.name} 上传失败,请重试`;
            NsMessage.error('上传失败,请重试');
          });
      };

      const handlePreview = async (index: number) => {
        previewImage.value = (await getBase64(fileList.value[index].originFileObj)) as string;
        previewVisible.value = true;
      };

      const deleteImg = (index: number) => {
        currentImg.value.splice(index, 1);
        fileList.value.splice(index, 1);
      };

      const handleCancel = () => {
        previewVisible.value = false;
      };

      const mouseEnter = (index: number) => {
        maskShow.value[index] = true;
      };

      const mouseLeave = (index: number) => {
        maskShow.value[index] = false;
      };
      const remove = () => {
        Object.keys(tempData.value).map((key) => {
          tempData.value[key] = '';
        });
        emit('change', { data: tempData.value });
      };
      const doWnload = (url) => {
        let a = document.createElement('a');
        document.body.appendChild(a);
        a.href = encodeURI(url);
        //设置下载的文件名
        // a.download = fileName.value;
        //触发a标签的点击事件,进行下载
        a.click();
      };

      return {
        previewVisible,
        previewImage,
        fileList,
        error,
        uploadResult,
        fileName,
        currentImg,
        maskShow,
        data,
        tempData,
        acceptType,
        selfUpload,
        handleCancel,
        handlePreview,
        beforeUpload,
        mouseEnter,
        mouseLeave,
        deleteImg,
        doWnload,
        remove,
      };
    },
  });
</script>
<style lang="less" scoped>
  .close {
    cursor: pointer;
  }
</style>