<template>
  <div>
    <div class="container clearfix">
      <!-- 图片显示框 -->
      <template v-if="currentImg.length">
        <div class="imgList" v-for="(item, index) in fileList" :key="item">
          <div class="imgContainer" @mouseenter="mouseEnter(index)" @mouseleave="mouseLeave(index)">
            <img :src="currentImg[index]" class="imgCover" />
            <span v-if="maskShow[index]" class="mask">
              <EyeOutlined v-if="false" @click="handlePreview(item, index)" />
              <DeleteOutlined v-if="!disabled" @click="deleteImg(index)" />
            </span>
          </div>
        </div>
      </template>
      <!-- 图片显示框 /-->
      <!-- 上传图片框/内置了input -->
      <a-spin :spinning="spinning">
        <a-upload
          v-if="count === 1 ? 'true' : fileList.length < count"
          list-type="picture-card"
          :before-upload="beforeUpload"
          @change="handleChange"
          :multiple="count != 1"
          :disabled="disabled"
          :customRequest="selfUpload"
          :showUploadList="false">
          <!-- :disabled="count == 1 && fileUuid ? true : false" -->
          <div>
            <template v-if="isLt5M && isJpgOrPngOrJpeg">
              <UploadOutlined :style="{ fontSize: '14px' }" />
              <div class="ant-upload-text">上传图片</div>
            </template>
            <template v-else>
              <LoadingOutlined />
              <div class="ant-upload-text">校验失败</div>
            </template>
          </div>
        </a-upload>
      </a-spin>
      <!-- 上传图片框/内置input /-->
    </div>
    <!-- 预览图片弹窗 -->
    <ns-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
      <img v-if="previewVisible" alt="example" style="width: 100%" :src="previewImage" />
    </ns-modal>
    <!-- 预览图片弹窗 /-->
    <!-- 错误消息提示 -->
    <div class="err-msg" v-if="!isJpgOrPngOrJpeg">
      <p>{{ fileName }} 文件上传失败</p>
      <p :style="{ color: 'red' }">请选择{{ fileType.join(',') }}的图片</p>
    </div>
    <div class="err-msg" v-if="isJpgOrPngOrJpeg ? !isLt5M : ''">
      <p>{{ fileName }} 文件上传失败</p>
      <p :style="{ color: 'red' }">请选择{{ maxSize / 1024 / 1024 }}M内的图片</p>
    </div>
    <!-- 错误消息提示 /-->
  </div>
