<template>
  <div>
    <p v-if="getUrlOrName && showFile && getUrlOrName('url', tempData)">
      <a download="" target="_blank" :href="getUrlOrName('url', tempData)">{{
        getUrlOrName("name", tempData)
      }}</a>
      <span class="close">
        <ns-icon name="close" @click="remove" />
      </span>
    </p>
    <div class="clearfix container">
      <!--:multiple="showCount != 1"-->
      <!--:showUploadList="false"-->
      <a-upload
        :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 } 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: "NsUploadFile",
  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,
    },
    // 固定限制的文件名称
    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,
    },
  },
  emits: ["change"],
  setup(props, { 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({});
    if (props.dataSouce && props.setDataSouce) {
      tempData.value = props.setDataSouce(JSON.parse(JSON.stringify(props.dataSouce)));
      emit("change", { data: tempData.value });
    }
    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;
          console.log(data);
          emit("change", data);
        })
        .catch(() => {
          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>
