<template>
  <div>
    <div class="file-area">
      <span class="label-text">{{ labelText }}</span>
      <div class="upload-box">
        <el-upload
          ref="upload"
          class="file-uploader"
          action="no"
          :accept="acceptFileType"
          :multiple="limit === null || limit > 1"
          :show-file-list="false"
          :auto-upload="false"
          :file-list="fileList"
          :on-change="onFileChange"
          :on-exceed="handleExceed"
          :limit="limit"
        >
          <el-button>{{ type === 'h5_games' ? '选择Zip压缩包或单个html文件' : '选取' + labelText + '文件' }}</el-button>
        </el-upload>
        <el-button size="small" type="primary" @click="uploadFiles">上传</el-button>
        <el-button size="small" type="primary" @click="useResource">使用资源</el-button>
      </div>
    </div>
    <el-divider />
    <div class="upload-tip">{{ uploadTip }}</div>
    <ul v-if="fileList.length > 0" slot="file-list" class="file-list">
      <li v-for="(file, i) in fileList" :key="i">
        <div class="file-name">
          <span>
            <SvgIcon v-if="iconClass" :icon-class="iconClass" size="12" />
            <!-- 编辑序号和名称 -->
            <template v-if="content.file_info[file.file_id] && content.file_info[file.file_id].isEdit">
              <el-input v-model="content.file_info[file.file_id].xuhao" placeholder="序号" style="width: 80px" />
              <el-input v-model="content.file_info[file.file_id].file_name" placeholder="名称" />
            </template>
            <!-- 可以编辑序号名称状态下显示序号 -->
            <span v-else>{{
              canEditName && file.file_id
                ? content.file_info[file.file_id].xuhao + content.file_info[file.file_id].file_name
                : (file.file_name ?? file.name)
            }}</span>
            <!-- <span>({{ file.size }})</span> -->
          </span>
          <el-progress
            v-if="file.progress > 0 && file.progress < 100"
            type="circle"
            :percentage="file.progress"
            :width="20"
            color="#2A5AF6"
            stroke-linecap="butt"
            :show-text="false"
          />
          <span v-else-if="file.file_id"> 完成 </span>
        </div>
        <SvgIcon icon-class="delete-black" size="12" @click="removeFile(file, i)" />
        <SvgIcon
          v-show="type === 'picture' && file.file_id"
          icon-class="mark"
          size="12"
          @click="viewDialog(file.file_id)"
        />
        <!-- 编辑名称和序号 -->
        <template v-if="canEditName && file.file_id">
          <SvgIcon
            v-if="content.file_info[file.file_id].isEdit"
            icon-class="icon-save"
            size="12"
            @click="changeIsEdit(content.file_info[file.file_id])"
          />
          <SvgIcon v-else icon-class="icon-edit" size="12" @click="changeIsEdit(content.file_info[file.file_id])" />
        </template>
      </li>
    </ul>

    <FillDescribe :file-data="curFile" :visible.sync="visible" @fillDescribeToFile="fillDescribeToFile" />

    <SelectResource
      :visible.sync="visibleResource"
      :project-id="project_id"
      :accept="accept"
      :courseware-id="courseware_id"
      @selectResource="selectResource"
    />
  </div>
</template>

<script>
import { fileUpload } from '@/api/app';
import { conversionSize } from '@/utils/common';

import FillDescribe from '../../common/FillDescribe.vue';
import SelectResource from './SelectResource.vue';

