<template>
  <div class="upload-box">
    <div v-for="(item, index) in fileList" class="items">
      <img v-if="item.filePath" :src="item.filePath"
        class="upload-image" />
      <div class="upload-handle" @click.stop>
        <div class="handle-icon" @click="handleEdit(index)" v-if="!self_disabled">
          <el-icon :size="props.iconSize">
            <Edit />
          </el-icon>
        </div>
        <div class="handle-icon" @click="onPreview(index)">
          <el-icon :size="props.iconSize">
            <ZoomIn />
          </el-icon>
        </div>
        <div class="handle-icon" @click="handleRemove(index)" v-if="!self_disabled">
          <el-icon :size="props.iconSize">
            <Delete />
          </el-icon>
        </div>
      </div>
    </div>
    <el-upload action="#" :id="uuid" class="upload-demo my-upload-images"
      :class="fileList.length > 0 && !loading ? 'success-file' : ''" :multiple="multiple" ref="uploadRef"
      :disabled="loading ? true : (self_disabled || fileList.length >= props.limit)" :http-request="handleHttpUpload"
      :before-upload="beforeUpload" list-type="picture-card" :limit="limit" :file-list="fileList"
      :show-file-list="false" v-if="!self_disabled" :on-exceed="onExceed" :accept="props.fileType">
      <el-icon v-if="!loading">
        <Plus />
      </el-icon>
      <el-progress type="circle" v-else :percentage="progress"></el-progress>
    </el-upload>
  </div>
</template>

<script setup lang="ts">
import { computed,ref } from "vue";
import { ElNotification, UploadFile, UploadInstance } from "element-plus";
import type { UploadProps, UploadRequestOptions } from "element-plus";
import { Plus } from '@element-plus/icons-vue'
import { generateUUID } from "@/utils/auth";

const uploadRef = ref<UploadInstance>();
import {upload} from '@/api/common'

// 接受父组件参数
const props = defineProps({
  zIndex: {
    default: -1
  },
  multiple: {
    type: Boolean,
    default: false
  },
  btnTip: {
    type: String,
    default: ''
  },
  limit: {
    type: Number,
    default: undefined
  },
  width: {
    type: String,
    default: '150px'
  },
  height: {
    type: String,
    default: '150px'
  },
  borderRadius: {
    type: String,
    default: '8px'
  },
  fileList: {
    type: Array,
    required: true,
    default: []
  },
  disabled: {
    default: false
  },
  fileSize: {
    default: 200
  },
  orderNo: {
    default: ''
  },
  fileType: {
    default: ""
  },
  name: {
    default: ""
  }
});
// 生成组件唯一id
const uuid = ref("id-" + generateUUID());

// 判断是否禁用上传和删除
const self_disabled = computed(() => {
  return props.disabled;
});
let editIndex = ''

const emit = defineEmits(["upload"]);
const progress = ref(0)
const loading = ref(false);
const handleHttpUpload = async (options: UploadRequestOptions) => {
  loading.value = true;
  try {
    const formData = new FormData()
    formData.append('file',options.file)
    formData.append('name',props.name)
    const res =await upload(formData)
    if (props.multiple) {
      let list = JSON.parse(JSON.stringify(props.fileList))
      if (editIndex !== '') {
        list.splice(editIndex, 1, {
          url: res.fileUrl,
          name: res.originalName,
          filePath:  res.fileUrl,
          fileName: res.originalName
        })
        editIndex = ''
      } else {
        list.push({
          url: res.fileUrl,
          name: res.originalName,
          filePath:  res.fileUrl,
          fileName: res.originalName
        })
      }
      emit('upload', list,props.zIndex)
    } else {
      emit("upload", res, props.zIndex);
    }
  } catch (error) {
    ElNotification({
      title: "温馨提示",
      message: "上传文件失败！",
      type: "error"
    });
    if (props.multiple) {
      emit('upload', props.fileList,props.zIndex)
    } else {
      uploadRef.value!.clearFiles();
      emit("upload", "", props.zIndex);
    }
    options.onError(error as any);
  } finally {
    progress.value = 0
    loading.value = false;
  }
};

const onPreview = (index: any) => {
  window.open(props.fileList[index].filePath)
}

const handleEdit = (index: any) => {
  editIndex = index
  const dom = document.querySelector(`#${uuid.value} .el-upload__input`);
  dom && dom.dispatchEvent(new MouseEvent('click'));
}
const handleRemove = (index: any) => {
  editIndex = index
  if (props.multiple) {
    emit("upload", props.fileList.filter((f, i) => !(editIndex == i)),props.zIndex)
  } else {
    uploadRef.value!.clearFiles();
    emit("upload", "" ,props.zIndex);
  }
};

const onExceed = () => {
  if (props.limit) {
    ElNotification({
      title: "温馨提示",
      message: `最多支持上传${props.limit}张`,
      type: "warning"
    });
  }
};


/**
 * @description 文件上传之前判断
 * @param rawFile 选择的文件
 * */
const beforeUpload: UploadProps["beforeUpload"] = (rawFile) => {
  const imgSize = rawFile.size / 1024 / 1024 < props.fileSize;
  if (!imgSize) {
    ElNotification({
      title: "温馨提示",
      message: `上传文件大小不能超过 ${props.fileSize}M！`,
      type: "warning"
    });
    return false;
  }
  if (props.fileType) {
    let fileType = props.fileType.replace(/\s/g, "");
    fileType.split('.').join('|')
    let fileIndex = rawFile.name.lastIndexOf('.')
    let substrName = rawFile.name.substr(fileIndex)
    if (fileType.indexOf(substrName) == -1) {
      ElNotification({
        title: "温馨提示",
        message: "上传文件不符合所需的格式！",
        type: "warning"
      });
      return false;
    }
  }
  return true;
};


</script>
<style scoped lang="scss">
.success-file {
  .el-upload {
    .el-upload-dragger {
      border-width: 3px;
      border-color: var(--el-color-success) !important;
    }
  }
}

.my-upload-images {
  .el-upload-dragger {
    padding: var(--el-upload-dragger-padding-vertical);
  }

  .el-upload-list__item.is-success.el-list-leave-active.el-list-leave-to {
    display: none;
  }

  .el-icon--close-tip {
    display: none !important;
  }
}

.el-form-item.is-error {
  .el-upload-dragger {
    border-width: 3px;
    border-color: var(--el-color-error) !important;
  }
}

::v-deep .el-upload-list__item {
  transition: none !important;
}

.upload-box {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  >div {
    margin-right: 10px;
    margin-bottom: 10px;
    position: relative;

    &.items {
      width: v-bind(width);
      height: v-bind(height);
      border: 1px dashed var(--el-border-color-darker);
      border-radius: v-bind(borderRadius);
    }

    &:hover {
      .upload-handle {
        opacity: 1;
      }
    }
  }

  .upload-image {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }

  .upload-handle {
    position: absolute;
    top: 0;
    right: 0;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    cursor: pointer;
    background: rgb(0 0 0 / 60%);
    opacity: 0;
    transition: var(--el-transition-duration-fast);

    .handle-icon {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 0 6%;
      color: aliceblue;

      .el-icon {
        margin-bottom: 40%;
        font-size: 130%;
        line-height: 130%;
      }

      span {
        font-size: 85%;
        line-height: 85%;
      }
    }
  }
}
</style>
