<template>
  <el-upload
    class="ps-upload-file"
    :action="action"
    :show-file-list="false"
    drag
    :limit="limit"
    :headers="headers"
    :on-exceed="handleExceed"
    :on-success="handleSuccess"
    :on-error="handleError"
    :file-list="currentFileList"
    :on-progress="handleProgress"
    :before-upload="handleBeforeUpload"
    :style="`width: ${this.showWidth}`"
  >
    <i class="el-icon-upload"></i>
    <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
    <p class="upload-tip">{{showFileType}}大小不超过{{this.fileSize}}M，最多可上传{{this.limit}}个</p>
    <div
      class="el-upload__tip"
      slot="tip"
      v-if="isTip"
    >{{errorMsg}}</div>
  </el-upload>
</template>

<script>
export default {
  name: 'PsUploadFile',
  props: {
    limit: {
      type: Number,
      default: 50
    },
    fileSize: {
      type: Number,
      default: 50
    },
    fileType: {
      type: Array,
      default: () => []
    },
    action: {
      type: String,
      default: ''
    },
    headers: {
      type: Object,
      default: () => {}
    },
    width: {
      type: [Number, String],
      default: 380
    },
    successCode: {
      type: String,
      default: '0000'
    },
    fileList: {
      type: Array,
      default: () => []
    },
    isTip: {
      type: Boolean,
      default: false
    }
  },

  data() {
    return {
      errorMsg: null
    }
  },

  computed: {
    // 宽度
    showWidth() {
      if (typeof this.width === 'number') {
        return `${this.width}px`
      }
      return this.width
    },
    // 是否显示提示
    showTip() {
      return this.isShowTip && (this.fileType || this.fileSize)
    },
    // 显示可上传的文件类型
    showFileType() {
      return this.fileType.length ? `支持${this.fileType.join('、')}格式，` : ''
    },
    currentFileList: {
      get() {
        return this.fileList
      },
      set() {}
    }
  },

  methods: {
    handleSuccess(res, file, fileList) {
      if (res.code === this.successCode) {
        this.$emit('change', file, fileList)
        this.$emit('success', res.data, file, fileList)
      } else {
        this.currentFileList = fileList.findIndex(item => item.uid !== file.uid)
        let currentIndex = fileList.findIndex(item => item.uid === file.uid)
        if (res.msg) {
          this.showErrorMsg(res.msg)
        } else {
          this.showErrorMsg('上传失败')
        }
        this.$set(this.fileList[currentIndex], 'status', 'fail')
        this.$emit('change', file, this.fileList)
        this.$emit('error', res, file, this.currentFileList)
      }
    },

    handleError(err, file, fileList) {
      this.$emit('change', file, fileList)
      this.$emit('error', err, file, fileList)
    },
    // 触发上传中
    handleProgress(event, file, fileList) {
      this.$emit('change', file, fileList)
      this.$emit('progress', event, file, fileList)
    },
    // 显示错误信息
    showErrorMsg(msg) {
      this.errorMsg = msg
      if (!this.isTip) {
        this.$message.error(msg)
      }
    },
    // 上传前校检格式和大小
    handleBeforeUpload(file) {
      // 校检文件类型
      if (this.fileType && this.fileType.length) {
        // 获取文件后缀
        let fileExtension
        if (file.name.lastIndexOf('.') > -1) {
          fileExtension = file.name.substring(file.name.lastIndexOf('.') + 1)
        }
        const isTypeOk = this.fileType.some(type => {
          return type === fileExtension
        })
        if (!isTypeOk) {
          this.showErrorMsg(`文件格式不正确，请上传${this.fileType.join('/')}格式文件！`)
          return false
        }
      }
      // 校检文件大小
      if (this.fileSize) {
        // KB
        const fileSize = file.size / 1024 / 1024
        const isLt = fileSize < this.fileSize
        if (!isLt) {
          this.showErrorMsg(`上传文件大小不能超过 ${this.fileSize} M!`)
          return false
        }
      }
      this.$emit('beforeUpload', file)
      return true
    },

    // 文件个数超出限制
    handleExceed() {
      this.showErrorMsg(`上传文件数量不能超过 ${this.limit} 个!`)
    }
  }
}
</script>

<style>
.ps-upload-file .upload-tip {
  margin-top: 8px;
  font-size: 12px;
  color: rgba(153, 153, 153, 1);
  padding: 0 16px;
}
.ps-upload-file .el-upload__text {
  color: rgba(51, 51, 51, 1);
}
.ps-upload-file .el-icon-upload {
  font-size: 36px;
  margin-top: 30px;
  line-height: 1;
}
.ps-upload-file .el-upload-dragger {
  border: none;
  background-color: rgba(248, 250, 252, 1);
  width: 100%;
}
.ps-upload-file .el-upload {
  width: 100%;
}
</style>
