<template>
  <div class="file-upload-container">
    <el-upload
      ref="elUploadEl"
      :action="actionUrl"
      :file-list="files"
      :headers="header"
      :show-file-list="false"
      :accept="accept"
      :limit="limit"
      :multiple="multiple"
      :before-upload="handleBeforeUpload"
      :on-progress="handleProgress"
      :on-exceed="handleExceed"
      :on-success="handleSuccess"
      :on-error="handleError"
      :with-credentials="withCredentials"
      :auto-upload="autoUpload"
      :http-request="httpRequest"
    >
      <el-tooltip placement="top" effect="light">
        <div slot="content">
          <span>附件格式支持：{{ acceptLabel }}</span>
          <br />
          <span>附件大小限制：单个文件不超过{{ size }}MB</span>
          <br />
          <span>附件个数限制：最多{{ limit }}个</span>
        </div>
        <el-button size="mini" round icon="el-icon-plus" v-if="!readonly"
          >上传</el-button
        >
      </el-tooltip>
    </el-upload>
    <el-button
      size="mini"
      round
      icon="el-icon-delete"
      @click="handleClear"
      v-if="!readonly && files.length > 0"
      >清空</el-button
    >
    <slot name="append"></slot>
  </div>
</template>
<script>
import utils from "@/utils.js";
import { setTimeout } from "timers";
export default {
  name: "file-upload",
  props: {
    withCredentials: {
      type: Boolean,
      default: false
    },
    value: {
      type: Array,
      required: true
    },
    actionUrl: {
      type: String,
      required: true
    },
    multiple: {
      type: Boolean
    },
    accept: {
      type: String
    },
    limit: {
      type: Number,
      default: 5
    },
    header: {
      type: Object
    },
    size: {
      type: Number,
      default: 50
    },
    readonly: {
      type: Boolean,
      default: false
    },
    beforeUpload: {
      type: Function
    },
    onSuccess: {
      type: Function
    },
    onError: {
      type: Function
    },
    autoUpload: {
      type: Boolean,
      default: true
    },
    httpRequest: {
      type: Function
    }
  },
  data() {
    return {
      files: []
    };
  },
  watch: {
    files: function(newVal) {
      if (newVal && newVal.constructor === Array) {
        let ary = [];
        newVal.forEach((m) => {
          if (m && m.constructor === Object) {
            ary.push(m);
          } else if (m && m.constructor === File) {
            var name = m.name;
            var index = name.lastIndexOf(".");
            var type = name.substring(index + 1, name.length);
            ary.push({
              name: name,
              size: m.size,
              percentage: m.percentage,
              status: m.status,
              state: m.state,
              response: m.response,
              type: type,
              uid: m.uid,
            });
          }
        });
        this.$emit("input", ary);
      }
    },
  },
  computed: {
    acceptLabel: function() {
      return this.accept ? this.accept : "所有格式";
    },
  },
  created() {
    this.files = this.value || [];
  },
  methods: {
    // 附件是否超过最大尺寸
    exceedFileSize(file) {
      return file.size > this.size * 1024 * 1024;
    },
    handleBeforeUpload(file) {
      let resultVal = false;
      if (this.exceedFileSize(file)) {
        let computerSize = this.$options.filters["computerSize"](file.size);
        this.$message({
          message: `附件的大小为${computerSize}，超过了允许的最大尺寸${this.size}MB.`,
          type: "warning",
        });
        resultVal = false;
      } else {
        resultVal = true;
      }

      if (
        this.beforeUpload &&
        this.beforeUpload.constructor == Function &&
        resultVal
      ) {
        resultVal = this.beforeUpload(file);
      }

      if (resultVal) {
        this.files.push(file);
      }

      return resultVal;
    },
    handleProgress(event, file, fileList) {
      const index = this.files.findIndex((m) => m === file);
      index > -1 && this.$set(this.files, index, file);
      this.$emit("on-progress", event, file, fileList);
    },
    handleExceed(files, fileList) {
      this.$message({
        message: `最多允许上传${this.limit}个附件.`,
        type: "warning",
      });
    },
    handleSuccess(response, file, fileList) {
      if (this.onSuccess && this.onSuccess.constructor == Function) {
        this.onSuccess(response, file, fileList);
      }
      const index = this.files.findIndex((m) => m === file);
      file.state = "success";
      index > -1 && this.$set(this.files, index, file);
    },
    handleError(err, file, fileList) {
      if (this.onError && this.onError.constructor == Function) {
        this.onError(err, file, fileList);
      }
      this.$emit("handle-error");
      const index = this.files.findIndex((m) => m === file);
      file.state = "exception";
      index > -1 && this.$set(this.files, index, file);
      this.$message({
        message: `附件${file.name}上传失败.`,
        type: "error",
        onClose: () => {
          this.files.remove(file);
        },
      });
    },
    handleClear() {
      this.$confirm("确定清空所有附件?").then(() => {
        this.files.forEach((m) => {
          this.abort(m);
        });
        this.$refs.elUploadEl.clearFiles();
        this.files = [];
      });
    },
    abort(file) {
      // 附件还在上传中，则中止上传。
      if (file && file.status === "uploading") {
        this.$refs.elUploadEl.abort(file);
      }
    },
    remove(file) {
      this.abort(file);
      this.files.remove(file);
      for (var i = 0; i < this.files.length; i++) {
        if (this.files[i].uid == file.uid) {
          this.files.splice(i, 1); //删除数组某一项
        }
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.el-upload {
  display: inline;
  text-align: center;
  cursor: pointer;
  outline: none;
}

div.file-upload-container > div {
  display: inline-block;
  margin-right: 10px;
}
</style>
