<template>
  <div class="upload_wrap">
    <div v-if="waitFileList.length > 0">
      <div class="el-upload-list el-upload-list--picture-card" v-if="listType == 'picture-card' || listType == 'picture'">
        <div class="el-upload-list__item is-success" style="width:fit-content;height:fit-content;"
          v-for="( item, index ) in  waitFileList " :key="index">
          <el-image style="width:fit-content;height:148px; min-width:148px" :src="item.url" fit="cover"
            :lazy="true"></el-image>
          <div v-if="!props.isDisableUpload" class="el-upload-list__item-actions el-upload-list__item-delete">
            <el-icon class="cursor-pointer" @click="removeFile(item)">
              <DeleteFilled />
            </el-icon>
          </div>
        </div>
      </div>
      <div class="template_list" v-if="listType == 'text'">
        <div class="template" v-for="(item, index) in waitFileList" :key="index">
          <span>
            <el-icon>
              <Link />
            </el-icon>
          </span>
          <span class="documentName">{{ item.name }}</span>
          <span v-if="!props.isDisableUpload">
            <el-icon color="#000000a6" size="16" @click="removeFile(item)">
              <Close />
            </el-icon>
          </span>
          <span v-if="isDownLoad" style="paddingleft: 5px">
            <el-icon @click="handleDownLoad(item)">
              <Download />
            </el-icon>
          </span>
        </div>
      </div>
    </div>
    <el-upload v-else class="w-auto upload" ref="uploadRef" :file-list="waitFileList" :multiple="props.isMultiple"
      :limit="props.limitNum" :list-type="listType" :accept="props.acceptType" :auto-upload="false"
      :show-file-list="false" :disabled="props.isDisableUpload" :on-change="handleChange" :on-remove="handleRemove">
      <div class="el-upload__text" v-if="listType == 'text'">
        <el-icon>
          <Upload />
        </el-icon>
        <span>上传文件</span>
      </div>
      <div v-else>
        <el-icon>
          <Plus />
        </el-icon>
      </div>
      <template #tip v-if="!props.isDisableUpload && isShowTips">
        <div class="el-upload__tip">
          <span>支持{{ acceptType.replaceAll(",", "/") }}；</span>
          <span v-if="isLimitSize">
            文件大小不能超过{{ props.maxFileSize }}M;
          </span>
          <span v-if="isCheckMM">
            尺寸：{{ props.widthLimit }}*{{ props.heightLimit }}px
          </span>
        </div>
      </template>
    </el-upload>
    <el-dialog v-model="dialogVisible">
      <img w-full :src="dialogImageUrl" alt="Preview Image" />
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch } from "vue";
import { ElLoading, ElMessage } from "element-plus";
import http from '@/api/http';
import { Close, Upload, Download, Plus, Link, DeleteFilled } from "@element-plus/icons-vue";
import type { UploadProps, UploadUserFile } from 'element-plus'
const emits = defineEmits(["fileSuccess", "fileRemove"]);
interface Props {
  acceptType?: string; // 上传文件类型
  isMultiple?: boolean; //   是否可批量上传
  isCheckName?: boolean; //   是否检查文件名
  limitNum?: number; // 允许上传文件的最大数量
  isDisableUpload?: boolean; // 是否禁用上传
  maxFileSize?: number; // 文件大小
  widthLimit?: number; // 图片宽度
  heightLimit?: number; // 图片高度
  isLimitSize?: boolean;//是否限制大小
  isShowTips?: boolean;
  action?: string;
  formType?: string;//上传的文件字段名称
  fileList?: any; // 回显的文件
  isDownLoad?: boolean; // 是否可以下载
  isCheckMM?: boolean; // 是否检查图片尺寸
  listType?: string;//文件上传样式类型
}
// 接收父组件传递过来的参数
const props = withDefaults(defineProps<Props>(), {
  acceptType: ".jpeg,.png",
  formType: "photo",
  isMultiple: false,
  isCheckName: false,
  isCheckMM: false,
  limitNum: 10,
  isDisableUpload: false,
  maxFileSize: 1,
  isShowTips: true,
  isLimitSize: true,
  action: "/qiniu/upload/image",
  fileList: [],
  widthLimit: 690,
  heightLimit: 280,
  isDownLoad: false,
  listType: 'picture-card'
});
let waitFileList = ref<any[]>([]);

waitFileList.value = props.fileList;
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!
  dialogVisible.value = true
}
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles)
}
watch(
  () => props.fileList,
  () => {
    console.log("props.fileList====>", props.fileList);
    waitFileList.value = props.fileList;
  }
);

