<template>
  <el-dialog
    :visible="visible"
    width="60%"
    style="height: 98%"
    :before-close="handleClose"
    top="5vh"
    lock-scroll
  >
    <div class="title" slot="title">
      <div class="divider"></div>
      <span class="label">{{ getDialogTitle }}</span>
      <span class="tips">
        <i class="el-icon-info"></i
        >提示：上传过程中请勿关闭此弹窗或刷新页面等操作
      </span>
    </div>
    <el-form
      :model="form"
      ref="form"
      :rules="rules"
      size="mini"
      label-width="80px"
    >
      <el-form-item label="标题" prop="uploadTitle">
        <el-input
          placeholder="请输入标题（必填）"
          v-model="form.uploadTitle"
          :disabled="isDisabledTitle"
        ></el-input>
      </el-form-item>
      <el-form-item label="上传文件">
        <el-upload
          ref="upload"
          class="upload-area"
          name="zipFile"
          :accept="fileType"
          :action="importZipUrl"
          :headers="headers"
          :on-success="handleSuccess"
          :on-change="handleChange"
          :auto-upload="false"
          drag
        >
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">
            将文件拖到此处，或<em>点击上传</em>, 只能上传{{
              fileType
            }}文件，一次只能传一个文件
          </div>
        </el-upload>
      </el-form-item>
      <el-form-item>
        <el-button size="mini" type="primary" @click="handleUpload"
          >确定上传</el-button
        >

        <el-button type="primary" size="mini" plain @click.native="handleClose"
          >关闭</el-button
        >
      </el-form-item>
    </el-form>

    <el-card
      class="upload-progress"
      shadow="never"
      v-if="displayList.length > 0"
    >
      <h3>上传列表</h3>
      <el-table :data="displayList" fit>
        <el-table-column prop="name" label="标题"> </el-table-column>
        <el-table-column prop="size" label="文件大小">
          <template slot-scope="scope">
            {{ getSize(scope.row.size) }}
          </template>
        </el-table-column>
        <el-table-column prop="progress" label="进度" width="300">
          <template slot-scope="scope">
            <el-progress
              :percentage="scope.row.percent"
              v-if="!isNaN(parseInt(scope.row.percent))"
              :status="scope.row.status"
              :text-inside="true"
              :stroke-width="16"
            ></el-progress>
          </template>
        </el-table-column>
        <el-table-column prop="operation" label="操作" width="100">
          <template slot-scope="scope">
            <el-button
              type="text"
              size="mini"
              @click.native="handleCancel(scope.$index)"
              v-if="scope.row.status == null"
              >取消</el-button
            >
            <!-- <el-button
              type="text"
              size="mini"
              @click.native="handleRestart(scope.$index)"
              v-if="scope.row.status == 'exception'"
              >重新上传</el-button
            > -->
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </el-dialog>
</template>

