<template>
    <div v-loading="isUploading" element-loading-text="上传中..." class="upload-loading-wrapper">
      <el-upload ref="uploadRef" v-model:file-list="fileList" action="*" :on-preview="handlePictureCardPreview"
        v-bind="options" :http-request="handleHttpRequest" :on-change="handleChange"
        :class="isMaxCount ? 'max-count' : ''" style="width: 100%">
        <el-icon v-show="['image', 'images'].includes(type)">
          <Plus />
        </el-icon>
        <div v-show="['file', 'files', 'video', 'videos'].includes(type)">
          <el-icon class="el-icon--upload">
            <upload-filled />
          </el-icon>
          <div class="el-upload__text">拖拽到这里或者 <em>点击上传</em></div>
        </div>
      </el-upload>
      <el-button v-show="showUploadButton" type="primary" @click="handleUpload">上传</el-button>
    </div>
  </template>
  
  <script lang="ts" setup>
  import {
    computed,
    ref,
    createVNode,
    render,
  } from "vue";
  import { Plus } from "@element-plus/icons-vue";
  import type { UploadFile, UploadFiles, UploadUserFile } from "element-plus";
  import { ElImageViewer } from "element-plus";
  import utils from "lib/utils";
  
  interface Props {
    value: {
      data?: FormData;
      uid?: string;
      url: string;
      name?: string;
      id?: string;
    }[];
    uploadFile: (file: FormData) => Promise<any>;
    type?: "image" | "images" | "file" | "files" | "video" | "videos";
    transport?: string;
    accept?: string;
  }
  
  const props = withDefaults(defineProps<Props>(), {
    type: "image",
    transport: "",
    accept: "*",
    value: [] as any,
    uploadFile: () => Promise.resolve({ url: "" }),
  });
  
  const showUploadButton = computed(() => {
    return options.value.autoUpload === false;
  });
  
  const emit = defineEmits(["updateValue"])
  
  const fileList = ref<UploadUserFile[]>([...props.value] as any);
  const uploadRef = ref<any>(null);
  const options = computed(() => {
    switch (props.type) {
      case "image":
        return {
          limit: 1,
          listType: "picture-card" as const, // 明确指定为字面量类型
          accept: "image/*",
        };
      case "images":
        return {
          limit: 9,
          listType: "picture-card" as const, // 明确指定为字面量类型
          accept: "image/*",
          multiple: true,
          autoUpload: false,
        };
      case "video":
        return {
          limit: 1,
          listType: "text" as const, // 明确指定为字面量类型
          accept: "video/*",
        };
      case "videos":
        return {
          limit: 9,
          listType: "text" as const, // 明确指定为字面量类型
          accept: "video/*",
          multiple: true,
          autoUpload: false,
        };
      case "file":
        return {
          limit: 1,
          accept: props.accept,
          drag: true,
          listType: "text" as const, // 为文件类型添加合适的 listType
        };
      case "files":
        return {
          limit: 10,
          accept: props.accept,
          drag: true,
          listType: "text" as const, // 为文件类型添加合适的 listType
          multiple: true,
          autoUpload: false,
        };
      default:
        return {
          limit: 1,
          listType: "picture-card" as const,
          accept: props.accept,
        };
    }
  });
  
  const isMaxCount = computed(() => {
    return fileList.value.length >= options.value.limit;
  });
  
  const isUploading = ref(false);

  
  interface UploadRequestOptions {
    file: File & { uid?: number; raw?: File, url?: string };
    filename: string;
    onSuccess: (res: any) => void;
    onError: (err: any) => void;
  }
  
  const handleHttpRequest = async (options: UploadRequestOptions) => {
    isUploading.value = true;
    const formData = new FormData();
    const rawFile = options.file?.raw ?? options.file;
    formData.append(options.filename || "file", rawFile, rawFile.name);
    try {
      const res = await props.uploadFile(formData);
      const url = res?.data?.url ?? res?.url;
      if (url) {
        options.file.url = url;
      }
      options.onSuccess(res);
      isUploading.value = false;
    } catch (err) {
      console.log('err', err)
      options.onError(err as any);
      isUploading.value = false;
    }
  };
  
  const handleRemove = async (uploadFile: UploadFile) => {
    // props.onFileChange(uploadFile);
    // emit("onUpdateValue", fileList.value.filter((f: any) => f.uid !== uploadFile.uid));
  };
  
  const handleChange = (file: any, list: any) => {
    const updateList = fileList.value
      .filter((f: any) => f.status === 'success')
      .map((f: any) => {
        return {
          url: f.raw?.url,
          uid: f.raw?.uid,
          name: f.raw?.name,
          id: f.raw?.id,
        }
      })
    emit("updateValue", updateList);
  }
  
  
  const handlePictureCardPreview = (file: any) => {
    const imageUrl = file.url;
    if (["file", "files"].includes(props.type)) {
      // 下载文件
  
      utils.downloadfile(imageUrl, imageUrl, "image/png");
      return;
    }
    // 如果是视频，打开标签页
    if (["video", "videos"].includes(props.type)) {
      window.open(imageUrl, "_blank");
      return;
    }
    if (!imageUrl) return;
  
    // 创建一个用于挂载 el-image-viewer 的容器
    const container = document.createElement("div");
    const parentNode =
      document.querySelector(props.transport || "body") || document.body;
    parentNode.appendChild(container);
    // 创建并挂载 el-image-viewer 节点
    const vnode = createVNode(ElImageViewer as any, {
      urlList: [imageUrl],
      onClose: () => {
        render(null, container);
        parentNode.removeChild(container);
      },
    });
  
    render(vnode, container);
  };
  
  const handleUpload = () => {
    uploadRef.value.submit();
  };
  </script>
  
  <style lang="less" scoped>
  .upload-loading-wrapper {
    position: relative;
    min-height: 100px;
  }
  
  :deep(.el-upload--picture-card) {
    --el-upload-picture-card-size: 100px;
  }
  
  :deep(.el-upload-list--picture-card) {
    --el-upload-list-picture-card-size: 100px;
  }
  
  :deep(.el-icon--close-tip) {
    display: none !important;
  }
  
  // 设置上传中进度条的大小
  :deep(.el-upload-list__item.is-uploading .el-progress) {
    .el-progress-circle {
      transform: scale(0.7);
    }
  }
  
  .max-count {
    :deep(.el-upload--picture-card) {
      display: none;
    }
  
    :deep(.el-upload) {
      display: none;
    }
  }
  
  :deep(.el-upload.el-upload--text) {
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    width: 100%;
    min-height: 100px;
  
    &>div {
      display: flex;
      flex-direction: column;
      align-items: center;
  
      .el-icon.el-icon--upload {
        font-size: 20px;
      }
    }
  }
  </style>
  