<template>
  <div class="file-group-upload" v-loading="loading">
    <div class="file-group-upload__btns">
      <el-badge
        v-for="(item, index) in uploadTypes"
        :key="item.key"
        :value="getTypeFileCount(item.key)"
      >
        <el-upload
          ref="upload"
          class="upload-demo"
          :action="action"
          multiple
          :file-list="item.children"
          :limit="item.max"
          :show-file-list="false"
          :on-exceed="handleExceed"
          :on-success="handleSuccess"
          :before-upload="handleBeforeUpload"
          :headers="headers"
          :data="{ fileId: item.key }"
        >
          <el-button
            size="small"
            icon="el-icon-upload"
            :disabled="readonly || loadFail"
            @click="handleUpload(index)"
          >
            {{ item.label }}
          </el-button>
        </el-upload>
      </el-badge>
    </div>
    <el-table
      :data="tableFileList"
      :highlight-current-row="true"
      :header-row-style="{ height: '40px' }"
      :row-style="{ height: '46px' }"
      :cell-style="{ padding: '0px' }"
      :header-cell-style="{ padding: '0px' }"
      :span-method="spanMethod" border
    >
      <el-button v-if="loadFail" slot="empty" type="text" icon="el-icon-refresh-right" @click="getFileList">加载错误，点击刷新</el-button>
      <el-table-column label="" type="index" width="30"></el-table-column>
      <el-table-column prop="belong" label="所属类别" align="center" />
      <el-table-column label="附件名" align="center">
        <template slot-scope="scope">
          <el-button type="text" @click="handleDownload(scope.row)">{{ scope.row.oldName }}</el-button>
        </template>
      </el-table-column>
      <el-table-column label="预览" align="center" min-width="60">
        <template slot-scope="scope">
          <div class="img-box">
            <el-image style="width:40px; height:40px" fit="contain" :src="getFullUrl(scope.row.attachFileUrl)" :preview-src-list="[getFullUrl(scope.row.attachFileUrl)]" />
          </div>
        </template>
      </el-table-column>
      <el-table-column label="类型" align="center" width="80">
        <template slot-scope="scope">
          <div>{{ scope.row.oldName.split('.')[1] }}</div>
        </template>
      </el-table-column>
      <el-table-column v-if="!readonly" label="操作" width="80" align="center">
        <template slot-scope="scope">
          <el-popconfirm
            title="删除后不可恢复，确定删除吗？"
            @confirm="handleRemove(scope.row)"
          >
            <el-button slot="reference" type="text" :disabled="readonly">删除</el-button>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth'
import { deleteFile, getAttachListByFileIds } from '@/api/common/file.js'
import download from '@/plugins/download.js'

