<template>
  <div
    :class="{
      'mobile-upload': fromType === 'mobileFile',
      'file-upload-container': fromType !== 'mobileFile',
    }"
  >
    <el-upload
      ref="elUploadEl"
      :list-type="listType"
      :action="actionUrl"
      :file-list="fileList"
      :headers="header"
      :show-file-list="false"
      :accept="accept"
      :limit="limit"
      :multiple="multiple"
      :drag="dragUpload"
      :on-progress="handleProgress"
      :before-upload="handleBeforeUpload"
      :on-exceed="handleExceed"
      :on-success="handleSuccess"
      :on-error="handleError"
      :with-credentials="withCredentials"
      @drop.native="(e) => beforeUploadHandler(e.dataTransfer.files)"
    >
      <template v-if="fromType === 'mobileFile'">
        <div ref="mobileFile" class="mobile-file-btn">
          <i class="el-icon-paperclip" style="font-size: 18px"></i>
          添加附件
        </div>
      </template>
      <template v-else-if="dragUpload">
        <i class="icon-my-todo-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处，或
          <em>点击上传</em>
        </div>
      </template>
      <template v-else>
        <el-button v-if="!readonly" size="mini" icon="el-icon-upload2">
          {{ uploadButtonName }}
        </el-button>
      </template>
    </el-upload>

    <el-button
      v-if="!readonly && files.length > 0 && fromType != 'mobileFile'"
      v-popconfirm="{ content: '确定要清空吗？', confirm: handleClear }"
      size="mini"
      style="height: 28px"
      icon="el-icon-delete"
    >
      清空
    </el-button>
    <el-button
      v-if="
        !readonly && simplicity && files.length > 0 && fromType != 'mobileFile'
      "
      v-popconfirm="{ content: '确定要批量下载吗？', confirm: handleDownAll }"
      size="mini"
      style="height: 28px"
      icon="icon-xiazai1"
    >
      批量下载
    </el-button>
    <span v-if="!readonly && fromType !== 'mobileFile'" class="tooltip-text">
      {{ acceptLabel }}，不超过{{ size }}MB，最多{{ limit }}个
    </span>

    <slot name="append"></slot>
  </div>