</template>
<script lang="ts">
  import {
    UploadOutlined,
    LoadingOutlined,
    EyeOutlined,
    DeleteOutlined,
  } from '@ant-design/icons-vue';
  import { defineComponent, ref, computed, reactive, watch } from 'vue';
  import { http } from '/nerv-lib/util/http';
  import { NsMessage } from '../../message';
  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) => {
      // console.log(file);
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result);
      reader.onerror = (error) => reject(error);
    });
  }
  export default defineComponent({
    name: 'NsUpload',
    components: {
      UploadOutlined,
      LoadingOutlined,
      DeleteOutlined,
      EyeOutlined,
    },
    props: {
      // 上传的地址
      url: {
        type: String,
        require: true,
      },
      // 上传的图片大小
      maxSize: {
        type: Number,
        default: 5242880,
      },
      // 上传的图片类型
      fileType: {
        type: Array,
        default: () => {
          return ['jpg', 'png', 'jpeg'];
        },
      },
      // 展示图片数量
      count: {
        type: Number,
        default: 1,
      },
      // 是否禁用
      disabled: {
        type: Boolean,
        default: false,
      },
      // 上传文件类型，0-证书，1-图片，2-身份证件
      uploadType: {
        type: Number,
        default: 1,
      },
      baseImageUrl: {
        type: [String, Object],
      },
      compatibilityUuid: {
        type: [String, Object],
      },
      // 图片归类所需
      params: {
        type: [Object],
      },
      // 是否两个都emit
      whetherTwo: {
        type: Boolean,
        default: false,
      },
    },
    emits: ['change'],
    setup(props, { emit }) {
      console.log(props);
      const previewVisible = ref<boolean>(false);
      const isLt5M = ref<boolean>(true);
      const isJpgOrPngOrJpeg = ref<boolean>(true);
      const previewImage = ref<string | undefined>('');
      const fileList = ref<FileItem[]>([]);
      const fileUuid = ref<string>('');
      const uuidList = ref([]);
      const uuidString = ref('');
      const currentImg = ref<string[]>([]);
      const isIntImg = ref(false);
      const spinning = ref(false);
      const filterValue = (value) => {
        if (typeof value == 'object') {
          let arr = [];
          value.forEach((item) => {
            if (item.includes('ParkPic/')) {
              arr.push(item.slice(item.lastIndexOf('/') + 1));
            } else {
              arr.push(item);
            }
          });
          return arr;
        } else {
          let str = '';
          if (value) {
            if (value.includes('ParkPic/')) {
              str = value.slice(value.lastIndexOf('/') + 1);
            } else {
              str = value;
            }
          }

          return str;
        }
      };
      if (props.baseImageUrl) {
        isIntImg.value = true;
        if (typeof props.baseImageUrl == 'object') {
          uuidList.value = props.compatibilityUuid;
          // currentImg.value.concat(props.baseImageUrl);
          props.baseImageUrl.map((item, index) => {
            console.log(item);
            fileList.value.push(item);
            currentImg.value.push(item);
            // previewImage.value = props.baseImageUrl[index];
          });
          // currentImg.value.unshift(...props.baseImageUrl);
          emit(
            'change',
            props.whetherTwo
              ? [filterValue(fileList.value), filterValue(uuidList.value)]
              : filterValue(fileList.value),
          );
        } else {
          console.log(props);

          fileList.value.push({});
          uuidString.value = props.compatibilityUuid;
          fileUuid.value = props.baseImageUrl;
          currentImg.value.unshift(props.baseImageUrl);
          previewImage.value = props.baseImageUrl;
          emit(
            'change',
            props.whetherTwo
              ? [filterValue(fileUuid.value), filterValue(uuidString.value)]
              : filterValue(fileUuid.value),
          );
        }
      }

      const fileName = ref<string | undefined>('');
      const maskShow = ref<boolean[]>([]);
      const acceptType = computed(() =>
        props.fileType.map((item: String) => {
          return 'image/' + item;
        }),
      );
      watch(
        () => props.baseImageUrl,
        (e) => {
          if (e) {
            isIntImg.value = true;
            if (typeof e == 'object') {
              e.map((item, index) => {
                fileList.value.push(item);
                currentImg.value.push(item);
              });
            } else {
              fileList.value.push({});
              currentImg.value.unshift(e);
              previewImage.value = e;
            }
          }
        },
      );
      const beforeUpload = (file: FileItem) => {
        // 上传出错后，下次上传图片前，重置为true，让图片可以上传
        isLt5M.value = true;
        isJpgOrPngOrJpeg.value = true;
        // 限制图片格式,服务器不支持gif图片
        // if (file.type === 'image/gif') {
        //   NsMessage.warn('不支持gif图片');
        //   return false;
        // }
        isJpgOrPngOrJpeg.value = acceptType.value.includes(file.type);
        // 如果大于指定的大小，显示错误信息
        if (file.size > props.maxSize) {
          isLt5M.value = false;
        }
        fileName.value = file.name;
        return isLt5M.value && isJpgOrPngOrJpeg.value;
      };
      const handleChange = ({ fileList: newFileList }: FileInfo) => {
        // 单图上传
        if (props.count === 1) {
          // 删除图片时，newFileList.length = 0
          // 图片大小不符合规范时，!isLt5M.value为true
          if (!isLt5M.value || !isJpgOrPngOrJpeg.value || newFileList.length - 1 < 0) {
            // 让图片不显示，也不上传
            fileList.value = [];
          } else {
            // 添加\更换图片
            // newFileList[newFileList.length - 1]的目的是为了只显示最新一张图片
            fileList.value = [newFileList[newFileList.length - 1]];
          }
        } else {
          // 多图上传
          // if (typeof props.baseImageUrl == 'object') {
          //   props.baseImageUrl.map((item, index) => {
          //     console.log(item);
          //     fileList.value.push(item);
          //     // currentImg.value.unshift(item);
          //     // previewImage.value = props.baseImageUrl[index];
          //   });
          // }
          if (!isLt5M.value || !isJpgOrPngOrJpeg.value) {
            // fileList.value = newFileList.slice(0, newFileList.length - 1);
            // fileList.value = fileList.slice(0, fileList.length - 1);
            // console.log(123444, fileList.value, newFileList);
          } else {
            fileList.value.push(newFileList);
            // uuidList.value.push(newFileList);
            // emit(
            //   'change',
            //   props.whetherTwo
            //     ? [filterValue(fileList.value), filterValue(uuidList.value)]
            //     : filterValue(fileList.value)
            // );
            // fileList.value = newFileList;
          }
        }
      };
      // const fill = (data) => {
      //   let arr = [];
      //   if (props.count == 1) return;
      //   data.map((item) => {
      //     if (item.indexOf('ParkPic') !== -1) {
      //       arr.push(item.split('ParkPic/')[1]);
      //     }
      //   });
      //   return arr;
      // };
      const selfUpload = async ({ file }) => {
        if (props.count !== 1) {
          // emit(
          //   'change',
          //   props.whetherTwo
          //     ? [filterValue(fileList.value), filterValue(uuidList.value)]
          //     : filterValue(fileList.value),
          // );
          currentImg.value.push(await getBase64(file));
        } else {
          currentImg.value = [await getBase64(file)];
        }
        const params = {
          uploadType: props.uploadType,
        };
        const formData = new FormData();
        formData.append('file', file);
        formData.append('uploadType', props.uploadType);
        Object.keys(props.params).map((item) => {
          formData.append(item, props.params[item]);
        });
        //formData.append('uploadType', 1);
        const config = {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
          // params: params,
        };
        // console.log(formData);
        // if (props.count == 1) {
        //   fileUuid.value = 'ceshi';
        // }
        spinning.value = true;
        http
          .post(props.url, formData, config)
          .then((res) => {
            if (props.count > 1) {
              // let imgBox = ref([]);
              // console.log(fileList.value);
              fileList.value.push(res.data.httpUrl);
              if (!uuidList.value) {
                uuidList.value = [];
              }
              uuidList.value.push(res.data.fileUuid);
              // fileList.value.push('/api/parking_merchant/objs/ParkPic/' + res.data.fileUuid);
              fileList.value.forEach((item, index) => {
                if (typeof item == 'object') {
                  fileList.value.splice(index, 1);
                }
              });
              uuidList.value.forEach((item, index) => {
                if (typeof item == 'object') {
                  uuidList.value.splice(index, 1);
                }
              });
              // props.whetherTwo;
              emit(
                'change',
                props.whetherTwo
                  ? [filterValue(fileList.value), filterValue(uuidList.value)]
                  : filterValue(fileList.value),
              );
            } else {
              fileUuid.value = res.data.httpUrl || res.data.picUuid || res.data.fileUuid;
              uuidString.value = res.data.fileUuid;
              emit(
                'change',
                props.whetherTwo
                  ? [filterValue(fileUuid.value), filterValue(uuidString.value)]
                  : filterValue(fileUuid.value),
              );
            }
            spinning.value = false;
          })
          .catch(() => {
            fileList.value.forEach((item, index) => {
              if (typeof item == 'object') {
                fileList.value.splice(fileList.value.length - 1, 1);
              }
            });
            NsMessage.error('上传失败，请重试');
            spinning.value = false;
          });
      };
      const handlePreview = async (item, index: number) => {
        if (props.count > 1) {
          previewImage.value = fileList.value[index];
        } else {
          previewImage.value = fileUuid.value;
        }
        // if (!isIntImg.value) {
        //   previewImage.value = (await getBase64(fileList.value[index])) as string;
        //   // 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);
        uuidList.value && uuidList.value.splice(index, 1);
        uuidString.value = '';
        fileUuid.value = '';
        isIntImg.value = false;
        if (props.count == 1) {
          emit(
            'change',
            props.whetherTwo
              ? [filterValue(fileUuid.value), filterValue(uuidString.value)]
              : filterValue(fileUuid.value),
          );
        } else {
          emit(
            'change',
            props.whetherTwo
              ? [filterValue(fileList.value), filterValue(uuidList.value)]
              : filterValue(fileList.value),
          );
        }
      };
      const handleCancel = () => {
        previewVisible.value = false;
      };
      const mouseEnter = (index: number) => {
        maskShow.value[index] = true;
      };
      const mouseLeave = (index: number) => {
        maskShow.value[index] = false;
      };
      return {
        previewVisible,
        previewImage,
        fileList,
        isLt5M,
        isJpgOrPngOrJpeg,
        fileName,
        currentImg,
        maskShow,
        fileUuid,
        selfUpload,
        handleCancel,
        handlePreview,
        handleChange,
        beforeUpload,
        mouseEnter,
        mouseLeave,
        deleteImg,
        spinning,
      };
    },
  });
