
<!--上传文件列表-->
<template>
  <div>
    <el-button size="small" type="primary" plain icon="el-icon-upload2" @click="$refs.uploadRef.onClick()">上传文件</el-button>
    <upload-file
      v-show="false"
      ref="uploadRef"
      class="ml10"
      style="display: inline-block"
      button-icon="el-icon-upload2"
      :button-plain="false"
      :accept="accept"
      :button-size="'small'"
      :multiple="true"
      button-name="上传文件"
      :before-upload="beforeUpload"
      :http-request="handleUploadFile"
    />
    <slot name="upload-tips" />
    <el-table
      class="table-header-bg table-border mt10"
      size="small"
      :data="showFileList"
      :height="300"
    >
      <el-table-column
        :label="`进行中` + (showFileList && showFileList.length > 0 ? `（${successCount}/${showFileList.length}）` : '')"
        prop="fileFullName"
      >
        <template slot-scope="{ row }">
          <p>{{ row.file.name }}</p>
          <el-progress v-show="row.status==='uploading'" style="width: 100%" :percentage="row.progressPercent" />
        </template>
      </el-table-column>
      <el-table-column :width="180">
        <template slot-scope="{ row }">
          <el-tag v-if="row.status==='success'">上传成功</el-tag>
          <el-tag v-else-if="row.status==='error'" type="danger">上传失败 {{ `${row.errorMsg}` }}</el-tag>
          <el-tag v-else-if="row.status === 'uploading'" type="warning">上传中</el-tag>
          <el-tag v-else>待上传</el-tag>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        :width="80"
        label="操作"
      >
        <template slot="header">
          <el-popconfirm
            v-show="showFileList &&showFileList.length > 0"
            icon="el-icon-info"
            icon-color="red"
            title="确认取消全部上传吗？"
            @confirm="handleBatchRemove"
          >
            <el-button slot="reference" size="small" type="text" class="text-danger">全部取消</el-button>
          </el-popconfirm>
        </template>
        <template slot-scope="{ row, $index }">
          <el-popconfirm
            icon="el-icon-info"
            icon-color="red"
            title="确认取消上传吗？"
            @confirm="handleRemove(row, $index)"
          >
            <i slot="reference" class="el-icon-circle-close text-danger" />
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
import UploadFile from './UploadFile.vue'
import Define from '@/utils/dict/Define'
import { uploadFile } from '@/api/upload'
import axios from 'axios'
import { removeFile } from '@/api/file'
import { Message } from 'element-ui'

let source = axios.CancelToken.source()
const { VIDEO, WORD, PNG, AUDIO, TAGS, EXCEL, PPT, PDF, TXT } = Define.FILE
export default {
  components: { UploadFile },
  props: {
    fileSizeLimit: {
      type: Number,
      default: 500000000
    },
    showRepeat: {
      type: Boolean,
      default: false
    },
    // 默认调用的删除方法
    removeFun: {
      type: Function,
      default: (list = []) => {
        return new Promise((resolve, reject) => {
          removeFile(list).then(() => {
            resolve()
          }).catch(err => {
            reject(err)
          })
        })
      }
    },
    accept: {
      type: String,
      default: `${VIDEO},${WORD},${PNG},${AUDIO},${TAGS},${EXCEL},${PPT},${PDF},${TXT}`
    },
    // 是否允许文件名重复
    isRepeat: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      showFileList: [], // 未调用上传接口前显示的文件列表
      successIndex: 0,
      action: process.env.VUE_APP_BASE_API + '/file/upload',
      progressPercent: 0,
      messageInstance: null
    }
  },
  computed: {
    successCount() {
      return this.showFileList.filter(item => item.status === 'success').length
    }
  },
  methods: {
    rewriteMessage(options) {
      if (this.messageInstance) {
        this.messageInstance.close()
      }
      this.messageInstance = Message(options)
    },
    beforeUpload(file) {
      const accept = this.accept
      const fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
      const fileName = file.name.slice(0, file.name.lastIndexOf('.'))
      if (!this.isRepeat && this.showFileList.length > 0 && this.showFileList.some(item => item.file.name === file.name)) {
        this.rewriteMessage({ message: '文件名称不能重复', type: 'error' })
        return false
      } else if (!accept.split(',').includes(`.${fileExtension.toLowerCase()}`)) {
        this.rewriteMessage({ message: '暂不支持上传该格式文件', type: 'error' })
        return false
      } else if (fileName.length > 100) {
        this.rewriteMessage({ message: '文件名称不能超过100个字', type: 'error' })
        return false
      } else {
        return true
      }
    },
    handleUploadFile(val) {
      const limit = val.file.size > (this.fileSizeLimit * 1024 * 1024)
      const item = { ...val, progressPercent: 0, status: limit ? 'error' : '', errorMsg: limit ? `，文件大于${this.fileSizeLimit}M` : '' }
      this.showFileList.push(item)
      if (!item.errorMsg) {
        const formData = new FormData()
        formData.set('file', val.file)
        const uploadProgressEvent = progressEvent => {
          item.progressPercent = Math.floor((progressEvent.loaded * 100) / progressEvent.total)
          item.status = 'uploading'
        }
        uploadFile(formData, uploadProgressEvent, source.token).then(({ data }) => {
          item.status = 'success'
          item.errorMsg = null
          data.fileId = data.id
          data.uid = val.file.uid
          data.deletable = true
          item.responseData = data
        }).catch(() => {
          item.status = 'error'
        })
      }
    },
    handleRemove(row, index) {
      if (row.status === 'success') {
        this.removeFun([row.responseData]).then(() => {
          this.showFileList.splice(index, 1)
        })
      } else {
        this.showFileList.splice(index, 1)
      }
    },
    handleBatchRemove() {
      const hasUpload = this.showFileList.filter(item => item.status === 'success')
      if (hasUpload && hasUpload.length > 0) {
        this.removeFun(hasUpload.map(item => item.responseData)).then(() => {
          this.showFileList = []
        })
      } else {
        this.showFileList = []
      }
    },
    onCancelToken() {
      source.cancel()
      source = axios.CancelToken.source()
    },
    onSubmit() {
      const hasFile = this.showFileList && this.showFileList.length > 0
      const files = hasFile ? this.showFileList.filter(item => item.status === 'success').map(item => item.responseData) : []
      return {
        valid: hasFile && this.showFileList.some(item => item.status === 'success'),
        values: files
      }
    },
    // 编辑回显数据
    onSetShowFileList(list) {
      this.showFileList = list.map(item => {
        const file = {
          name: item.fileFullName
        }
        return {
          file: { ...file },
          status: 'success',
          responseData: item
        }
      })
    }
  }
}
</script>
<style scoped lang="scss">
.el-table.table-header-bg ::v-deep thead th.el-table__cell {
  background-color: #F7F7F7;
}
@mixin table-border{
  border-right: 1px solid #EBEEF5;
  border-left: 1px solid #EBEEF5;
}
.table-border::v-deep .el-table__empty-block {
  border-right: 1px solid #EBEEF5;
}
.table-border::v-deep .el-table__body-wrapper {
  @include table-border
}
</style>

<style lang="scss" scoped>
.disabled-upload {
  ::v-deep .el-upload.el-upload--picture-card {
    cursor: not-allowed;
  }
}
//移除动画
::v-deep .el-upload-list__item {
  transition: none !important;
  -webkit-transition: none !important;
}

::v-deep .el-upload-list__item-name {
  transition: none !important;
  -webkit-transition: none !important;
}
::v-deep .disabled .el-upload--picture-card {
  display: none !important;
}
</style>