// 文件类型所对应的mime类型
const FILE_MIME_MAP = {
  'png': 'image/png',
  'jpg': 'image/jpeg',
  'jpeg': 'image/jpeg',
  'ppt': 'application/vnd.ms-powerpoint',
  'doc': 'application/msword',
  'docx': 'application/vndopenxmlformats-officedocumentwordprocessingmldocument',
  'xls': 'application/vnd.ms-excel',
  'xlsx': 'application/vndopenxmlformats-officedocumentspreadsheetmlsheet'
}
export default {
  name: 'FileGroupUpload',
  props: {
    // 上传的种类 每个种类都会形成一个独有的上传按钮
    uploadTypes: {
      type: Array,
      default: () => {
        return [
          {
            prop: 'fileId',
            label: '上传附件', // 按钮名称
            key: '', // 文件分类的标识，如果是第一次上传则无这个标识，由uuid生成
            idFromServer: false, // 文件ID是否来自服务器
            min: 1, // 最少上传数量 一般没啥用
            max: 10, // 最多上传数量
            types: '', // 限制上传类型 用逗号隔开
          }
        ]
      }
    },
    readonly: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      loading: false,
      loadFail: false,
      fileList: [], // 文件总列表
      currentActive: 0, // 当前操作的文件类型下标
      action: process.env.VUE_APP_BASE_API + '/common/upload',
      headers: {
        Authorization: 'Bearer ' + getToken()
      }
    }
  },
  computed: {
    fileKeyList() {
      const fileKeyList = {};
      this.fileList.forEach(item => {
        if (!fileKeyList[item.key]) {
          fileKeyList[item.key] = [];
        }
        fileKeyList[item.key].push(item);
      });
      return fileKeyList;
    },
    tableFileList() {
      const list = [];
      Object.keys(this.fileKeyList).forEach(key => {
        list.push(...this.fileKeyList[key]);
      })
      return list;
    }
  },
  watch: {
    uploadTypes(newVal) {
      this.getFileList();
    }
  },
  methods: {
    getFullUrl(url) {
      return process.env.VUE_APP_BASE_API + url;
    },
    async getFileList() {
      const filterUploadTypes = this.uploadTypes.filter(item => item.idFromServer);
      const fileIds = filterUploadTypes.map(item => item.key);
      this.loading = true;
      this.loadFail = false;
      try {
        const { data } = await getAttachListByFileIds(fileIds.join());
        if (!data) {
          return;
        }
        const fileList = [];
        filterUploadTypes.forEach(item => {
          let children = data[item.key] || [];
          children = children.map(child => ({
            ...child,
            key: item.key,
            prop: item.prop,
            belong: item.label,
            attachId: child.id,
          }));
          fileList.push(...children);
        });
        this.fileList = fileList;
      } catch (error) {
        this.loadFail = true;
      } finally {
        this.loading = false;
      }
      
    },
    getTypeFileCount(key) {
      return this.fileList.filter(item => item.key === key).length;
    },
    // 更新发送文件ID数据
    sendFileId() {
      const fileIdMap = this.fileList.reduce((pre, cur) => {
        return {
          ...pre,
          [cur.prop]: cur.key
        }
      }, {});
      this.$emit('fileMap', fileIdMap);
    },
    /**
     * 上传操作
     * @param {*} index 上传类型所对应的下标
     */
    handleUpload(index) {
      this.currentActive = index
    },
    /**
     * 删除
     * @param {*} info 文件信息
     */
    async handleRemove(info) {
      try {
        const { code } = await deleteFile(info.attachId)
        if (+code === 200) {
          this.$message.success('删除成功')
          this.fileList = this.fileList.filter(item => item.attachId !== info.attachId);
          this.sendFileId();
        }
      } catch (e) {
        console.error(e)
      }
    },
    /**
     * 处理文件超出个数限制
     * @param {*} files 上传的文件
     * @param {*} fileList 文件总列表
     */
    handleExceed(files, fileList) {
      this.$message.warning(`文件超出可上传的个数限制! 该类型文件最多可上传${this.uploadTypes[this.currentActive].max}个`)
    },
    /**
     * @param {*} res 上传接口返回
     * @param {*} file 上传的文件
     * @param {*} fileList 已经上传的文件列表
     */
    handleSuccess(res, file, fileList) {
      const { cmAttach } = res
      const { label, key, prop } = this.uploadTypes[this.currentActive]
      this.fileList.push({
        ...cmAttach,
        prop,
        belong: label,
        key,
        attachId: cmAttach.id
      });
      this.sendFileId();
    },
    handleBeforeUpload(file) {
      const acceptTypes = this.uploadTypes[this.currentActive].types.split(',').map(item => FILE_MIME_MAP[item])
      if (!acceptTypes.includes(file.type)) {
        this.$message.error(`只允许上传类型为: ${this.uploadTypes[this.currentActive].types} 的文件`)
        return false
      } else {
        return true
      }
    },
    /**
     * 点击文件名下载文件
     * @param {*} info 文件信息
     */
    async handleDownload(info) {
      try {
        download.attachId(info.attachId, info.oldName, false)
      } catch (e) {
        console.error(e)
      }
    },
    spanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex !== 1) {
        return ;
      }
      const typeFiles = this.fileKeyList[row.key];
      const firstFile = typeFiles[0];
      if (row.attachId === firstFile.attachId) {
        return [typeFiles.length, 1];
      } else {
        return [0, 0];
      }
    },
  }
}
</script>

<style scoped lang="scss">

.file-group-upload {
  margin-top: 12px;
  &__btns {
    margin-bottom: 12px;
    display: grid;
    grid-template-columns: repeat(auto-fill, 88px);
    grid-auto-rows: 32px;
    gap: 12px;

    .el-button--small {
      width: 88px;
      height: 32px;
      padding: 0;
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
  .file-name:hover {
    cursor: pointer;
    color: #409EFF;
  }

  .file-delete:hover {
    color: #409EFF;
  }
}
.img-box {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