// 文件变化Handle 这里监听上传文件的变化是一个一个接收到变化的，所以文件也是一个一个上传到服务器上面的
const handleChange = async (file: any, fileList: any[]) => {
  if (props.isCheckMM) {
    const test = await limitFileWH(file)
    if (!test) return
  }
  if (!/^[0-9]+_/.test(file.name) && props.isCheckName) {
    ElMessage.error(`文件上传格式错误`);
    return false
  }
  // 防止多次执行change
  const rawFile = file.raw;
  const list = props.acceptType.split(",");
  let acceptTypeList = list.map((its: string) => {
    return getType(its)
  })
  console.log(list, acceptTypeList, rawFile.type, 'acceptTypeListacceptTypeList');
  // 如果要检索的字符串值没有出现，则该方法返回 -1
  const ars = acceptTypeList.filter((q: string) => {
    return rawFile.type.indexOf(q) > -1
  })
  // 用于校验是否符合上传条件
  const type = props.acceptType
  if (ars.length < 1) {
    ElMessage.error(`仅支持格式为${type}的图片`);
    return false;
  } else if (rawFile.size / 1024 / 1024 > props.maxFileSize && props.isLimitSize) {
    ElMessage.error(`文件大小不能超过${props.maxFileSize}MB!`);
    const arr = [...waitFileList.value];
    waitFileList.value = arr.filter((item: any) => {
      return item.uid != rawFile.uid;
    });
    return false;
  }
  else {
    let formData = new FormData();
    formData.append(props.formType, rawFile);
    const loadingInstance = ElLoading.service({
      text: "正在上传",
      background: "rgba(0,0,0,.2)",
    });
    // 上传到服务器上面
    const requestURL: string = props.action;
    http.post(requestURL, formData)
      .then(async (res: any) => {
        if (res.code == 10000) {
          loadingInstance.close();
          waitFileList.value.push({ uid: file.uid, url: res.data })
          emits("fileSuccess", res.data);
        } else {
          loadingInstance.close();
          ElMessage.warning(`文件上传失败`);
        }
      })
      .catch(() => {
        loadingInstance.close();
        // ElMessage.warning(`文件上传失败`);
      });
  }
  return true;
};
//限制图片尺寸
const limitFileWH = (file) => {
  const isSize = new Promise(function (resolve, reject) {
    const reader = new FileReader();
    reader.onload = (event) => {
      const image = new Image();
      image.onload = () => {
        const { width, height, size } = image;
        if (width !== props.widthLimit || height !== props.heightLimit) {
          reject(image);
        } else {
          resolve(image);
        }
      };

      image.onerror = (error) => {
        reject(`图片加载错误：${error}`);
      };
      image.src = event.target.result;
    };

    reader.onerror = (error) => {
      reject(`文件读取错误：${error}`);
    };

    reader.readAsDataURL(file.raw);
  }).then((e) => {
    return true;
  }, (e) => {
    console.log(props.widthLimit);
    ElMessage.error({
      message: '上传文件的图片大小不合符标准,宽需要为' + props.widthLimit + 'px，高需要为' + props.heightLimit + 'px。当前上传图片的宽高分别为：' + e.width + 'px和' +
        e.height + 'px',
    })
    return false;
  });
  return isSize
}


// 校验上传文件格式
const getType = (acceptType: string) => {
  let val = "";
  switch (acceptType) {
    case ".xls":
      val = "excel";
      break;
    case ".doc":
      val = "word";
      break;
    case ".pdf":
      val = "pdf";
      break;
    case ".zip":
      val = "zip";
      break;
    case ".xlsx":
      val = "sheet";
      break;
    case ".pptx":
      val = "presentation";
      break;
    case ".docx":
      val = "document";
      break;
    case ".text":
      val = "text";
      break;
    case ".jpeg":
      val = "jpeg";
      break;
    case ".png":
      val = "png";
      break;
    case ".gif":
      val = "gif";
      break;
    case ".mp4":
      val = "mp4";
      break;
    case ".mp3":
      val = "mp3";
      break;
  }
  return val
};

// 移除文件
const removeFile = (file: any) => {
  const arr: any[] = [...waitFileList.value];
  waitFileList.value = arr.filter((its: any) => {
    console.log(its, file);
    return its.uid != file.uid;
  });

  console.log(file, 'file', arr, waitFileList.value);
  emits("fileRemove", file);
};

const handleDownLoad = (row: { ossFile: string }) => {
  const str = window.location.href.split("#")[0];
  const herf = str.slice(0, str.length - 1);
  window.location.href = herf + row.ossFile;
};
</script>

<style lang="scss" scoped>
.upload_wrap {
  .upload {
    width: auto;
    padding-bottom: 10px;
  }

  .tips {
    display: block;
    font-size: 14px;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: rgba(0, 0, 0, 0.65);
  }
}

:deep().el-upload__text {
  width: 106px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.15);

  img {
    display: block;
    width: 14px;
    height: 14px;
  }

  span {
    font-size: 14px;
    padding-left: 6px;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: rgba(0, 0, 0, 0.65);
  }
}

.template_list {
  padding-bottom: 4px;
}

.template {
  display: flex;
  align-items: center;
  padding: 5px 0;

  span {
    line-height: 16px;
  }

  img {
    margin-right: 8px;
    width: 16px;
    height: 16px;
  }

  .documentName {
    margin-right: 12px;
    font-size: 14px;
    color: rgba(0, 0, 0, 0.65);
  }
}
</style>