</script>
<style lang="less" scoped>
  :deep(.ant-upload-picture-card-wrapper) {
    width: unset !important;
  }
  :deep(.ant-upload-picture-card-wrapper .ant-upload.ant-upload-select-picture-card) {
    margin: 0;
    width: 64px !important;
    height: 64px !important;
    border: 1px solid #d9d9d9;
  }
  :deep(.ant-upload-picture-card-wrapper .ant-upload.ant-upload-select-picture-card:hover) {
    border-color: #d9d9d9;
  }
  :deep(.ant-upload-select-picture-card i) {
    font-size: 32px;
    color: #999;
  }
  :deep(.ant-upload-select-picture-card .ant-upload-text) {
    color: #666;
    font-size: 12px;
  }
  :deep(.ant-upload-picture-card-wrapper .ant-upload-list-picture-card-container) {
    width: 88px;
    height: 64px !important;
  }
  :deep(.ant-upload-picture-card-wrapper .ant-upload-list-picture-card .ant-upload-list-item) {
    margin: 0;
    padding: 0;
    width: 64px !important;
    height: 64px !important;
  }
  .title,
  .err-msg {
    text-align: left;
  }
  .err-msg p {
    margin: 0;
  }
  .container {
    display: flex;
    justify-content: flex-start;
    flex-wrap: wrap;
  }
  .imgList {
    display: flex;
  }
  .imgContainer {
    margin-right: 16px;
    border: 1px solid #d9d9d9;
    position: relative;
    margin-bottom: 8px;
  }
  .imgCover {
    width: 64px;
    height: 64px;
    object-fit: contain;
  }
  .imgContainer .mask {
    position: absolute;
    top: 0;
    left: 0;
    width: 64px !important;
    height: 64px !important;
    background: rgba(0, 0, 0, 0.5);
    text-align: center;
    line-height: 64px !important;
  }
  .mask .anticon-eye {
    color: white;
    margin-right: 18px;
  }
  .mask .anticon-eye:hover {
    color: #00acff;
    margin-right: 18px;
  }
  .mask .anticon-delete {
    color: white;
  }
  .mask .anticon-delete:hover {
    color: #00acff;
  }
</style>
