/**version-1.0*/
import { read, utils } from "xlsx";
import axios from "axios";
import SparkMD5 from "spark-md5";

let tmixins = {};
let XLSX = window.XLSX || { read, utils };
import { getToken } from "../../../../../utils/auth";
import XEUtils from "xe-utils";
import { getErrorMsg } from "@base/utils/index.js";

let configUtil = {
  baseUrl: process.env.VUE_APP_BASE_API,
  XLSX,
  getToken,
};
let importTimer = null;
let loadingObj = null;
tmixins = {
  name: "excelImport",
  props: ["param", "parentTarget"],
  inject: ["getReportTemplate", "formHttp"],
  data() {
    return {
      excTime: 0,
      showImportDialog: false,
      showImportDialog2: false,
      falseValue: false,
      fileRaw: false,
      isEnd: false,
      currentIndex: 0,
      excelTemplate: "",
      prefix: "/user",
      dataSize: 0,
      totalSuccessNum: 0,
      totalErrorNum: 0,
      percentageNum: 0,
      successRows: [],
      failRows: [],
      oriCols: [],
      showImportResult: false,
      resultType: "",
      option: {},
      showContent: false,
      resOption: {},
      fileCellFields: [],
      importLoading: false,
      loadingTitle: null,

      percent1: 0,
      percent2: 0,
      percent3: 0,

      loadingPercent: 0,
      handleRowSize: 1,

      headerRows: 3,
    };
  },
  computed: {
    importFileLimitSize() {
      return Math.min(
        this.param?.importOption?.importFileLimitSize || 200,
        200
      );
    },
  },
  created() {
    this.exc();
  },
  beforeDestroy() {
    this.clearImportTimer();
  },
  methods: {
    initResGird() {
      let that = this;
      let tableRef = "resGrid";
      let columns = [
        {
          type: "checkbox",
          fixed: "left",
          width: 48,
          resizable: false,
          headerClassName: "vxe-hcs",
          className: "vxe-hcs",
        },
        {
          field: "impNumber",
          title: this.$t2("行号", "components.excelImport.impNumber"),
          width: 100,
          fixed: "left",
        },
        {
          field: "_resultContent",
          title: this.$t2("结果", "components.excelImport.resultContent"),
          width: 250,
          fixed: "left",
          slots: {
            default: ({ row, $rowIndex, $table }) => {
              return that.handleRes(row._resultContent);
            },
          },
        },
      ];
      let cCols = this.oriCols.map((oriCol, index) => {
        let col = {
          field: oriCol.field,
          title: oriCol.title,
          width: 150,
          ...oriCol.otherConfig,
        };
        if (index === 0) {
          col.fixed = "left";
        }
        return col;
      });
      columns = columns.concat(cCols);

      let tableOption = {
        vue: this,
        tableRef: tableRef,
        tableNameRequired: false,
        columns: columns,
        config: {
          toolbarConfig: {
            custom: false,
          },
        },
      };

      this.$vxeTableUtil.initVxeTable(tableOption).then((opts) => {
        this.resOption = opts;
      });
    },
    exc() {
      this.option = this.param;
      this.showContent = true;
      this.showImportDialog = true;
      this.showImportDialog2 = false;
    },
    showSuccessResult() {
      this.showImportResult = true;
      this.resultType = 1;
      this.$nextTick(() => {
        this.initResGird();
        this.$nextTick(() => {
          let tDatas = this.successRows.map((item, index) => {
            item.id = index;
            return item;
          });
          this.$refs.resGrid.loadData(tDatas);
        });
      });
    },
    showErrorResult() {
      this.showImportResult = true;
      this.resultType = 0;
      this.$nextTick(() => {
        this.initResGird();
        this.$nextTick(() => {
          let tDatas = this.failRows.map((item, index) => {
            item.id = index;
            return item;
          });
          this.$refs.resGrid.loadData(tDatas);
        });
      });
    },
    fileChange(file) {
      if (file) {
        this.fileRaw = file.raw;
      } else {
        this.fileRaw = false;
      }
    },
    dialogClose1() {
      this.importLoading = false;
      if (!this.showImportDialog2) {
        this.$emit("update:visiable", false);
        this.showContent = false;
      }
    },
    async dialogPrimary1() {
      let that = this;
      let option = this.option;

      let fileRaw = this.fileRaw;
      if (!fileRaw) {
        this.$baseAlert(
          this.$t2("请上传附件", "components.excelImport.warmMsg1")
        );
        return false;
      }
      let importFileLimitSize = this.importFileLimitSize;
      let fileSize = fileRaw.size;
      let limitSize = importFileLimitSize * 1024 * 1024;
      if (fileSize > limitSize) {
        this.$baseAlert(
          this.$t1("导入文件不允许超过{fileSize}MB", {
            fileSize: importFileLimitSize,
          })
        );
        return false;
      }

      if (option.importFrontOnly) {
        this.dialogPrimary3();
        return false;
      }

      /* this.createImportTimer();
      this.showImportDialog = false;
      if (!option.onConfirm) {
        this.showImportDialog2 = true;
      } */
      // this.$nextTick(() => {
      try {
        this.readExcel(this.fileRaw, function (resultData) {
          that.createImportTimer();
          that.showImportDialog = false;
          if (!option.onConfirm) {
            that.showImportDialog2 = true;
          }
          that.$nextTick(() => {
            if (option.onConfirm) {
              option.onConfirm(resultData.data, that.fileRaw);
            } else {
              that.handleBeforeImport0(that.fileRaw, resultData, () => {
                that.syncDataForImport({
                  multi: false,
                  data: resultData,
                  // saveUrl: saveUrl
                });
              });
            }
          });
        });
      } catch (et) {
        that.clearImportTimer();
        console.error(et);
      }
      // });
    },
    handleBeforeImport(file, resultData, callback) {
      let importOption = this.option.importOption;
      let that = this;
      if (importOption.onBeforeImport) {
        const toDo = (res) => {
          let rows = res?.objx || [];
          rows.forEach((row, rowIndex) => {
            let item = resultData[rowIndex];
            Object.keys(row).forEach((key) => {
              item[key] = row[key];
            });
          });
          callback && callback();
        };
        this.getFieldTarget().handleCustomEvent(
          importOption.onBeforeImport,
          ["file", "resultData", "done"],
          [file, resultData, toDo]
        );
      } else {
        callback && callback();
      }
    },
    handleBeforeImport0(file, resultData, callback) {
      if (!this.showImportDialog2) return;
      let importOption = this.option.importOption;
      if (!importOption.enabledImportPreHandle) {
        this.handleBeforeImport(file, resultData, () => {
          callback && callback();
        });
        return;
      }

      this.uploadFile(() => {
        this.importLoading = false;
        this.handleBeforeImport(file, resultData, () => {
          callback && callback();
        });
      });
      return;
    },
    handleBeforeClose(hide) {
      this.option.onCancel &&
        this.option.onCancel(this.getCallbackData(), this.fileRaw);
      let importOption = this.option.importOption;
      this.getFieldTarget().handleCustomEvent(
        importOption.onSuccessImport,
        ["resultData", "file"],
        [this.getCallbackData(), this.fileRaw]
      );
      this.handleTableCallback();
      hide();
    },
    dialogClose2() {
      this.showImportDialog2 = false;
      this.option.onBeforeCancel &&
        this.option.onBeforeCancel(this.getCallbackData(), this.fileRaw);
      let importOption = this.option.importOption;
      this.getFieldTarget().handleCustomEvent(
        importOption.onSuccessImport,
        ["resultData", "file"],
        [this.getCallbackData(), this.fileRaw]
      );
      this.handleTableCallback();
    },
    handleClose2() {
      this.clearImportTimer();
      this.showImportDialog2 = false;
      this.showContent = false;
      this.option.onClose &&
        this.option.onClose(this.getCallbackData(), this.fileRaw);
      this.option.callback &&
        this.option.callback(this.getCallbackData(), this.fileRaw);
      this.dialogClose1();
    },
    dialogPrimary2() {
      let importOption = this.option.importOption;
      this.showImportDialog2 = false;
      this.option.onBeforeConfirm &&
        this.option.onBeforeConfirm(this.getCallbackData(), this.fileRaw);
      this.getFieldTarget().handleCustomEvent(
        importOption.onSuccessImport,
        ["resultData", "file"],
        [this.getCallbackData(), this.fileRaw]
      );
      this.handleTableCallback();
    },
    getCallbackData() {
      return {
        ...this.resultData,
        successRows: this.successRows,
        failRows: this.failRows,
      };
    },

    /*dialogClose2(flag) {
      let importOption = this.option.importOption;
      this.clearImportTimer();
      this.showImportDialog2 = false;
      this.dialogClose1();
      this.handleTableCallback(flag);
      this.parentTarget.handleCustomEvent(importOption.onSuccessImport, ['resultData', 'file'], [this.resultData, this.fileRaw])
      this.option.callback && this.option.callback(this.resultData, this.fileRaw);
    },
    dialogPrimary2() {
      let importOption = this.option.importOption;
      this.clearImportTimer();
      this.showImportDialog2 = false;
      this.dialogClose1()
      this.handleTableCallback();
      let fileRaw = this.fileRaw;
      this.parentTarget.handleCustomEvent(importOption.onSuccessImport, ['resultData', 'file'], [this.resultData, this.fileRaw])
      this.option.callback && this.option.callback(this.resultData, this.fileRaw);
    },*/
    handleTableCallback(flag) {
      if (flag === 0) return;
      let importOption = this.option.importOption;
      let tableTarget;
      if (importOption.tableRef)
        tableTarget = this.getFieldTarget().getWidgetRef(importOption.tableRef);
      if (tableTarget) {
        let isQueryTable = tableTarget.widget.options.isQueryTable;
        if (isQueryTable) {
          tableTarget.searchEvent();
        }
      }
    },
    async readExcel(file, callback) {
      let that = this;
      let option = this.option;

      if (option.importOption.multipleSheet) {
        this.readExcel2(file, callback);
        return;
      }

      const fileReader = new FileReader();
      fileReader.onload = async (ev) => {
        let resultData;
        try {
          const data = ev.target.result;
          const workbook = configUtil.XLSX.read(data, {
            type: "binary",
          });

          let sheet = workbook.Sheets[workbook.SheetNames[0]];
          if (sheet["!ref"] === undefined || sheet["!ref"] === null) {
            /*that.showImportDialog2 = false;
            that.showContent = false;
            that.clearImportTimer();*/
            that.$baseAlert(
              this.$t2(
                "请使用正确的导入模版！",
                "components.excelImport.warmMsg2"
              )
            );
            that.handleClose2();
            return false;
          }
          let range = configUtil.XLSX.utils.decode_range(sheet["!ref"]);
          let dataSize = range.e.r + 1; //行数
          that.dataSize = dataSize - 3 >= 0 ? dataSize - 3 : 0;
          let titles = [];
          let fields = [];

          const ws = workbook.Sheets[sheet];

          let prefix = option.prefix;
          let excelUrl = option.excel;

          let excelRows = [];
          let row;
          let rowNum;
          let colNum;
          for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
            row = [];
            for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
              let nextCell =
                sheet[
                  configUtil.XLSX.utils.encode_cell({
                    r: rowNum,
                    c: colNum,
                  })
                ];
              if (typeof nextCell === "undefined") {
                row.push(void 0);
              } else {
                row.push(nextCell.w.trim());
              }
            }
            if (rowNum === 1) {
              titles = row;
            }
            if (rowNum === 2) {
              fields = row;
              let checkResult = true;
              /*await that.checkExcelForImport(titles, fields, excelUrl, prefix).then(
                res => {
                  if (res.type !== "success") {
                    checkResult = false;
                  }
                });
              if (!checkResult) {
                that.showContent = false;
                that.clearImportTimer();
                return false;
              }*/
            }
            if (rowNum > 2) {
              let item = {};
              for (let i = 0; i < fields.length; i++) {
                let field = fields[i];
                if (field) {
                  item[field] = row[i] ?? null;
                }
              }
              excelRows.push(item);
            }
          }
          if (
            !titles.length ||
            !fields.length ||
            titles.length !== fields.length
          ) {
            // that.showContent = false;
            // that.clearImportTimer();
            that.$baseAlert(
              this.$t2(
                "请使用正确的导入模版！",
                "components.excelImport.warmMsg2"
              )
            );
            that.handleClose2();
            return false;
          }

          let columns = [];
          let cols = [];
          let uniqueFields = [];
          for (let i = 0; i < titles.length; i++) {
            let title = titles[i];
            if (title) {
              let field = fields[i];
              if (field === null  || field  === undefined) {
                // that.showContent = false;
                // that.clearImportTimer();
                that.$baseAlert(
                  this.$t2(
                    "请使用正确的导入模版！",
                    "components.excelImport.warmMsg2"
                  )
                );
                that.handleClose2();
                return false;
              }
              let t = title.substr(-1);
              let u = title.length >= 2 ? title.substr(-2) : title;
              let isNeed = false;
              if (t === "*") {
                isNeed = true;
              }
              let isUnique = false;
              if (u === "**") {
                uniqueFields.push(field);
                isUnique = true;
              }

              let otherConfig = {};
              let isFile = false;
              if (field.startsWith("attachments_")) {
                that.fileCellFields.push(field);
                isFile = true;
                otherConfig = {
                  slots: {
                    default: "attachment",
                  },
                };
              }

              let col = {
                field: field,
                title: title,
                width: 100,
                isNeed: isNeed,
                isUnique: isUnique,
                isFile,
                otherConfig,
              };
              cols.push(col);
            }
          }

          let oriCols = JSON.parse(JSON.stringify(cols)); //列信息
          if (uniqueFields.length) {
            //分组唯一字段为空时，全部不发包。
            for (let i = 0; i < oriCols.length; i++) {
              let oriCol = oriCols[i];
              if (oriCol.isNeed) {
                for (let j = 0; j < excelRows.length; j++) {
                  let data = excelRows[j];
                  let value = data[oriCol.field];
                  if (value === null  || value === undefined  || value === "") {
                    that.clearImportTimer();
                    that.$baseAlert(
                      this.$t2(
                        "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
                        "components.excelImport.warmMsg3",
                        {
                          lineNo: j + 4,
                          title: oriCol.title,
                        }
                      )
                    );
                    that.handleClose2();
                    return false;
                  }
                }
              }
            }
          }

          this.oriCols = oriCols;

          resultData = {
            data: excelRows,
            titles: titles,
            fields: fields,
            uniqueFields: uniqueFields,
            oriCols: oriCols,
          };
          this.resultData = resultData;
          callback(resultData);
        } catch (et) {
          that.showContent = false;
          that.clearImportTimer();
          console.error(et);
        }
      };
      fileReader.readAsBinaryString(file);
    },
    async checkExcelForImport(titles, fields, turl, prefix) {
      if (!this.showImportDialog2) return;
      let that = this;
      let data = {
        filed_name: fields,
        field_note: titles,
        url: turl,
      };
      let param = JSON.stringify(data);
      return this.$http({
        url: prefix + "/sf_common/compareExcelFields",
        method: "post",
        headers: {
          "Content-Type": "application/json;charset=utf-8",
        },
        // data: param,
        data: data,
      });
    },
    saveImportHandle(data, opt) {
      let multi = this.option.multi;
      let importOption = this.option.importOption;

      let entity = importOption.importEntity;

      if (!entity) return;

      let reportTemplate = this.getReportTemplate();
      let formCode = reportTemplate?.formCode;
      let scriptCode = importOption.importScriptCode || "import";
      // let config = option?.config;

      // let reqData = this.getReqFormData();
      let fileCellFields = this.fileCellFields;
      let formData = null;
      if (multi) {
        formData = data;
      } else {
        formData = {
          [entity]: { ...data },
        };
        if (fileCellFields.length) {
          fileCellFields.forEach((field) => {
            let attachments = data[field] || [];
            delete formData[entity][field];
            formData[field] = attachments;
          });
        }
      }

      let reqData = {
        formCode: formCode,
        formVersion: reportTemplate.formVersion,
        taBm: entity,
        data: formData,
      };

      this.formHttp({
        scriptCode: scriptCode,
        data: reqData,
        modal: false,
        ...opt,
      });
    },
    syncDataForImport(opts) {
      let that = this;
      let multi = this.option.multi;
      let resultData = this.resultData;
      let datas = resultData.data;
      let titles = resultData.titles;
      let fields = resultData.fields;
      let uniqueFields = resultData.uniqueFields;
      let saveUrl = opts.saveUrl;
      let size = datas.length;
      let index = 0;
      let successNum = 0;
      let failNum = 0;
      let dialogObj = this.$refs.importDialog.$el;
      let successNumObj = dialogObj.querySelector(".successNum");
      let failNumObj = dialogObj.querySelector(".failNum");
      let percentageObj = dialogObj.querySelector(".percentage");
      let doneNumObj = dialogObj.querySelector(".doneNum");
      dialogObj.querySelector(".dataSize").innerText = size;

      that.successRows = [];
      that.failRows = [];

      let multiSize = this.option.multiSize || 2;

      let groupIndex = 0;
      let groupDatas = [];
      if (uniqueFields.length) {
        let d = XEUtils.groupBy(datas, function (item, itemIndex, items) {
          let keyArr = [];
          uniqueFields.forEach((field) => {
            keyArr.push(item[field]);
          });
          return keyArr.join("&_&");
        });
        for (let key in d) {
          groupDatas.push(d[key]);
        }
        datas.forEach((item, itemIndex) => {
          item.impSeq = itemIndex;
          item.impNumber = itemIndex + 4;
        });
      }

      let compareV = function (property) {
        return function (a, b) {
          let value1 = a[property];
          let value2 = b[property];
          return value1 - value2;
        };
      };

      let prevHandleData = function (percentageStr, excNum) {
        successNumObj.innerText = successNum;
        failNumObj.innerText = failNum;
        doneNumObj.innerText = successNum + failNum;
        that.percentageNum = percentageStr;
        let isEnd = false;
        if (multi && uniqueFields.length) {
          isEnd = groupIndex + 1 >= groupDatas.length;
        } else {
          isEnd = index + excNum >= size;
        }
        if (!isEnd) {
          index = index + excNum;
          groupIndex = groupIndex + 1;
          setTimeout(function () {
            handleData();
          }, 1);
        } else {
          setTimeout(function () {
            that.clearImportTimer();
          }, 300);
        }
      };

      let getDefaultValue = (row) => {
        let value = null;
        let defaultValue = this.option.defaultValue;
        if (defaultValue) {
          if (typeof defaultValue === "function") {
            value = defaultValue(row) || {};
          } else {
            value = defaultValue || {};
          }
        }
        return value;
      };

      let handleData = () => {
        if (!that.isEnd && index < size) {
          let param;
          let excNum;
          if (multi) {
            if (!uniqueFields.length) {
              if (index + multiSize < size) {
                excNum = multiSize;
              } else {
                excNum = size - index;
              }

              let dataList = [];
              for (let i = 0; i < excNum; i++) {
                let mIndex = index + i;
                let mData = datas[mIndex];
                mData.impSeq = mIndex;
                mData.impNumber = mIndex + 4;

                let errorInfo = that.vailData(mData, opts);
                if (errorInfo.length > 0) {
                  mData._resultType = "error";
                  mData._resultContent = errorInfo;
                  failNum++;
                  that.failRows.push(mData);
                } else {
                  let defaultValue = getDefaultValue(mData);
                  if (defaultValue) {
                    Object.assign(mData, defaultValue);
                  }
                  dataList.push(mData);
                }

                datas[mIndex] = mData;
              }
              if (dataList.length > 0) {
                param = dataList;
              }
            } else {
              excNum = groupDatas[groupIndex].length;
              param = groupDatas[groupIndex];
            }
          } else {
            let data = that.resultData.data[index];
            data.impSeq = index;
            data.impNumber = index + 4;
            excNum = 1;
            datas[index] = data;

            let errorInfo = that.vailData(data, opts);
            if (errorInfo.length > 0) {
              data._resultType = "error";
              data._resultContent = errorInfo;
              failNum++;
              that.failRows.push(data);
            } else {
              param = data;
              let defaultValue = getDefaultValue(data);
              if (defaultValue) {
                Object.assign(param, defaultValue);
              }
            }
          }

          let percentageStr = parseInt(((index + excNum) * 100) / size);
          if (param === null  || param === undefined  || param.length === 0) {
            if (that.showContent) {
              prevHandleData(percentageStr, excNum);
            }
            return;
          }

          that.saveImportHandle(param, {
            failMsg: false,
            callback: (resultMsg) => {
              if (multi) {
                if (resultMsg.type === "success") {
                  let multiRows = resultMsg.objx;
                  for (let i = 0; i < multiRows.length; i++) {
                    let multiRow = multiRows[i];
                    let data = datas[multiRow.impSeq];
                    data._resultType = multiRow.impReturnType;
                    data._resultContent =
                      multiRow.impReturnType === "success"
                        ? this.$t2(
                            "导入成功",
                            "components.excelImport.importSucess"
                          )
                        : multiRow.impReturnMsg;
                    if (multiRow.impReturnType === "success") {
                      successNum++;
                      that.successRows.push(data);
                    } else {
                      failNum++;
                      that.failRows.push(data);
                    }
                  }

                  that.failRows = that.failRows.sort(compareV("impSeq"));
                } else {
                  // error_win(resultMsg);
                  // layer.close(opts.dialogObjIndex);

                  let items = param.map((item) => {
                    return {
                      ...item,
                      _resultType: "error",
                      _resultContent: resultMsg.content,
                    };
                  });
                  failNum = failNum + items.length;
                  that.failRows.push(...items);

                  that.failRows = that.failRows.sort(compareV("impSeq"));

                  /* that.$errorMsg(resultMsg);
                  that.showContent = false;
                  that.clearImportTimer();
                  return; */
                }
              } else {
                let data = that.resultData.data[index];
                data._resultType = resultMsg.type;
                data._resultContent =
                  resultMsg.type === "success"
                    ? this.$t2(
                        "导入成功",
                        "components.excelImport.importSucess"
                      )
                    : resultMsg.content;

                if (resultMsg.type === "success") {
                  successNum++;
                  that.successRows.push(data);
                } else {
                  failNum++;
                  that.failRows.push(data);
                }
              }
              if (that.showContent) {
                prevHandleData(percentageStr, excNum);
              }
            },
            error: (et) => {
              that.isEnd = true;
              that.clearImportTimer();
              console.error(et);
            },
          });
        }
      };
      handleData();
    },
    commonLocalDownload() {
      let importOption = this.option.importOption;
      let importAttachCode = importOption.importAttachCode;
      if (!importAttachCode) return;
      this.$http({
        url: USER_PREFIX + "/bd_attach_setting/getByCode",
        method: "post",
        data: {
          stringOne: importAttachCode,
        },
        success: (res) => {
          let fileObj = res.objx;
          let url = fileObj?.url;
          if (fileObj && url) {
            this.$commonFileUtil.downloadFile(url,fileObj.name);
          }
        },
      });
    },
    vailData(data, opts) {
      let oriCols = opts.data.oriCols;
      let errorInfo = [];
      for (let i = 0; i < oriCols.length; i++) {
        let oriCol = oriCols[i];
        if (oriCol.isNeed) {
          let value = data[oriCol.field];
          if (value === null  || value === undefined  || value === "") {
            errorInfo.push(
              this.$t2(
                "[" + oriCol.title + "]不能为空;",
                "components.excelImport.warmMsg4",
                { title: oriCol.title }
              )
            );
          }
        }
      }
      return errorInfo.join("");
    },
    handleRes(val) {
      /* let content = val;
      let text = content;
      if (content && content.indexOf("Exception") >= 0) {
        let index0 = content.lastIndexOf("*]");
        if (index0 >= 0) {
          text = content.substr(index0);
          if (text) {
            let index1 = text.indexOf("Exception:");
            if (index1 >= 0) {
              text = text.substr(index1 + 10);
            }
          }
        }
      } */
      let text = getErrorMsg(val);
      return text;
    },
    exportToExcel() {
      let str =
        this.resultType === 1
          ? this.$t2("成功", "components.excelImport.success")
          : this.$t2("失败", "components.excelImport.fail");
      let fileName =
        this.$t2("导入结果导出", "components.excelImport.exportFileName") +
        "（" +
        str +
        "）";
      let $grid = this.$refs.resGrid;
      let columns = $grid.getColumns();
      if (columns && columns.length) {
        let fields = columns
          .filter((item, index) => {
            return index > 0 && item.property;
          })
          .map((item, index) => {
            return item.property;
          });
        this.$refs.resGrid.exportData({
          filename: fileName,
          mode: "all",
          type: "csv",
          columns: fields,
        });
      }
    },
    createImportTimer() {
      this.excTime = 0;
      let beginTime = new Date().getTime();
      importTimer = setInterval(() => {
        let nowTime = new Date().getTime();
        let diffTime = (nowTime - beginTime) / 1000;
        this.$set(this, "excTime", this.$baseLodash.round(diffTime, 2));
      }, 100);
    },
    clearImportTimer() {
      clearInterval(importTimer);
      loadingObj && loadingObj.close();
    },
    getWidgetTarget() {},
    getFieldTarget() {
      return this.param.target;
    },
    async dialogPrimary3() {
      if (!this.fileRaw) {
        this.$baseAlert(
          this.$t2("请上传附件", "components.excelImport.warmMsg1")
        );
        return false;
      }
      let that = this;
      let option = this.option;
      loadingObj = this.$baseLoading({
        target: document.body,
        background: "unset",
      });

      let importOption = option.importOption;
      this.readExcel(this.fileRaw, function (resultData) {
        let file = that.fileRaw;
        let flag = false;
        let done = () => {
          if (flag) return;
          flag = true;
          that.showImportDialog = false;
          return that
            .getFieldTarget()
            .handleCustomEvent(
              importOption.onSuccessImport,
              ["resultData", "file"],
              [resultData, file]
            );
        };
        const close = () => {
          that.dialogClose1();
        }
        try {
          if (importOption.onConfirmImportEnabled) {
            if (
              that
                .getFieldTarget()
                .handleCustomEvent(
                  importOption.onConfirmImport,
                  ["resultData", "file", "done", 'close'],
                  [resultData, file, done, close]
                ) !== false
            ) {
              done();
            }
          } else if (importOption.tableRef) {
            let tableRef = that
              .getFieldTarget()
              .getWidgetRef(importOption.tableRef);
            tableRef && tableRef.addTableData(resultData.data);
            done();
          }
        } catch (et) {
          console.error(et);
        }
        setTimeout(function () {
          loadingObj && loadingObj.close();
        }, 200);
      });
    },

    //begin
    fileParse(file, type = "base64", callback) {
      let fileRead = new FileReader();
      if (type === "base64") {
        fileRead.readAsDataURL(file);
      } else if (type === "buffer") {
        fileRead.readAsArrayBuffer(file);
      }
      fileRead.onload = (ev) => {
        callback(ev.target.result);
      };
    },
    getUploadText(percent) {
      return this.$t1("上传导入文件  {percent}%", { percent });
    },
    changeUploadPercent(percent) {
      // return this.$t1('上传导入文件  {percent}%', {percent})
      this.percent1 = percent;
      this.loadingIndex = 1;
    },
    uploadFile(callback) {
      let that = this;
      that.loadingPercent = 0;
      // that.loadingTitle = this.getUploadText(0);
      that.changeUploadPercent(0);
      let file = this.fileRaw;
      let uploadChunkSize = 5;
      this.importLoading = true;
      this.fileUploadCallback = callback;
      this.fileParse(file, "buffer", (buffer) => {
        let spark = new SparkMD5.ArrayBuffer(),
          chunkSize = uploadChunkSize * 1024 * 1024, // Read in chunks of 2MB
          chunks = Math.ceil(file.size / chunkSize),
          hash,
          suffix;
        spark.append(buffer);
        hash = spark.end();
        let md5 = hash;
        let nameSplit = /\.([0-9a-zA-Z]+)$/i.exec(file.name);

        suffix = nameSplit && nameSplit.length > 1 ? nameSplit[1] : "";

        let chunkParam = {
          fullFile: file,
          chunkSize: chunkSize,
          chunks: chunks,
          chunkIndex: 0,
          md5: hash,
          uuid: "",
          name: file.name,
        };
        file.chunkParam = chunkParam;

        this.sendRequest(file);
      });
    },
    async sendRequest(fullFile) {
      if (!this.showImportDialog2) return;
      let that = this;
      let uploadUrl = USER_PREFIX + "/excel_import/uploadFile";
      let chunkParam = fullFile.chunkParam;
      let target = that.$refs.upload;
      let abort;
      let config = {
        headers: {
          "Content-Type": "multipart/form-data",
        },
        cancelToken: new axios.CancelToken(function executor(c) {
          abort = c;
          fullFile.abort = c;
        }),
        onUploadProgress: (progressEvent) => {
          let start = chunkParam.start;
          let uploadedSize =
            start +
            Math.floor(
              (chunkParam.currentSize * progressEvent.loaded) /
                progressEvent.total
            );
          let percent = Math.floor((uploadedSize * 100) / fullFile.size);
          if (percent === 100) {
            percent = 99;
          }
          that.loadingPercent = percent;

          // that.$set(that, 'loadingTitle', this.getUploadText(percent))
          that.changeUploadPercent(percent);
        },
        // failMsg: false,
        modal: false,
        callback: (res1) => {
          if (res1.type === "success") {
            let uuid = res1.objx.uuid;
            chunkParam.uuid = uuid;
            if (preFormData.chunk + 1 >= preFormData.chunks) {
              let mergeData = {
                name: chunkParam.name,
                md5: chunkParam.md5,
                uuid: uuid,
              };
              let _param = {
                mergeData: mergeData,
                chunkParam: chunkParam,
              };
              setTimeout(() => {
                this.mergeFile(_param);
              }, 100);
            } else {
              chunkParam.chunkIndex = chunkParam.chunkIndex + 1;
              chunkParam.uuid = uuid;
              setTimeout(() => {
                this.sendRequest(fullFile);
              }, 100);
            }
          } else {
            this.dialogClose2(0);
          }
          return res1;
        },
        error: (err) => {
          console.log(err);
          this.dialogClose2(0);
        },
      }; //添加请求头

      let chunkIndex = chunkParam.chunkIndex;
      let chunkSize = chunkParam.chunkSize;
      let start = chunkIndex * chunkSize,
        end =
          start + chunkSize >= fullFile.size
            ? fullFile.size
            : start + chunkParam.chunkSize;
      chunkParam.currentSize = end - start;
      chunkParam.start = start;
      chunkParam.end = end;

      let preFormData = {
        file: fullFile.slice(start, end),
        name: fullFile.name,
        chunks: chunkParam.chunks,
        chunk: chunkIndex,
        md5: chunkParam.md5,
        uuid: chunkParam.uuid,
      };

      let formData = new FormData();
      Object.keys(preFormData).forEach((key) => {
        formData.append(key, preFormData[key]);
      });

      let req = this.$http.post(uploadUrl, formData, config);
      req.abort = () => {
        abort(this.$t2("取消上传", "components.VabUpload.cancelUpload"));
      };
    },
    mergeFile(param) {
      if (!this.showImportDialog2) return;
      let that = this;
      let mergeData = param.mergeData;
      let chunkParam = param.chunkParam;
      let fullFile = chunkParam.fullFile;
      let mergeUrl = USER_PREFIX + "/excel_import/mergeChunk";
      let target = this.$refs.upload;
      this.$http({
        url: mergeUrl,
        method: "post",
        data: mergeData,
        // failMsg: false,
        modal: false,
        cancelToken: new axios.CancelToken(function executor(c) {
          if (fullFile) fullFile.abort = c;
        }),
        callback: (res) => {
          if (res.type === "success") {
            that.loadingPercent = 100;
            // that.loadingTitle = this.getUploadText(100);
            this.changeUploadPercent(100);
            setTimeout(() => {
              this.checkImportData();
            }, 100);
          } else {
            this.dialogClose2(0);
          }
        },
        error: (e) => {
          console.log(err);
          this.dialogClose2(0);
        },
      });
    },
    getCheckText(percent) {
      return this.$t1("校验导入文件中的图片数据格式  {percent}%", { percent });
    },
    changeCheckTextPercent(percent) {
      this.percent2 = percent;
      this.loadingIndex = 2;
    },
    checkImportData() {
      if (!this.showImportDialog2) return;
      let that = this;
      that.loadingPercent = 0;
      // that.loadingTitle = this.getCheckText(0);
      that.changeCheckTextPercent(0);
      let fullFile = this.fileRaw;
      let chunkParam = fullFile.chunkParam;

      this.$http({
        url: USER_PREFIX + "/excel_import/checkData",
        method: "post",
        data: {
          name: chunkParam.name,
          md5: chunkParam.md5,
          uuid: chunkParam.uuid,
        },
        // failMsg: false,
        modal: false,
        cancelToken: new axios.CancelToken(function executor(c) {
          if (fullFile) fullFile.abort = c;
        }),
        onUploadProgress: (progressEvent) => {
          let percent = Math.floor(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          if (percent === 100) {
            percent = 99;
          }
          that.loadingPercent = percent;
          // that.$set(that, 'loadingTitle', this.getCheckText(percent))
          that.changeCheckTextPercent(percent);
        },
        callback: (res) => {
          if (res.type === "success") {
            that.loadingPercent = 100;
            // that.loadingTitle = this.getCheckText(100);
            that.changeCheckTextPercent(100);
            this.handleImageData();
          } else {
            this.dialogClose2(0);
          }
        },
        error: (e) => {
          console.log(err);
          this.dialogClose2(0);
        },
      });
    },
    getSaveImageText(percent) {
      return this.$t1("存储导入文件中的图片  {percent}%", { percent });
    },
    changeSaveImageTextPercent(percent) {
      // return this.$t1('存储导入文件中的图片  {percent}%', {percent})
      this.percent3 = percent;
      this.loadingIndex = 3;
    },
    handleImageData() {
      let that = this;
      that.loadingPercent = 0;
      // that.loadingTitle = this.getSaveImageText(0);
      that.changeSaveImageTextPercent(0);
      this.getImportData(0);
    },
    getImportData(index) {
      if (!this.showImportDialog2) return;
      let that = this;
      let rowSize = this.handleRowSize;
      let fullFile = this.fileRaw;
      let chunkParam = fullFile.chunkParam;
      let rowDatas = this.resultData.data;
      let size = rowDatas.length;
      let currentLineNo = index + 1;
      let rowNumber = index + 3;
      let startRow = index + 3;
      let endRow = index + 3 + rowSize - 1;
      this.$http({
        url: USER_PREFIX + "/excel_import/getData",
        method: "post",
        data: {
          name: chunkParam.name,
          md5: chunkParam.md5,
          uuid: chunkParam.uuid,
          startRow: startRow,
          endRow: endRow,
        },
        // failMsg: false,
        modal: false,
        cancelToken: new axios.CancelToken(function executor(c) {
          if (fullFile) fullFile.abort = c;
        }),
        callback: (res) => {
          if (res.type === "success") {
            let rows = res?.objx?.datas || [];
            let fileCellFields = this.fileCellFields;
            rows.forEach((row) => {
              let rowIndex = row.row - 3;
              let item = rowDatas[rowIndex];
              Object.keys(row).forEach((key) => {
                if (fileCellFields.includes(key)) {
                  let value = row[key] || [];
                  if (!Array.isArray(value)) {
                    value = [value];
                  }
                  item[key] = value;
                }
              });
            });
            let cIndex = index + rowSize - 1;
            let percent = Math.floor(((cIndex + 1) * 100) / size);
            that.loadingPercent = percent;
            // that.loadingTitle = this.getSaveImageText(percent);
            that.changeSaveImageTextPercent(percent);
            if (cIndex + 1 < size) {
              this.getImportData(cIndex + 1);
            } else {
              this.fileUploadCallback();
            }
          } else {
            this.dialogClose2(0);
          }
        },
        error: (e) => {
          this.dialogClose2(0);
        },
      });
    },
    async generateNewExcel() {
      let file = this.fileRaw;
      try {
        // 1. 读取原始文件
        const workbook = XLSX.read(file, { type: "binary" });
        const sheetName = workbook.SheetNames[0];
        const rawData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);

        // 2. 提取表头和数据
        const headers = rawData.slice(0, this.headerRows);
        const bodyData = rawData.slice(this.headerRows);

        let exporLineNos = [];
        if (this.resultType) {
          exporLineNos = this.successRows.map((item) => item.impNumber - 1);
        } else {
          exporLineNos = this.failRows.map((item) => item.impNumber - 1);
        }
        // 3. 应用筛选规则
        let selectRule = (row, index) => {
          return exporLineNos.includes(index);
        };
        const filteredData = bodyData.filter(
          (row, index) => {
            return selectRule(row, index + this.headerRows);
          }
          // this.selectRule(row, index + this.headerRows) // 注意索引转换
        );

        // 4. 合并数据
        const newData = [...headers, ...filteredData];

        // 5. 生成新文件
        const newWorkbook = XLSX.utils.book_new();
        const newSheet = XLSX.utils.aoa_to_sheet(newData);
        XLSX.utils.book_append_sheet(newWorkbook, newSheet, "Sheet1");

        // 6. 下载文件
        const blob = XLSX.write(newWorkbook, {
          bookType: "xlsx",
          type: "array",
        });

        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        let fileName = null;
        if (this.resultType) {
          fileName = `导入结果（成功）.xlsx`;
        } else {
          fileName = `导入结果（失败）.xlsx`;
        }
        a.download = fileName;
        a.click();

        // 7. 更新进度
        this.progress = 100;
        setTimeout(() => (this.progress = 0), 1000);
      } catch (error) {
        console.error("处理文件时出错:", error);
      }
    },
    //end
    getLoadingClass(flag, percent) {
      let classStr = null;
      let loadingIndex = this.loadingIndex;
      if (percent >= 100) {
        classStr = "ok";
      } else if (flag === loadingIndex) {
        classStr = "loading";
      }
      return classStr;
    },

    /***sheet1 */
    async readExcel2(file, callback) {
      let that = this;
      let option = this.option;

      const fileReader = new FileReader();
      fileReader.onload = async (ev) => {
        let resultData;
        try {
          const data = ev.target.result;
          const workbook = configUtil.XLSX.read(data, {
            type: "binary",
          });

          let sheetDatas = [];
          for (let pi = 0; pi < workbook.SheetNames.length; pi++) {
            let sheetName = workbook.SheetNames[pi];
            let sheet = workbook.Sheets[sheetName];

            if (sheet["!ref"] === undefined || sheet["!ref"] === null) {
              that.$baseAlert(
                this.$t2(
                  "请使用正确的导入模版！",
                  "components.excelImport.warmMsg2"
                )
              );
              that.handleClose2();
              return false;
            }
            let range = configUtil.XLSX.utils.decode_range(sheet["!ref"]);
            let dataSize = range.e.r + 1; //行数
            that.dataSize = dataSize - 3 >= 0 ? dataSize - 3 : 0;
            let titles = [];
            let fields = [];

            const ws = workbook.Sheets[sheet];

            let prefix = option.prefix;
            let excelUrl = option.excel;

            let excelRows = [];
            let row;
            let rowNum;
            let colNum;
            for (rowNum = range.s.r; rowNum <= range.e.r; rowNum++) {
              row = [];
              for (colNum = range.s.c; colNum <= range.e.c; colNum++) {
                let nextCell =
                  sheet[
                    configUtil.XLSX.utils.encode_cell({
                      r: rowNum,
                      c: colNum,
                    })
                  ];
                if (typeof nextCell === "undefined") {
                  row.push(void 0);
                } else {
                  row.push(nextCell.w.trim());
                }
              }
              if (rowNum === 1) {
                titles = row;
              }
              if (rowNum === 2) {
                fields = row;
                let checkResult = true;
              }
              if (rowNum > 2) {
                let item = {};
                for (let i = 0; i < fields.length; i++) {
                  let field = fields[i];
                  if (field) {
                    item[field] = row[i] ?? null;
                  }
                }
                excelRows.push(item);
              }
            }
            if (
              !titles.length ||
              !fields.length ||
              titles.length !== fields.length
            ) {
              that.$baseAlert(
                this.$t2(
                  "请使用正确的导入模版！",
                  "components.excelImport.warmMsg2"
                )
              );
              // that.handleClose2();
              return false;
            }

            let columns = [];
            let cols = [];
            let uniqueFields = [];
            let uniqueKeys = [];
            for (let i = 0; i < titles.length; i++) {
              let title = titles[i];
              if (title) {
                let field = fields[i];
                if (field === null  || field  === undefined) {
                  that.$baseAlert(
                    this.$t2(
                      "请使用正确的导入模版！",
                      "components.excelImport.warmMsg2"
                    )
                  );
                  // that.handleClose2();
                  return false;
                }
                let t = title.substr(-1);
                let u = title.length >= 2 ? title.substr(-2) : title;
                let p = title.length >= 3 ? title.substr(-3) : title;
                let isNeed = false;
                if (t === "*") {
                  isNeed = true;
                }
                let isUnique = false;
                /* if (u === "**") {
                  uniqueFields.push(field);
                  isUnique = true;
                } */
                let isSheetUnique = false;
                if (p === "***") {
                  uniqueKeys.push(field);
                  isSheetUnique = true;
                }
                if (!uniqueKeys.length) {
                  // that.clearImportTimer();
                  that.$baseAlert(
                    `[${sheetName}]` + that.$t1("缺失单据唯一标识***")
                  );
                  // that.handleClose2();
                  return false;
                }

                let otherConfig = {};
                let isFile = false;
                if (field.startsWith("attachments_")) {
                  that.fileCellFields.push(field);
                  isFile = true;
                  otherConfig = {
                    slots: {
                      default: "attachment",
                    },
                  };
                }

                let col = {
                  field: field,
                  title: title,
                  width: 100,
                  isNeed: isNeed,
                  isUnique: isUnique,
                  isFile,
                  otherConfig,
                  isSheetUnique,
                };
                cols.push(col);
              }
            }

            let oriCols = JSON.parse(JSON.stringify(cols)); //列信息
            /* if (uniqueKeys.length) {
              //分组唯一字段为空时，全部不发包。
              for (let i = 0; i < oriCols.length; i++) {
                let oriCol = oriCols[i];
                if (uniqueKeys.includes(oriCol.field)) {
                  for (let j = 0; j < excelRows.length; j++) {
                    let data = excelRows[j];
                    let value = data[oriCol.field];
                    if (value === null  || value === undefined  || value === "") {
                      that.errorHandle(`[${sheetName}]`+
                      that.$t2(
                        "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
                        "components.excelImport.warmMsg3",
                        {
                          lineNo: j + 4,
                          title: oriCol.title,
                        }
                      ));
                      return false;
                    }
                  }
                }
              }
            } */
            // this.oriCols = oriCols;

            let resultData1 = {
              sheetName: sheetName,
              data: excelRows,
              titles: titles,
              fields: fields,
              uniqueFields: uniqueFields,
              oriCols: oriCols,
              uniqueKeys,
            };
            sheetDatas.push(resultData1);
          }

          //校验必填
          if (!that.checkAllSheetData(sheetDatas)) {
            return false;
          }

          //合并多sheet数据
          let newDatas = [];
          resultData = that.$baseLodash.cloneDeep(sheetDatas[0]);
          let uniqueKey = resultData.uniqueKeys[0];
          let data2 = [];
          for (let i = 0; i < resultData.data.length; i++) {
            let item = resultData.data[i];
            let sheetName = resultData[sheetName];
            let uniqueValue = item[uniqueKey];

            if (!that.isNull(uniqueValue)) {
              let newItem = { ...item };
              let allItems = [];
              for (let j = 1; j < sheetDatas.length; j++) {
                let sheetData = sheetDatas[j];
                let fDatas = [];
                for (let k = 0; k < sheetData.data.length; k++) {
                  let sheetItem = sheetData.data[k];
                  if (that.isNull(sheetItem[uniqueKey])) {
                    that.handleCellNotNull(k, sheetData);
                    return;
                  }
                  if (sheetItem[uniqueKey] === uniqueValue) {
                    fDatas.push(sheetItem);
                  }
                }
                allItems.push(fDatas);
              }
              newItem.sheetItems = allItems;
              data2.push(newItem);
            } else {
              that.handleCellNotNull(i, resultData);
              return false;
            }
          }

          resultData.sheetDatas = sheetDatas;
          resultData.data = data2;
          this.oriCols = resultData.oriCols;
          this.resultData = resultData;
          callback(resultData);
        } catch (et) {
          that.showContent = false;
          that.clearImportTimer();
          console.error(et);
        }
      };
      fileReader.readAsBinaryString(file);
    },
    isNull(val) {
      if (val === null  || val === undefined || val === "" || val === undefined  || val === null) {
        return true;
      }
    },
    checkAllSheetData(sheetItems){
      let that = this;
      for(let sheetItem of sheetItems){
        let oriCols = sheetItem.oriCols;
        let uniqueKeys = sheetItem.uniqueKeys;
        let excelRows = sheetItem.data;
        let sheetName = sheetItem.sheetName;

        for (let i = 0; i < oriCols.length; i++) {
          let oriCol = oriCols[i];
          if (oriCol.isNeed || uniqueKeys.includes(oriCol.field)) {
            for (let j = 0; j < excelRows.length; j++) {
              let data = excelRows[j];
              let value = data[oriCol.field];
              if (that.isNull(value)) {
                that.errorHandle(`[${sheetName}]`+
                that.$t2(
                  "第" + (j + 4) + "行[" + oriCol.title + "]不能为空;",
                  "components.excelImport.warmMsg3",
                  {
                    lineNo: j + 4,
                    title: oriCol.title,
                  }
                ));
                return false;
              }
            }
          }
        }

      }
      return true;
    },


    handleCellNotNull(i, sheetData) {
      let that = this;
      let uniqueKey = sheetData.uniqueKeys[0];
      let oriCol = sheetData.oriCols.find((item) => item.field === uniqueKey);
      that.errorHandle(
        `[${sheetData.sheetName}]` +
          that.$t2(
            "第" + (i + 4) + "行[" + oriCol.title + "]不能为空;",
            "components.excelImport.warmMsg3",
            {
              lineNo: i + 4,
              title: oriCol.title,
            }
          )
      );
    },
    errorHandle(errorText) {
      this.clearImportTimer();
      this.$baseAlert(errorText);
      // this.handleClose2();
    },
    /***sheet2 */
  },
};
export const mixins = tmixins;
