<template>
  <div>
    <el-upload
      v-if="listType === 'picture' || listType === 'text'"
      :name="name"
      :list-type="listType"
      :action="action"
      :multiple="multiple"
      :accept="accept"
      :file-list="FileList"
      v-bind="$attrs"
      v-on="$listeners"
      :before-upload="beforeUpload"
      :on-preview="handlePreview"
      :on-success="handleSuccess"
      :on-remove="handleRemove"
    >
      <slot>
        <el-button size="small" type="primary">点击上传</el-button>
      </slot>
    </el-upload>
    <el-upload
      v-else
      :name="name"
      :list-type="listType"
      :action="action"
      :multiple="multiple"
      :accept="accept"
      :file-list="FileList"
      v-bind="$attrs"
      v-on="$listeners"
      :before-upload="beforeUpload"
      :on-preview="handlePreview"
      :on-success="handleSuccess"
      :on-remove="handleRemove"
    >
      <slot>
        <i class="el-icon-plus"></i>
      </slot>
    </el-upload>

    <!-- 图片查看 -->
    <el-image-viewer
      v-if="preview"
      :appendToBody="false"
      :on-close="
        () => {
          (preview = false), (filepaths = []);
        }
      "
      :url-list="filepaths"
    />
    <!-- 视频预览 -->
    <div
      class="fixed left-0 top-0 z-[999] flex h-full w-full flex-col items-center justify-center gap-2 bg-[rgba(0,0,0,.5)]"
      v-if="show"
    >
      <video
        v-if="previewData.type === 'video'"
        class="h-[400px]"
        :src="previewData.url"
        autoplay
        muted
        controls
      ></video>
      <audio
        v-else-if="previewData.type === 'audio'"
        :src="previewData.url"
        autoplay
        muted
        controls
      ></audio>
      <i
        class="el-icon-circle-close cursor-pointer text-[40px] text-white"
        @click.self="show = false"
      ></i>
    </div>
  </div>
</template>

<script>
export default {
  name: "YUpload",
  model: {
    prop: "value",
    event: "change",
  },
  components: {},
  props: {
    name: {
      type: String,
      default: "file",
    },
    listType: {
      type: String,
      default: "text",
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    value: {
      required: true,
      type: [String, Array],
      default: "",
    },
    // 文件限制
    accept: {
      type: String,
      default: "",
    },
    // 上传数量
    limit: {
      type: Number,
      validator: (value) => {
        return value >= 0;
      },
      default: 1, // 0为不限制
    },
    // 上传文件大小限制mb 0为不限制
    MB: {
      type: Number,
      validator: (value) => {
        return value >= 0;
      },
      default: 10,
    },
    action: {
      type: String,
      default: "/bill/file/commonupload",
    },
  },

  data() {
    return {
      FileList: [],
      imageType: ["png", "jpg", "jpeg", "gif", "svg"],
      videoType: ["mp4", "avi", "wmv", "rmvb", "flv", "mkv"],
      audioType: [
        "mp3",
        "wav",
        "amr",
        "aac",
        "ogg",
        "wma",
        "flac",
        "ape",
        "mid",
        "wav",
        "wma",
        "mp3",
        "m4a",
        "m4r",
        "m4p",
        "m4b",
        "wma",
        "wav",
        "wma",
        "wma",
      ],
      // 图片预览
      filepaths: [],
      preview: false,
      previewData: {
        type: "",
        url: "",
      },

      show: false,
    };
  },
  watch: {
    value: {
      handler(newValue) {
        if (newValue) {
          if (Array.isArray(newValue)) {
            this.FileList = newValue.map((v) => {
              let index = v.lastIndexOf("/");
              let name = v.slice(index + 1);
              return {
                name,
                url: v,
              };
            });
          } else {
            this.FileList = newValue.split(",").map((v) => {
              let index = v.lastIndexOf("/");
              let name = v.slice(index + 1);
              return {
                name,
                url: v,
              };
            });
          }
        } else {
          this.FileList = [];
        }
      },
      deep: true,
      immediate: true,
    },
  },

  computed: {},

  created() {},

  methods: {
    handleSuccess(response, file, fileList) {
      this.FileList = [...fileList];
      if (file.status == "success") {
        if (file.response && file.response.code === -1) {
          let msg = file.response.msg || "上传失败";
          this.$message.error(msg);
          fileList = fileList.filter((file) => file.response.code !== -1);
        }
        if (this.limit) {
          this.FileList = [...fileList].slice(-this.limit);
        }
        this.FileList = this.FileList.map((v) => {
          if (v.response) {
            v.url = v.response.url;
          }
          return v;
        });

        let value;
        if (Array.isArray(this.value)) {
          value = this.FileList.map((v) => v.url);
        } else {
          value = this.FileList.map((v) => v.url).join(",");
        }
        this.$emit("change", value);
        this.$emit("success", { file, fileList });
      }
    },
    handleRemove(file, fileList) {
      let value;
      if (Array.isArray(this.value)) {
        value = fileList.map((v) => v.url);
      } else {
        value = fileList.map((v) => v.url).join(",");
      }
      this.$emit("change", value);
      this.$emit("success", { file, fileList });
    },
    beforeUpload(file) {
      let isType = true;
      let isExceed = true;
      return new Promise((resolve, reject) => {
        if (this.accept) {
          const fileType = this.accept.split(","); // 限制文件类型
          let index = file.name.lastIndexOf(".");
          let type = file.name.slice(index);
          isType = fileType.includes(type);
        }
        if (!isType) {
          let msg = this.accept.replaceAll(",", "或者");
          this.$message.error(`请上传${msg}文件!`);
        }

        if (this.MB) {
          isExceed = file.size / 1024 / 1024 <= this.MB;
        }
        if (!isExceed) {
          this.$message.error(`文件大小不能超过${this.MB}MB!`);
        }
        if (isType && isExceed) {
          resolve(file);
        } else {
          reject();
        }
      });
    },
    // 预览
    handlePreview(file) {
      let { url } = file;
      if (!url) return;
      let index = url.lastIndexOf(".");
      let type = url.slice(index + 1);
      if (this.imageType.includes(type)) {
        this.filepaths = [url];
        this.preview = true;
      } else if (this.videoType.includes(type)) {
        this.previewData.type = "video";
        this.previewData.url = url;
        this.show = true;
      } else if (this.audioType.includes(type)) {
        this.previewData.type = "audio";
        this.previewData.url = url;
        this.show = true;
      } else {
        let a = document.createElement("a");
        a.href = url;
        a.download = file.name;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      }
    },
  },
};
</script>

<style lang="less" scoped></style>