export default {
  name: 'UploadFile',
  components: {
    FillDescribe,
    SelectResource,
  },
  inject: ['property', 'courseware_id', 'project_id'],
  props: {
    // 课件id
    coursewareId: {
      type: String,
      default: '',
    },
    // 组件id
    componentId: {
      type: String,
      default: '',
    },
    // 组件标签
    labelText: {
      type: String,
      default: '',
    },
    // 上传支持的文件格式
    acceptFileType: {
      type: String,
      default: '*',
    },
    // 提示语
    uploadTip: {
      type: String,
      default: '',
    },
    // 图标
    iconClass: {
      type: String,
      default: '',
    },
    fileList: {
      type: Array,
      default: () => [],
    },
    fileIdList: {
      type: Array,
      default: () => [],
    },
    fileInfoList: {
      type: Array,
      default: () => [],
    },
    type: {
      type: String,
      default: '',
    },
    singleSize: {
      type: Number,
      default: 100,
    },
    totalSize: {
      type: Number,
      default: 1024,
    },
    limit: {
      type: Number,
      default: null,
    },
    canEditName: {
      type: Boolean,
      default: false,
    },
    fileInfo: {
      type: Object,
      default: () => ({}),
    },
    index: {
      // 如果是二维数组里循环上传 一维索引
      type: Number,
      default: null,
    },
    indexs: {
      // 如果是二维数组里循环上传 二维索引
      type: Number,
      default: null,
    },
  },
  data() {
    return {
      curFile: null,
      conversionSize,
      visible: false,
      content: {
        file_list: this.fileList,
        file_id_list: this.fileIdList,
        file_info_list: this.fileInfoList,
        file_info: this.fileInfo,
      },
      visibleResource: false,
    };
  },
  computed: {
    accept() {
      let accept = '*';
      if (this.acceptFileType.includes('.mp3')) {
        accept = 'audio';
      } else if (this.acceptFileType.includes('.mp4')) {
        accept = 'video';
      } else if (this.acceptFileType.includes('.jpg')) {
        accept = 'image';
      } else if (this.acceptFileType.includes('.zip')) {
        accept = 'h5_game';
      } else if (this.acceptFileType.includes('.txt')) {
        accept = 'text';
      }
      return accept;
    },
  },
  watch: {
    content: {
      handler(val) {
        this.$emit('updateFileList', val, this.index, this.indexs);
      },
      deep: true,
    },
    property: {
      handler(val) {
        if (val.isGetContent) {
          this.content = {
            file_list: this.fileList,
            file_id_list: this.fileIdList,
            file_info_list: this.fileInfoList,
            file_info: this.fileInfo,
          };
        }
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    // 显示自定义样式文件列表
    onFileChange(file, fileList) {
      this.afterSelectFile(file);
      fileList.forEach((file) => {
        if (!file.progress || file.progress <= 0) file.progress = 0;
      });
      const lists = this.$refs.upload.uploadFiles;
      if (lists.length === 0) return;
      const files = lists.filter((item) => {
        let find = this.content.file_list.findIndex((p) => p.uid === item.uid);
        return find === -1;
      });
      if (this.limit !== null && this.content.file_list.length + files.length > this.limit) {
        this.$message.warning(
          `当前限制选择 ${this.limit} 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + this.content.file_list.length} 个文件`,
        );
        return;
      }
      this.content.file_list = [...this.content.file_list, ...files];
    },

    handleExceed(files, fileList) {
      this.$message.warning(
        `当前限制选择 ${this.limit} 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`,
      );
    },

    // 删除文件
    removeFile(file, i) {
      this.$confirm('是否删除当前文件？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.$refs.upload.handleRemove(file);
          this.content.file_list.splice(i, 1);
          this.content.file_id_list.splice(i, 1);
        })
        .catch(() => {});
    },

    // 文件校验
    afterSelectFile(file) {
      const fileName = file.name;
      let singleSizeTip = `文件[${fileName}]大小超过${conversionSize(this.singleSize * 1024 * 1024)},被移除！`;
      if (file.size > this.singleSize * 1024 * 1024) {
        this.$message.error(singleSizeTip);
        this.$refs.upload.handleRemove(file);
        return false;
      }

      const suffix = fileName.slice(fileName.lastIndexOf('.') + 1, fileName.length).toLowerCase();
      let fileType = [];
      let typeTip = '';

      if (this.type === 'audio') {
        fileType = ['mp3', 'acc', 'wma', 'wav'];
        typeTip = '音频文件只能是 mp3、acc、wma、wav格式!';
      } else if (
        this.type === 'picture' ||
        this.type === 'image_text' ||
        this.type === 'drawing' ||
        this.type === 'character_structure' ||
        this.type === 'newWord_template' ||
        this.type === 'character'
      ) {
        fileType = ['jpg', 'png', 'jpeg'];
        typeTip = '图片文件只能是 jpg、png、jpeg 格式!';
      } else if (this.type === 'video' || this.type === 'video_interaction') {
        fileType = ['mp4'];
        typeTip = '视频文件只能是 mp4 格式!';
      } else if (this.type === 'upload_preview' || this.type === 'video_interaction_file') {
        fileType = [
          'png',
          'jpg',
          'jpeg',
          'txt',
          'pdf',
          'doc',
          'docx',
          'xls',
          'xlsx',
          'ppt',
          'pptx',
          'mp3',
          'wma',
          'mp4',
          'mov',
          'zip',
          'rar',
        ];
        typeTip = '文件不支持';
      } else if (this.type === 'h5_games') {
        fileType = ['zip', 'html'];
        typeTip = 'H5游戏文件只能是 zip、html 格式!';
      } else if (this.type === '3DModel') {
        fileType = ['fbx', 'obj', 'gltf', 'glb', 'mtl'];
        typeTip = '3D模型文件只能是 fbx、obj、gltf、glb、mtl 格式!';
      }
      const isNeedType = fileType.includes(suffix);
      if (!isNeedType) {
        typeTip += `,[${fileName}]被移除！`;
        this.$message.error(typeTip);
        this.$refs.upload.handleRemove(file);
        return false;
      }
    },

    // 上传文件
    uploadFiles() {
      const files = (this.content.file_list || []).filter((file) => file.uid && file.status !== 'success');
      if (files.length <= 0) {
        this.$message.error('没有需要上传的文件！');
        return false;
      }
      const totalSize = files.reduce((sum, cur) => sum + Number(cur.size || 0), 0);
      if (totalSize > this.totalSize * 1024 * 1024) {
        this.$message.error(`文件总大小不能超过${conversionSize(this.totalSize * 1024 * 1024)}!`);
        return false;
      }

      files
        .filter((p) => {
          let pro = p.progress || -1;
          return pro <= 0;
        })
        .forEach((file) => {
          let form = new FormData();
          form.append(file.name, file.raw, file.name);
          fileUpload('Mid', form, {
            handleUploadProgress: (progressEvent) => {
              // 进度到99等服务器返回文件信息后才算实际完成
              let per = Number((progressEvent.progress * 99).toFixed(2) || 0);
              let en = this.content.file_list.find((p) => p.uid === file.uid);
              if (en) {
                en.progress = per;
                this.$forceUpdate();
              }
            },
          }).then(({ file_info_list }) => {
            let file_index = this.content.file_list.findIndex((p) => p.uid === file.uid);
            if (file_index > -1) {
              if (this.type === 'picture') {
                this.content.file_info_list[file_index] = {
                  file_id: file_info_list[0].file_id,
                  file_name: file_info_list[0].file_name,
                  title: '',
                  intro: '',
                };
              }
              this.content.file_list[file_index] = {
                file_id: file_info_list[0].file_id,
                file_name: file_info_list[0].file_name,
                file_url: file_info_list[0].file_url,
              };
              if (this.canEditName) {
                let obj = {
                  xuhao: '',
                  isEdit: false,
                  file_name: file_info_list[0].file_name,
                };
                this.$set(this.content.file_info, file_info_list[0].file_id, obj);
              }
              this.content.file_id_list.push(file_info_list[0].file_id);
              this.$refs.upload.uploadFiles = [];
              this.$forceUpdate();
            }
          });
        });
    },

    // 显示弹窗
    viewDialog(file_id) {
      if (file_id) this.visible = true;
      this.curFile = this.content.file_info_list.find((file) => file.file_id === file_id);
    },

    // 给文件加介绍
    fillDescribeToFile(file) {
      let en = this.content.file_info_list.find((p) => p.file_id === file.file_id);
      if (en) {
        Object.assign(en, file);
      }
    },
    // 使用资源
    useResource() {
      this.visibleResource = true;
    },
    selectResource({ file_id, file_name, file_url, intro }) {
      this.content.file_list.push({ file_id, file_name, file_url });
      this.content.file_id_list.push(file_id);
      this.content.file_info_list.push({ file_id, file_name, title: '', intro });
      if (this.canEditName) {
        let obj = {
          xuhao: '',
          isEdit: false,
          file_name,
        };
        this.$set(this.content.file_info, file_id, obj);
      }
      this.visibleResource = false;
    },
    // 编辑文件名及序号
    changeIsEdit(file) {
      file.isEdit = !file.isEdit;
    },
  },
};
</script>

<style lang="scss" scoped>
.module-content {
  .file-area {
    display: flex;
    column-gap: 16px;
    align-items: center;

    .label-text {
      font-size: 14px;
      color: $font-light-color;
    }

    div {
      flex: 1;
    }
  }

  .el-divider {
    margin: 16px 0;
  }

  .upload-tip {
    margin-bottom: 16px;
    font-size: 12px;
    color: #86909c;
  }

  .upload-box {
    display: flex;
    justify-content: space-between;

    .el-button + .el-button {
      margin-left: 2px;
    }

    .file-uploader {
      flex: 1;

      :deep .el-upload {
        &--text {
          width: 100%;
          background-color: $fill-color;
          border-radius: 2px 0 0 2px;

          .el-button {
            width: 100%;
            color: #86909c;
            text-align: left;
          }
        }
      }
    }

    .el-button {
      border-radius: 0 2px 2px 0;
    }
  }

  .old_file_list {
    margin-top: 16px;
  }

  .file-list {
    display: flex;
    flex-direction: column;
    row-gap: 16px;

    li {
      display: flex;
      column-gap: 12px;
      align-items: center;

      .file-name {
        display: flex;
        column-gap: 14px;
        align-items: center;
        justify-content: space-between;
        max-width: 500px; // 360px有点窄
        padding: 8px 12px;
        font-size: 14px;
        color: #1d2129;
        background-color: #f7f8fa;

        span {
          display: flex;
          column-gap: 14px;
          align-items: center;
        }
      }

      .svg-icon {
        cursor: pointer;
      }
    }
  }
}
</style>