<script>
import { importZip } from "@/utils/file";
import { getToken } from "@/utils/auth";
export default {
  name: "UploadDialog",
  props: {
    //biz_cultural_relic——文物，biz_exhibition——展览，还需考虑其他的类型
    bizType: {
      type: String,
      default: "biz_cultural_relic",
    },
    flowId: {
      type: String,
      default: "", //流程id
    },
    title: {
      type: String,
      default: "", //标题，重传时会带过来
    },
    fileType: {
      type: String,
      default: ".zip", //‘.zip为压缩文件,.jpg,.png,.jpeg’为图片
    },
  },
  computed: {
    getSize(size) {
      return (size) => {
        return (size / 1024 / 1024).toFixed(2) + "M"; //1M=1024Kb=1024*1024byte
      };
    },
    importZipUrl() {
      if (!this.bizType) {
        return;
      }
      return process.env.VUE_APP_BASE_API + "/bizImport/importZip";
    },
    getDialogTitle() {
      switch (this.bizType) {
        case "biz_cultural_relic":
          return "批量上传文物";
        case "biz_exhibition":
          return "批量上传展览";
        default:
          return "上传文件";
      }
    },
  },
  data() {
    return {
      dialogVisible: false,
      isUpLoading: false,
      percentState: 0,
      list: {
        records: [],
        current: 1,
        size: 10,
      },
      progressStatus: null,
      visible: false, //控制批量上传弹窗显示
      fileList: [], //上传当中的文件队列
      displayList: [], //用于显示下方的文件队列
      uploadCount: 0, //处于上传中的文件数量，当等于fileList的时候就关闭弹窗，请求完毕一个就++
      cancelUploadArr: [], //保存每个文件上传接口对应的取消请求的函数[fn,fn,fn...]，点叉叉关闭弹窗就遍历这个全部执行一遍就取消了所以请求
      headers: {
        authorization: getToken(),
      },
      form: {
        uploadTitle: "",
      },
      rules: {
        uploadTitle: [
          {
            required: true,
            message: "请输入上传标题",
            trigger: "change",
          },
        ],
      },
      isDisabledTitle: false,
    };
  },
  watch: {
    title(value) {
      this.form.uploadTitle = value;
      this.isDisabledTitle = true;
    },
  },

  methods: {
    // 取消编辑
    cancelForm() {
      this.handleClose();
    },
    // 提交上传
    handleUpload(file) {
      this.$refs.form.validate((valid) => {
        if (valid) {
          if (file && file instanceof File) {
            this.fileList = [file];
          } else {
            this.fileList = this.$refs.upload.uploadFiles;
          }
          console.log("this.fileList", this.fileList);
          // return
          for (let i = 0; i < this.fileList.length; i++) {
            this.uploadSelf(this.fileList[i].raw, i); //弹窗显示的时候，就根据文件队列的数量调用上传接口
          }
        }
      });
    },
    // 保证一次只能传一个，覆盖上一次
    handleChange(file, fileList) {
      if (fileList.length > 1) {
        fileList[0] = fileList[1];
        fileList.splice(1, 1);
      }
    },

    // 上传函数实现逻辑
    uploadSelf(file, index) {
      const loading = this.$loading({
        lock: true,
        text: "正在上传中...文件较大，请耐心等待，请勿刷新页面",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });
      let formData = new FormData();
      formData.append("type", this.bizType);
      formData.append("zipFile", file);
      formData.append("flowTitle", this.form.uploadTitle);
      if (this.flowId) {
        formData.append("flowId", this.flowId);
      }

      importZip(
        formData,
        (progressEvent) => this.uploadUnderWayCallback(progressEvent, index),
        (cancelCallback) => this.cancelCallBack(cancelCallback, index)
      )
        .then((res) => {
          loading.close();
          const { code, msg } = res.data;
          if (code == 0) {
            this.$set(this.fileList[index], "status", "success");
            this.$set(this.fileList[index], "percent", 100);
            this.$set(this.fileList[index], "desc", "上传成功");
            this.$message.success("文件" + file.name + "上传成功！");
            this.$emit("update");
          } else {
            this.$set(this.fileList[index], "status", "exception");
            this.$set(this.fileList[index], "desc", "上传失败" + msg);
            this.$message.error("上传失败:" + msg);
            this.$emit("update");
          }
          //  删除已经上传成功的，并向display中新增一条
          this.displayList.push(this.fileList[index]);
          this.fileList.splice(index, 1);
          this.$refs.form.resetFields();
        })
        .catch((err) => {
          loading.close();
          console.log("err", err);
        });
    },

    // 文件上传进度回调
    uploadUnderWayCallback(progressEvent, index) {
      let completeVal =
        (progressEvent.loaded / progressEvent.total) * 100 - 1 || 0; //处理成组件库进度组件需要的格式
      this.$set(this.fileList[index], "percent", Math.floor(completeVal)); //直接改变数组某一项不是响应式的，因此我们需要用到这个api，将其响应式化，添加到数组中
    },

    // 文件取消回调
    cancelCallBack(cancelCallback, index) {
      this.$set(this.cancelUploadArr, index, cancelCallback); //添加取消队列中，关闭弹窗批量取消
      this.uploadCount = 0;
    },
    // 关闭弹窗回调
    handleClose() {
      // 文件列表中如果Status为null，则代表有仍在上传中
      let isUpLoading = false;
      this.fileList.map((item) => {
        if (item.status == null) {
          isUpLoading = true;
          return;
        }
      });
      let title = isUpLoading ? "当前有上传任务，是否取消上传" : "确认关闭？";
      let confirmButtonText = isUpLoading ? "关闭并取消上传" : "确定";
      let cancelButtonText = isUpLoading ? "否" : "取消";
      let that = this;
      this.$confirm(title, "提示", {
        confirmButtonText,
        cancelButtonText,
        type: "warning",
      })
        .then(() => {
          // 点击取消上传
          if (that.isUpLoading) {
            this.handleCancelAllUpLoad();
            this.$message.warning("已取消上传！");
          }
          this.visible = false; //最后关闭
        })
        .catch(() => {
          console.log("用户取消操作");
        });
    },
    // 取消单个上传任务
    handleCancel(index) {
      if (this.cancelUploadArr[index]) {
        this.cancelUploadArr[index](); //取消上传
        this.cancelUploadArr.splice(index, 1); //从取消队列中删除
      }
      if (this.displayList[index]) {
        this.displayList.splice(index, 1);
      }
      this.handleReset();
      this.$message.info("已取消上传！");
    },
    // // 重新上传
    // handleRestart(index) {
    //   // debugger
    //   const { name } = this.displayList[index];
    //   this.form.uploadTitle = name;
    //   this.handleUpload(this.displayList[index]);
    // },

    // 全部取消上传
    handleCancelAllUpLoad() {
      this.cancelUploadArr.forEach((cancelCallBack) => cancelCallBack()); //批量取消上传
    },
    // 上传成功的回调
    handleSuccess(res) {
      res.Success && this.$Message.success("上传成功"); //提示
      this.fileList = [];
    },
    // 恢复初始值
    handleReset() {
      this.fileList = [];
      this.uploadCount = 0;
      this.cancelUploadArr = [];
    },
  },
};
</script>

<style lang="scss" scoped>
.title {
  display: flex;
  align-items: center;
  .divider {
    width: 8px;
    height: 16px;
    border-left: 4px solid #409eff;
    margin-right: 8px;
  }
  .label {
    font-weight: bold;
  }
  .tips {
    font-size: 14px;
    color: #666;
    margin-left: 10px;
  }
}
.upload-area {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  margin-bottom: 30px;
  ::v-deep .el-upload,
  ::v-deep .el-upload-dragger {
    width: 100%;
  }
}
.upload-progress {
  margin-bottom: 30px;
}
.upload-records {
  margin-bottom: 30px;
}
.dialog-footer {
  margin-top: 30px;
  display: flex;
  justify-content: flex-end;
}
.el-dialog__body {
  padding: 0 20px 30px 20px;
}
::v-deep .el-upload-list {
  display: flex;
  justify-content: flex-start;
  width: 100%;
}
</style>