</template>
<script>
  import mobileMode from '@/mixins/mobileMode.js'
  export default {
    name: 'HtFileUpload',
    mixins: [mobileMode],
    props: {
      withCredentials: {
        type: Boolean,
        default: false,
      },
      value: {
        type: Array,
        required: true,
      },
      actionUrl: {
        type: String,
        required: true,
      },
      listType: {
        type: String,
      },
      multiple: {
        type: Boolean,
      },
      simplicity: {
        type: Boolean,
      },
      dragUpload: {
        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,
      },
      onExceed: {
        type: Function,
      },
      onError: {
        type: Function,
      },
      fromType: String, // 移动端附件时特殊展示 mobileFile
      uploadButtonName: {
        type: String,
        default: '上传附件',
      },
    },
    data() {
      return {
        // 用于操作上传的数据
        files: [],
        //element组件upload不能直接修改fileList的值
        fileList: [],
        onces: true, //次数
      }
    },
    computed: {
      acceptLabel: function () {
        return this.accept ? this.accept : '所有格式'
      },
    },
    watch: {
      value: {
        handler(val) {
          if (val && val.length < 1) {
            this.files = []
            this.fileList = []
          } else {
            this.files = val
            // this.fileList = val
          }
        },
        deep: true,
        immediate: true,
      },
    },
    created() {
      this.files = this.value || []
      this.fileList = this.value || []
    },
    methods: {
      reload(files) {
        this.files = files
        this.fileList = files
      },
      // 附件是否超过最大尺寸
      exceedFileSize(file) {
        return file.size > this.size * 1024 * 1024
      },
      beforeUploadHandler(fileList) {
        //拖拽+类型限制 会导致校验不了
        if (!this.accept) return
        //当是单选时 只拿第一个
        if (!this.multiple && fileList.length > 0) {
          fileList.length > 1 &&
            this.messageToast('warning', `每次最多上传1个附件.`)
          this.handleBeforeUpload(fileList[0])
          return
        }
        //多选时
        // 判断是否超过最大上传数  当前选择的文件数+当前已上传的文件数
        if (
          this.limit &&
          this.limit >= fileList.length + this.fileList.length
        ) {
          for (let item of fileList) {
            this.handleBeforeUpload(item)
          }
        }
      },
      handleBeforeUpload(file) {
        let resultVal = false
        if (this.exceedFileSize(file)) {
          let computerSize = this.$options.filters['computerSize'](file.size)
          this.onces &&
            this.messageToast(
              'warning',
              `附件的大小为${computerSize}，超过了允许的最大尺寸${this.size}MB.`
            )
          // this.onces = false
          setTimeout(() => {
            this.onces = true
          }, 1500)
          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) {
        if (this.onExceed && this.onExceed.constructor == Function) {
          this.onExceed(files, fileList)
        } else {
          this.messageToast('warning', `最多允许上传${this.limit}个附件.`)
        }
      },
      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', err, file, fileList)
        const index = this.files.findIndex((m) => m === file)
        file.state = 'exception'
        index > -1 && this.$set(this.files, index, file)
        this.messageToast('error', `附件${file.name}上传失败.`, () => {
          this.files.remove(file)
        })
      },
      handleClear() {
        this.files.forEach((m) => {
          this.abort(m)
        })
        this.$refs.elUploadEl.clearFiles()
        this.files = []
        this.$emit('clear')
      },
      handleDownAll() {
        this.$emit('downloadAll', this.fileList)
      },
      abort(file) {
        // 附件还在上传中，则中止上传。
        if (file && file.status === 'uploading') {
          this.$refs.elUploadEl.abort(file)
        }
        // 单个删除文件后，需主动触发删除，否则会有limit限制上传个数bug
        const index = this.$refs.elUploadEl.uploadFiles.findIndex(
          (e) => e.uid === file.uid
        )
        if (index > -1) {
          this.$refs.elUploadEl.uploadFiles.splice(index, 1)
        }
      },
      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) //删除数组某一项
          }
        }
      },
      messageToast(type, message, onClose) {
        if (this.isMobile && type === 'error') {
          type = 'danger'
        }
        return this.isMobile
          ? this.$notify({ type: type, message, onClose })
          : this.$message({ type: type, message: message, onClose: onClose })
      },
    },
  }
</script>
<style lang="scss" scoped>
  .el-upload {
    display: inline;
    text-align: center;
    cursor: pointer;
    outline: none;
  }

  .file-upload-container {
    margin-bottom: 4px;
    .tooltip-text {
      margin-top: 8px;
      margin-left: 0;
      line-height: 1;
    }
  }

  div.file-upload-container > div {
    display: inline-block;
    margin-right: 10px;
  }
  .mobile-upload {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    .mobile-upload_label {
      color: #262626;
      font-size: 14px;
    }
    .mobile-file-btn {
      font-size: 14px;
      color: #409eff;
      position: absolute;
      top: 10px;
      right: 0;
    }
  }
  .tooltip-text {
    font-size: 12px;
    color: #8c8c8c;
    margin-left: 8px;
    display: block;
    word-break: break-all;
    white-space: normal;
  }
  div {
    ::v-deep .el-upload .el-upload-dragger {
      width: 212px;
      height: 62px;
      background: #f9f9f9;
      border-radius: 4px 4px 4px 4px;
      opacity: 1;
      border: 1px dashed #dcdee0;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      .el-upload__text {
        font-size: 12px;
        line-height: 22px;
        em {
          color: var(--themeColor);
        }
      }
      &:hover {
        border: 1px solid var(--themeColor);
        background: #fff;
      }
    }
  }

  .icon-my-todo-upload {
    font-size: 21px;
  }
</style>
