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

    <!-- 图片查看 -->
    <el-image-viewer
      v-if="preview"
      :appendToBody="false"
      :on-close="closePreview"
      :url-list="filepaths"
    />
    <!-- 视频\音频预览 -->
    <div class="preview-box" 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
        controls
      ></audio>
      <i class="el-icon-circle-close" @click="show = false"></i>
    </div>
  </div>
</template>

<script>
import ElImageViewer from "element-ui/packages/image/src/image-viewer";
import { mapGetters } from "vuex";
export default {
  name: "YUpload",
  model: {
    prop: "value",
    event: "success",
  },
  components: {
    ElImageViewer,
  },
  props: {
    name: {
      type: String,
      default: "file",
    },
    listType: {
      type: String,
      default: "text",
    },
    fileList: {
      type: Array,
      default: () => [],
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    value: {
      required: true,
      type: [String, Array],
      default: "",
    },
    headers: {
      type: Object,
      default: () => {},
    },
    // 文件限制
    accept: {
      type: String,
      default: "",
    },
    // 上传数量
    limit: {
      type: Number,
      validator: (value) => {
        return value >= 0;
      },
      default: 1, // 0为不限制
    },
    // 上传文件大小限制mb 0为不限制
    maxSize: {
      type: Number,
      validator: (value) => {
        return value >= 0;
      },
      default: 10,
    },
    action: {
      type: String,
      default: "/fm/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",
        "m4a",
        "m4r",
        "m4p",
        "m4b",
      ],
      // 图片预览
      filepaths: [],
      preview: false,
      previewData: {
        type: "",
        url: "",
      },

      show: false,
    };
  },
  watch: {
    fileList: {
      handler(newValue) {
        this.initFileList(newValue);
      },
      deep: true,
      immediate: true,
    },
  },

  computed: {
    ...mapGetters(["token"]),
    Headers() {
      let form = {
        Authorization: this.token,
      };
      return {
        ...form,
        ...this.headers,
      };
    },
  },

  created() {},

  methods: {
    // 初始化文件列表
    initFileList(fileList) {
      this.FileList = fileList.map((v) => {
        return {
          uid: v.url,
          name: v.name,
          url: v.url,
          status: "success",
        };
      });
    },
    // 上传成功
    handleSuccess(response, file, fileList) {
      if (this.limit) {
        fileList = fileList.slice(-this.limit);
      }
      // 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);
        }
        fileList = fileList.map((v) => {
          if (v.response) {
            v.url = v.response.url;
          }
          return v;
        });

        let value;
        if (Array.isArray(this.value)) {
          value = fileList.map((v) => v.url);
        } else {
          value = fileList.map((v) => v.url).join(",");
        }
        this.$emit("success", value);
        this.$emit("change", { 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("success", value);
      this.$emit("change", { 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.maxSize) {
          isExceed = file.size / 1024 / 1024 <= this.maxSize;
        }
        if (!isExceed) {
          this.$message.error(`文件大小不能超过${this.maxSize}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);
      }
    },
    // 超出上传数量提示
    handleExceed() {
      this.$message.warning(
        `文件数量超出限制，当前限制为 ${this.limit} 个文件`
      );
    },
    closePreview() {
      this.preview = false;
      this.filepaths = [];
    },
    clearFiles() {
      this.$refs.upload.clearFiles();
    },
    abort() {
      this.$refs.upload.abort(...arguments);
    },
    submit() {
      this.$refs.upload.submit();
    },
  },
  beforeDestroy() {
    this.$refs.upload.clearFiles();
  },
};
</script>

<style lang="less" scoped>
.preview-box {
  width: 100%;
  height: 100%;
  position: fixed;
  left: 0px;
  top: 0px;
  z-index: 999;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 15px;
  .el-icon-circle-close {
    font-size: 40px;
    color: #fff;
    cursor: pointer;
  }
}
</style>
