/**
 * author: vformAdmin
 * email: vdpadmin@163.com
 * website: https://www.vform666.com
 * date: 2021.08.18
 * remark: 如果要分发VForm源码，需在本文件顶部保留此文件头信息！！
 */

import {
  deepClone,
  generateId,
  getDefaultFormConfig,
  overwriteObj,
  createUUID,
  columnFormatMap,
} from "../../../components/xform/utils/util";
import {
  containers,
  advancedFields,
  basicFields,
  customFields,
  businessFields,
} from "../../../components/xform/form-designer/widget-panel/widgetsConfig.js";
import { VARIANT_FORM_VERSION } from "../../../components/xform/utils/config";
import { keyNamePrefixMap } from "../../../components/xform/form-designer/widget-panel/widgetsConfig";

let createDesigner0;
const baseRefUtil = {
  deepClone,
  generateId,
  getDefaultFormConfig,
  overwriteObj,
  containers,
  advancedFields,
  basicFields,
  customFields,
  VARIANT_FORM_VERSION,
};

let chartContainers = [],
  chartWidgets = [];

(function () {
  createDesigner0 = function (vueInstance) {
    let defaultFormConfig = baseRefUtil.deepClone(
      baseRefUtil.getDefaultFormConfig()
    );

    return {
      widgetList: [],
      formConfig: {
        cssCode: "",
        gridConfig: {
          accessReturnType: 1,
          isLoadDataByAccess: false,
        },
        scriptList: [],
        formType: 0,
        getConfig: {
          accessType: "1",
          accessUrl: null,
          accessParam: null,
          accessCallback: null,
          scriptName: null,
          scriptCode: null,
        },
        saveConfig: {
          accessType: "1",
          accessUrl: null,
          accessParam: null,
          accessCallback: null,
          scriptName: null,
          scriptCode: null,
        },
        editFormCode: null,
        editFormName: null,
        searchDialogNameField: null,
        searchDialogUniqueField: null,
        entity: null,
        wfEnabled: false,
        isLoadEntity: false,
        formScriptCode: "getOne",
        formScriptParam: null,
        formScriptSuccess: null,
        saveScriptCode: "saveUpdate",
        wfConfig: null,
        wfStartBindSave: false,
        wfAgreenBindSave: false,
        wfAgreeConfigData: [],
        wfConfigDataEnabled: false,
        wfConfigData: [],
        multiTabEnabled: false,
        multiTabLabelField: null,
        addFormCode: null,
        addFormName: null,
        wfTheme: null,
        otherTabEnabled: false,
        otherTabList: [],
        customListTabLabel: null,
        globalConfig: null,
      },
      dataSources: [], //数据源

      selectedId: null,
      selectedWidget: null,
      selectedWidgetName: null, //选中组件名称（唯一）
      vueInstance: vueInstance,

      formWidget: null, //表单设计容器

      cssClassList: [], //自定义样式列表

      historyData: {
        index: -1, //index: 0,
        maxStep: 20,
        steps: [],
      },

      initDesigner(resetFormJson) {
        this.widgetList = [];
        this.formConfig = baseRefUtil.deepClone(defaultFormConfig);
        this.dataSources = [];

        //输出版本信息和语雀链接
        /* console.info(`%cVariantForm %cVer${baseRefUtil.VARIANT_FORM_VERSION} %chttps://www.yuque.com/visualdev/vform`,
          "color:#409EFF;font-size: 22px;font-weight:bolder",
          "color:#999;font-size: 12px",
          "color:#333"
        ); */

        /*if (!resetFormJson) {
          this.initHistoryData();
        }*/
      },

      clearDesigner(skipHistoryChange) {
        let emptyWidgetListFlag = this.widgetList.length === 0;
        this.widgetList = [];
        this.selectedId = null;
        this.selectedWidgetName = null;
        this.selectedWidget = {}; //this.selectedWidget = null
        baseRefUtil.overwriteObj(this.formConfig, defaultFormConfig); //
        this.formConfig.gridConfig = defaultFormConfig.gridConfig;

        if (!!skipHistoryChange) {
          //什么也不做！！
        } else if (!emptyWidgetListFlag) {
          this.emitHistoryChange();
        } else {
          this.saveCurrentHistoryStep();
        }
      },

      loadPresetCssCode(preCssCode) {
        if (this.formConfig.cssCode === "" && !!preCssCode) {
          this.formConfig.cssCode = preCssCode;
        }
      },

      getLayoutType() {
        return this.formConfig.layoutType || "PC";
      },

      changeLayoutType(newType) {
        this.formConfig.layoutType = newType;
      },

      getImportTemplate() {
        return {
          widgetList: [],
          // formConfig: baseRefUtil.deepClone(this.formConfig)
          formConfig: baseRefUtil.deepClone(defaultFormConfig),
        };
      },

      handleImportJson(formJson) {
        let formConfig = formJson.formConfig;
        if (formConfig.formCode === vueInstance?.reportTemplate?.formCode) {
          return;
        }
        let widgetArr = formJson.widgetList;
        let itemFieldMap = {
          grid: "cols",
          table: "rows",
          "table-cell": "widgetList",
          "h5-table": "rows",
          "h5-table-cell": "widgetList",
          tab: "tabs",
          "tab-pane": "widgetList",
          "grid-col": "widgetList",
          "vf-box": "widgetList",
          card: "widgetList",
          detail: "panes",
          "detail-pane": "widgetList",
          "detail-h5": "panes",
          "h5-card": "panes",
          "h5-card-pane": "widgetList",
        };
        let loopDo = (widgetList) => {
          if (!widgetList) return;
          widgetList.forEach((widget) => {
            if (widget.type === "data-table" || widget.type === "list-h5") {
              let vailColumns = widget.options.tableColumns.filter(
                (item) => item.prop && item.label
              );
              vailColumns.forEach((item) => {
                if (item.formatS === "editAttachment") {
                  let prop = item.prop;
                  let columnOption = item.columnOption;
                  let editColumnOption = item.editColumnOption;

                  let suffix = this.createAttachmentSuffix();
                  let keyName = this.createAttachmentKeyName(suffix);
                  if (columnOption) {
                    columnOption.keyName = keyName;
                    columnOption.keyNameSuffix = suffix;
                  }
                  if (editColumnOption) {
                    editColumnOption.keyName = keyName;
                    editColumnOption.keyNameSuffix = suffix;
                  }
                  item.prop = keyName;
                }
              });
            } else if (
              widget.type === "vabUpload" ||
              widget.type === "baseAttachment"
            ) {
              let suffix = this.createAttachmentSuffix();
              let keyName = this.createAttachmentKeyName(suffix);
              widget.options.keyName = keyName;
              widget.options.keyNameSuffix = suffix;
            } else {
              if (widget.category === "container") {
                let itemField = itemFieldMap[widget.type];
                if (itemField) {
                  if ("table" === widget.type) {
                    widget[itemField].forEach((item) => {
                      loopDo(item.cols);
                    });
                  } else if ("h5-table" === widget.type) {
                    widget[itemField].forEach((item) => {
                      loopDo(item.cols);
                    });
                  } else {
                    loopDo(widget[itemField]);
                  }
                }
              }
            }
          });
        };
        loopDo(widgetArr);
      },
      loadFormJson(formJson) {
        let modifiedFlag = false;

        if (!!formJson && !!formJson.widgetList) {
          this.widgetList = formJson.widgetList;
          modifiedFlag = true;
        }
        if (!!formJson && !!formJson.formConfig) {
          //this.formConfig = importObj.formConfig
          baseRefUtil.overwriteObj(
            this.formConfig,
            formJson.formConfig
          ); /* 用=赋值，会导致inject依赖注入的formConfig属性变成非响应式 */
          modifiedFlag = true;
        }

        if (modifiedFlag) {
          this.emitEvent("form-json-imported", []); // 通知其他组件
        }
        this.setSelected();
        return modifiedFlag;
      },
      handleSelectedWidget(selected) {
        //处理历史未定义的属性
        if (selected.formItemFlag || selected.type === "data-table") {
          if (selected.options.submitFlag === void 0) {
            // selected.options.submitFlag = true;
            this.vueInstance.$set(selected.options, "submitFlag", true);
          }
        }
        this.handleKeyNameSuffix(selected);
      },
      handleKeyNameSuffix(selected) {
        if (!selected) return;
        let optionModel = selected.options;
        let prefix = this.getKeyNamePrefix(selected.type);
        if (
          optionModel.keyNameEnabled &&
          !!prefix &&
          !optionModel.keyNameSuffix
        ) {
          let keyName = optionModel.keyName;
          if (keyName.startsWith(prefix)) {
            this.vueInstance.$set(
              optionModel,
              "keyNameSuffix",
              keyName.substring(prefix.length)
            );
          }
        }
      },
      setSelected(selected) {
        if (!selected) {
          this.clearSelected();
          return;
        }

        //处理历史未定义的属性
        this.handleSelectedWidget(selected);

        this.selectedWidget = selected;
        if (!!selected.id) {
          this.selectedId = selected.id;
          this.selectedWidgetName = selected.options.name;
          if (!selected.category) {
            this.emitEvent("canvas-select-field", selected.options.name);
          } else {
            this.emitEvent("canvas-select-container", selected.options.name);
          }
        }
      },

      updateSelectedWidgetNameAndLabel(selectedWidget, newName, newLabel) {
        this.selectedWidgetName = newName;
        //selectedWidget.options.name = newName  //此行多余
        if (
          !!newLabel &&
          Object.keys(selectedWidget.options).indexOf("label") > -1
        ) {
          selectedWidget.options.label = newLabel;
        }
      },

      clearSelected() {
        this.selectedId = null;
        this.selectedWidgetName = null;
        this.selectedWidget = {}; //this.selectedWidget = null
      },

      checkWidgetMove(evt) {
        /* Only field widget can be dragged into sub-form */
        if (!!evt.draggedContext && !!evt.draggedContext.element) {
          let wgCategory = evt.draggedContext.element.category;
          let wgType = evt.draggedContext.element.type;
          if (!!evt.to) {
            if (
              evt.to.className === "sub-form-table" &&
              wgCategory === "container"
            ) {
              //this.$message.info(this.vueInstance.i18nt('designer.hint.onlyFieldWidgetAcceptable'))
              return false;
            }
          }
        }

        return true;
      },

      checkFieldMove(evt) {
        if (!!evt.draggedContext && !!evt.draggedContext.element) {
          let wgCategory = evt.draggedContext.element.category;
          let wgType = evt.draggedContext.element.type + "";
          //console.log('wgType======', wgType)
          if (!!evt.to) {
            if (evt.to.className === "sub-form-table" && wgType === "slot") {
              //this.$message.info(this.vueInstance.i18nt('designer.hint.onlyFieldWidgetAcceptable'))
              return false;
            }
          }
        }

        return true;
      },

      /**
       * 追加表格新行
       * @param widget
       */
      appendTableRow(widget) {
        let rowIdx = widget.rows.length; //确定插入行位置
        let newRow = baseRefUtil.deepClone(widget.rows[widget.rows.length - 1]);
        newRow.id = "table-row-" + baseRefUtil.generateId();
        newRow.merged = false;
        newRow.cols.forEach((col) => {
          col.id = "table-cell-" + baseRefUtil.generateId();
          col.options.name = col.id;
          col.merged = false;
          col.options.colspan = 1;
          col.options.rowspan = 1;
          col.widgetList.length = 0;
        });
        widget.rows.splice(rowIdx, 0, newRow);

        this.emitHistoryChange();
      },

      /**
       * 追加表格新列
       * @param widget
       */
      appendTableCol(widget) {
        let colIdx = widget.rows[0].cols.length; //确定插入列位置
        widget.rows.forEach((row) => {
          let newCol = baseRefUtil.deepClone(
            this.getContainerByType("table-cell")
          );
          newCol.id = "table-cell-" + baseRefUtil.generateId();
          newCol.options.name = newCol.id;
          newCol.merged = false;
          newCol.options.colspan = 1;
          newCol.options.rowspan = 1;
          newCol.widgetList.length = 0;
          row.cols.splice(colIdx, 0, newCol);
        });

        this.emitHistoryChange();
      },

      insertTableRow(widget, insertPos, cloneRowIdx, curCol, aboveFlag) {
        let newRowIdx = !!aboveFlag ? insertPos : insertPos + 1; //初步确定插入行位置
        if (!aboveFlag) {
          //继续向下寻找同列第一个未被合并的单元格
          let tmpRowIdx = newRowIdx;
          let rowFoundFlag = false;
          while (tmpRowIdx < widget.rows.length) {
            if (!widget.rows[tmpRowIdx].cols[curCol].merged) {
              newRowIdx = tmpRowIdx;
              rowFoundFlag = true;
              break;
            } else {
              tmpRowIdx++;
            }
          }

          if (!rowFoundFlag) {
            newRowIdx = widget.rows.length;
          }
        }

        let newRow = baseRefUtil.deepClone(widget.rows[cloneRowIdx]);
        newRow.id = "table-row-" + baseRefUtil.generateId();
        newRow.merged = false;
        newRow.cols.forEach((col) => {
          col.id = "table-cell-" + baseRefUtil.generateId();
          col.options.name = col.id;
          col.merged = false;
          col.options.colspan = 1;
          col.options.rowspan = 1;
          col.widgetList.length = 0;
        });
        widget.rows.splice(newRowIdx, 0, newRow);

        let colNo = 0;
        while (
          newRowIdx < widget.rows.length - 1 &&
          colNo < widget.rows[0].cols.length
        ) {
          //越界判断
          const cellOfNextRow = widget.rows[newRowIdx + 1].cols[colNo];
          const rowMerged = cellOfNextRow.merged; //确定插入位置下一行的单元格是否为合并单元格
          if (!!rowMerged) {
            let rowArray = widget.rows;
            let unMergedCell = {};
            let startRowIndex = null;
            for (let i = newRowIdx; i >= 0; i--) {
              //查找该行已合并的主单元格
              if (
                !rowArray[i].cols[colNo].merged &&
                rowArray[i].cols[colNo].options.rowspan > 1
              ) {
                startRowIndex = i;
                unMergedCell = rowArray[i].cols[colNo];
                break;
              }
            }

            if (!!unMergedCell.options) {
              //如果有符合条件的unMergedCell
              let newRowspan = unMergedCell.options.rowspan + 1;
              this.setPropsOfMergedRows(
                widget.rows,
                startRowIndex,
                colNo,
                unMergedCell.options.colspan,
                newRowspan
              );
              colNo += unMergedCell.options.colspan;
            } else {
              colNo += 1;
            }
          } else {
            //colNo += 1
            colNo += cellOfNextRow.options.colspan || 1;
          }
        }

        this.emitHistoryChange();
      },

      insertTableCol(widget, insertPos, curRow, leftFlag) {
        let newColIdx = !!leftFlag ? insertPos : insertPos + 1; //初步确定插入列位置
        if (!leftFlag) {
          //继续向右寻找同行第一个未被合并的单元格
          let tmpColIdx = newColIdx;
          let colFoundFlag = false;
          while (tmpColIdx < widget.rows[curRow].cols.length) {
            if (!widget.rows[curRow].cols[tmpColIdx].merged) {
              newColIdx = tmpColIdx;
              colFoundFlag = true;
              break;
            } else {
              tmpColIdx++;
            }

            if (!colFoundFlag) {
              newColIdx = widget.rows[curRow].cols.length;
            }
          }
        }

        widget.rows.forEach((row) => {
          let newCol = baseRefUtil.deepClone(
            this.getContainerByType("table-cell")
          );
          newCol.id = "table-cell-" + baseRefUtil.generateId();
          newCol.options.name = newCol.id;
          newCol.merged = false;
          newCol.options.colspan = 1;
          newCol.options.rowspan = 1;
          newCol.widgetList.length = 0;
          row.cols.splice(newColIdx, 0, newCol);
        });

        let rowNo = 0;
        while (
          newColIdx < widget.rows[0].cols.length - 1 &&
          rowNo < widget.rows.length
        ) {
          //越界判断
          const cellOfNextCol = widget.rows[rowNo].cols[newColIdx + 1];
          const colMerged = cellOfNextCol.merged; //确定插入位置右侧列的单元格是否为合并单元格
          if (!!colMerged) {
            let colArray = widget.rows[rowNo].cols;
            let unMergedCell = {};
            let startColIndex = null;
            for (let i = newColIdx; i >= 0; i--) {
              //查找该行已合并的主单元格
              if (!colArray[i].merged && colArray[i].options.colspan > 1) {
                startColIndex = i;
                unMergedCell = colArray[i];
                break;
              }
            }

            if (!!unMergedCell.options) {
              //如果有符合条件的unMergedCell
              let newColspan = unMergedCell.options.colspan + 1;
              this.setPropsOfMergedCols(
                widget.rows,
                rowNo,
                startColIndex,
                newColspan,
                unMergedCell.options.rowspan
              );
              rowNo += unMergedCell.options.rowspan;
            } else {
              rowNo += 1;
            }
          } else {
            //rowNo += 1
            rowNo += cellOfNextCol.options.rowspan || 1;
          }
        }

        this.emitHistoryChange();
      },
      insertH5TableCol(widget, insertPos, curRow, leftFlag) {
        let newColIdx = !!leftFlag ? insertPos : insertPos + 1; //初步确定插入列位置
        if (!leftFlag) {
          //继续向右寻找同行第一个未被合并的单元格
          let tmpColIdx = newColIdx;
          let colFoundFlag = false;
          while (tmpColIdx < widget.rows[curRow].cols.length) {
            if (!widget.rows[curRow].cols[tmpColIdx].merged) {
              newColIdx = tmpColIdx;
              colFoundFlag = true;
              break;
            } else {
              tmpColIdx++;
            }

            if (!colFoundFlag) {
              newColIdx = widget.rows[curRow].cols.length;
            }
          }
        }

        widget.rows.forEach((row) => {
          let newCol = baseRefUtil.deepClone(
            this.getContainerByType("h5-table-cell")
          );
          newCol.id = "table-cell-" + baseRefUtil.generateId();
          newCol.options.name = newCol.id;
          newCol.merged = false;
          newCol.options.colspan = 1;
          newCol.options.rowspan = 1;
          newCol.widgetList.length = 0;
          row.cols.splice(newColIdx, 0, newCol);
        });

        let rowNo = 0;
        while (
          newColIdx < widget.rows[0].cols.length - 1 &&
          rowNo < widget.rows.length
        ) {
          //越界判断
          const cellOfNextCol = widget.rows[rowNo].cols[newColIdx + 1];
          const colMerged = cellOfNextCol.merged; //确定插入位置右侧列的单元格是否为合并单元格
          if (!!colMerged) {
            let colArray = widget.rows[rowNo].cols;
            let unMergedCell = {};
            let startColIndex = null;
            for (let i = newColIdx; i >= 0; i--) {
              //查找该行已合并的主单元格
              if (!colArray[i].merged && colArray[i].options.colspan > 1) {
                startColIndex = i;
                unMergedCell = colArray[i];
                break;
              }
            }

            if (!!unMergedCell.options) {
              //如果有符合条件的unMergedCell
              let newColspan = unMergedCell.options.colspan + 1;
              this.setPropsOfMergedCols(
                widget.rows,
                rowNo,
                startColIndex,
                newColspan,
                unMergedCell.options.rowspan
              );
              rowNo += unMergedCell.options.rowspan;
            } else {
              rowNo += 1;
            }
          } else {
            //rowNo += 1
            rowNo += cellOfNextCol.options.rowspan || 1;
          }
        }

        this.emitHistoryChange();
      },
      setPropsOfMergedCols(
        rowArray,
        startRowIndex,
        startColIndex,
        newColspan,
        rowspan
      ) {
        for (let i = startRowIndex; i < startRowIndex + rowspan; i++) {
          for (let j = startColIndex; j < startColIndex + newColspan; j++) {
            if (i === startRowIndex && j === startColIndex) {
              rowArray[i].cols[j].options.colspan = newColspan; //合并后的主单元格
              continue;
            }

            rowArray[i].cols[j].merged = true;
            rowArray[i].cols[j].options.colspan = newColspan;
            rowArray[i].cols[j].widgetList = [];
          }
        }
      },

      setPropsOfMergedRows(
        rowArray,
        startRowIndex,
        startColIndex,
        colspan,
        newRowspan
      ) {
        for (let i = startRowIndex; i < startRowIndex + newRowspan; i++) {
          for (let j = startColIndex; j < startColIndex + colspan; j++) {
            if (i === startRowIndex && j === startColIndex) {
              rowArray[i].cols[j].options.rowspan = newRowspan;
              continue;
            }

            rowArray[i].cols[j].merged = true;
            rowArray[i].cols[j].options.rowspan = newRowspan;
            rowArray[i].cols[j].widgetList = [];
          }
        }
      },

      setPropsOfSplitCol(
        rowArray,
        startRowIndex,
        startColIndex,
        colspan,
        rowspan
      ) {
        for (let i = startRowIndex; i < startRowIndex + rowspan; i++) {
          for (let j = startColIndex; j < startColIndex + colspan; j++) {
            rowArray[i].cols[j].merged = false;
            rowArray[i].cols[j].options.rowspan = 1;
            rowArray[i].cols[j].options.colspan = 1;
          }
        }
      },

      setPropsOfSplitRow(
        rowArray,
        startRowIndex,
        startColIndex,
        colspan,
        rowspan
      ) {
        for (let i = startRowIndex; i < startRowIndex + rowspan; i++) {
          for (let j = startColIndex; j < startColIndex + colspan; j++) {
            rowArray[i].cols[j].merged = false;
            rowArray[i].cols[j].options.rowspan = 1;
            rowArray[i].cols[j].options.colspan = 1;
          }
        }
      },

      mergeTableCol(rowArray, colArray, curRow, curCol, leftFlag, cellWidget) {
        let mergedColIdx = !!leftFlag
          ? curCol
          : curCol + colArray[curCol].options.colspan;

        // let remainedColIdx = !!leftFlag ? curCol - colArray[curCol - 1].options.colspan : curCol
        let remainedColIdx = !!leftFlag ? curCol - 1 : curCol;
        if (!!leftFlag) {
          //继续向左寻找同行未被合并的第一个单元格
          let tmpColIdx = remainedColIdx;
          while (tmpColIdx >= 0) {
            if (!rowArray[curRow].cols[tmpColIdx].merged) {
              remainedColIdx = tmpColIdx;
              break;
            } else {
              tmpColIdx--;
            }
          }
        }

        if (
          !!colArray[mergedColIdx].widgetList &&
          colArray[mergedColIdx].widgetList.length > 0
        ) {
          //保留widgetList
          if (
            !colArray[remainedColIdx].widgetList ||
            colArray[remainedColIdx].widgetList.length === 0
          ) {
            colArray[remainedColIdx].widgetList = baseRefUtil.deepClone(
              colArray[mergedColIdx].widgetList
            );
          }
        }

        let newColspan =
          colArray[mergedColIdx].options.colspan * 1 +
          colArray[remainedColIdx].options.colspan * 1;
        this.setPropsOfMergedCols(
          rowArray,
          curRow,
          remainedColIdx,
          newColspan,
          cellWidget.options.rowspan
        );

        this.emitHistoryChange();
      },

      mergeTableWholeRow(rowArray, colArray, rowIndex, colIndex) {
        //需要考虑操作的行存在已合并的单元格！！
        //整行所有单元格行高不一致不可合并！！
        let startRowspan = rowArray[rowIndex].cols[0].options.rowspan;
        let unmatchedFlag = false;
        for (let i = 1; i < rowArray[rowIndex].cols.length; i++) {
          if (rowArray[rowIndex].cols[i].options.rowspan !== startRowspan) {
            unmatchedFlag = true;
            break;
          }
        }
        if (unmatchedFlag) {
          this.vueInstance.$message.info(
            this.vueInstance.i18nt(
              "designer.hint.rowspanNotConsistentForMergeEntireRow"
            )
          );
          return;
        }

        let widgetListCols = colArray.filter((colItem) => {
          return (
            !colItem.merged &&
            !!colItem.widgetList &&
            colItem.widgetList.length > 0
          );
        });
        if (!!widgetListCols && widgetListCols.length > 0) {
          //保留widgetList
          if (
            widgetListCols[0].id !== colArray[0].id &&
            (!colArray[0].widgetList || colArray[0].widgetList.length <= 0)
          ) {
            colArray[0].widgetList = baseRefUtil.deepClone(
              widgetListCols[0].widgetList
            );
          }
        }

        this.setPropsOfMergedCols(
          rowArray,
          rowIndex,
          0,
          colArray.length,
          colArray[colIndex].options.rowspan
        );

        this.emitHistoryChange();
      },

      mergeTableRow(rowArray, curRow, curCol, aboveFlag, cellWidget) {
        let mergedRowIdx = !!aboveFlag
          ? curRow
          : curRow + cellWidget.options.rowspan;

        //let remainedRowIdx = !!aboveFlag ? curRow - cellWidget.options.rowspan : curRow
        let remainedRowIdx = !!aboveFlag ? curRow - 1 : curRow;
        if (!!aboveFlag) {
          //继续向上寻找同列未被合并的第一个单元格
          let tmpRowIdx = remainedRowIdx;
          while (tmpRowIdx >= 0) {
            if (!rowArray[tmpRowIdx].cols[curCol].merged) {
              remainedRowIdx = tmpRowIdx;
              break;
            } else {
              tmpRowIdx--;
            }
          }
        }

        if (
          !!rowArray[mergedRowIdx].cols[curCol].widgetList &&
          rowArray[mergedRowIdx].cols[curCol].widgetList.length > 0
        ) {
          //保留widgetList
          if (
            !rowArray[remainedRowIdx].cols[curCol].widgetList ||
            rowArray[remainedRowIdx].cols[curCol].widgetList.length === 0
          ) {
            rowArray[remainedRowIdx].cols[curCol].widgetList =
              baseRefUtil.deepClone(
                rowArray[mergedRowIdx].cols[curCol].widgetList
              );
          }
        }

        let newRowspan =
          rowArray[mergedRowIdx].cols[curCol].options.rowspan * 1 +
          rowArray[remainedRowIdx].cols[curCol].options.rowspan * 1;
        this.setPropsOfMergedRows(
          rowArray,
          remainedRowIdx,
          curCol,
          cellWidget.options.colspan,
          newRowspan
        );

        this.emitHistoryChange();
      },

      mergeTableWholeCol(rowArray, colArray, rowIndex, colIndex) {
        //需要考虑操作的列存在已合并的单元格！！
        //整列所有单元格列宽不一致不可合并！！
        let startColspan = rowArray[0].cols[colIndex].options.colspan;
        let unmatchedFlag = false;
        for (let i = 1; i < rowArray.length; i++) {
          if (rowArray[i].cols[colIndex].options.colspan !== startColspan) {
            unmatchedFlag = true;
            break;
          }
        }
        if (unmatchedFlag) {
          this.vueInstance.$message.info(
            this.vueInstance.i18nt(
              "designer.hint.colspanNotConsistentForMergeEntireColumn"
            )
          );
          return;
        }

        let widgetListCols = [];
        rowArray.forEach((rowItem) => {
          let tempCell = rowItem.cols[colIndex];
          if (
            !tempCell.merged &&
            !!tempCell.widgetList &&
            tempCell.widgetList.length > 0
          ) {
            widgetListCols.push(tempCell);
          }
        });

        let firstCellOfCol = rowArray[0].cols[colIndex];
        if (!!widgetListCols && widgetListCols.length > 0) {
          //保留widgetList
          if (
            widgetListCols[0].id !== firstCellOfCol.id &&
            (!firstCellOfCol.widgetList ||
              firstCellOfCol.widgetList.length <= 0)
          ) {
            firstCellOfCol.widgetList = baseRefUtil.deepClone(
              widgetListCols[0].widgetList
            );
          }
        }

        this.setPropsOfMergedRows(
          rowArray,
          0,
          colIndex,
          firstCellOfCol.options.colspan,
          rowArray.length
        );

        this.emitHistoryChange();
      },

      undoMergeTableCol(rowArray, rowIndex, colIndex, colspan, rowspan) {
        this.setPropsOfSplitCol(rowArray, rowIndex, colIndex, colspan, rowspan);

        this.emitHistoryChange();
      },

      undoMergeTableRow(rowArray, rowIndex, colIndex, colspan, rowspan) {
        this.setPropsOfSplitRow(rowArray, rowIndex, colIndex, colspan, rowspan);

        this.emitHistoryChange();
      },

      deleteTableWholeCol(rowArray, colIndex) {
        //需考虑删除的是合并列！！
        let onlyOneColFlag = true;
        rowArray.forEach((ri) => {
          if (ri.cols[0].options.colspan !== rowArray[0].cols.length) {
            onlyOneColFlag = false;
          }
        });
        //仅剩一列则不可删除！！
        if (onlyOneColFlag) {
          this.vueInstance.$message.info(
            this.vueInstance.i18nt("designer.hint.lastColCannotBeDeleted")
          );
          return;
        }

        //整列所有单元格列宽不一致不可删除！！
        let startColspan = rowArray[0].cols[colIndex].options.colspan;
        let unmatchedFlag = false;
        for (let i = 1; i < rowArray.length; i++) {
          if (rowArray[i].cols[colIndex].options.colspan !== startColspan) {
            unmatchedFlag = true;
            break;
          }
        }
        if (unmatchedFlag) {
          this.vueInstance.$message.info(
            this.vueInstance.i18nt(
              "designer.hint.colspanNotConsistentForDeleteEntireColumn"
            )
          );
          return;
        }

        rowArray.forEach((rItem) => {
          rItem.cols.splice(colIndex, startColspan);
        });

        this.emitHistoryChange();
      },

      deleteTableWholeRow(rowArray, rowIndex) {
        //需考虑删除的是合并行！！
        let onlyOneRowFlag = true;
        rowArray[0].cols.forEach((ci) => {
          if (ci.options.rowspan !== rowArray.length) {
            onlyOneRowFlag = false;
          }
        });
        //仅剩一行则不可删除！！
        if (onlyOneRowFlag) {
          this.vueInstance.$message.info(
            this.vueInstance.i18nt("designer.hint.lastRowCannotBeDeleted")
          );
          return;
        }

        //整行所有单元格行高不一致不可删除！！
        let startRowspan = rowArray[rowIndex].cols[0].options.rowspan;
        let unmatchedFlag = false;
        for (let i = 1; i < rowArray[rowIndex].cols.length; i++) {
          if (rowArray[rowIndex].cols[i].options.rowspan !== startRowspan) {
            unmatchedFlag = true;
            break;
          }
        }
        if (unmatchedFlag) {
          this.vueInstance.$message.info(
            this.vueInstance.i18nt(
              "designer.hint.rowspanNotConsistentForDeleteEntireRow"
            )
          );
          return;
        }

        rowArray.splice(rowIndex, startRowspan);

        this.emitHistoryChange();
      },

      getContainerByType(typeName) {
        let allWidgets = [
          ...baseRefUtil.containers,
          ...baseRefUtil.basicFields,
          ...baseRefUtil.advancedFields,
          ...baseRefUtil.customFields,
          ...businessFields,
        ];
        let foundCon = null;
        allWidgets.forEach((con) => {
          if (!!con.category && !!con.type && con.type === typeName) {
            foundCon = con;
          }
        });

        return foundCon;
      },

      getFieldWidgetByType(typeName) {
        let allWidgets = [
          ...baseRefUtil.containers,
          ...baseRefUtil.basicFields,
          ...baseRefUtil.advancedFields,
          ...baseRefUtil.customFields,
          ...chartContainers,
          ...chartWidgets,
          ...businessFields,
        ];
        let foundWidget = null;
        allWidgets.forEach((widget) => {
          if (!!!widget.category && !!widget.type && widget.type === typeName) {
            foundWidget = widget;
          }
        });

        return foundWidget;
      },

      hasConfig(widget, configName) {
        let originalWidget = null;
        if (!!widget.category) {
          originalWidget = this.getContainerByType(widget.type);
        } else {
          originalWidget = this.getFieldWidgetByType(widget.type);
        }

        if (!originalWidget || !originalWidget.options) {
          return false;
        }

        return Object.keys(originalWidget.options).indexOf(configName) > -1;
      },
      /*upgradeWidgetConfig(oldWidget) {
        let newWidget = null;
        if (!!oldWidget.category) {
          newWidget = this.getContainerByType(oldWidget.type);
        } else {
          newWidget = this.getFieldWidgetByType(oldWidget.type);
        }

        if (!newWidget || !newWidget.options) {
          return;
        }

        Object.keys(newWidget.options).forEach(ck => {
          if (!oldWidget.options.hasOwnProperty(ck)) {
            oldWidget.options[ck] = baseRefUtil.deepClone(newWidget.options[ck]);
          }
        });
      },*/
      upgradeWidgetConfig(oldWidget) {
        let newWidget = null;
        if (!!oldWidget.category) {
          newWidget = this.getContainerByType(oldWidget.type);
        } else {
          newWidget = this.getFieldWidgetByType(oldWidget.type);
        }

        if (!newWidget || !newWidget.options) {
          return;
        }

        Object.keys(newWidget.options).forEach((ck) => {
          if (!oldWidget.options.hasOwnProperty(ck)) {
            let value = newWidget.options[ck];
            let nullValue = Array.isArray(value) ? [] : null;
            oldWidget.options[ck] = nullValue;
          }
        });
      },

      upgradeFormConfig(oldFormConfig) {
        Object.keys(this.formConfig).forEach((fc) => {
          if (!oldFormConfig.hasOwnProperty(fc)) {
            let value = this.formConfig[fc];
            let nullValue = Array.isArray(value) ? [] : null;
            oldFormConfig[fc] = baseRefUtil.deepClone(nullValue);
          }
        });
      },

      cloneGridCol(widget, parentWidget) {
        let newGridCol = baseRefUtil.deepClone(
          this.getContainerByType("grid-col")
        );
        newGridCol.options.span = widget.options.span;
        let tmpId = baseRefUtil.generateId();
        newGridCol.id = "grid-col-" + tmpId;
        newGridCol.options.name = "gridCol" + tmpId;

        parentWidget.cols.push(newGridCol);
      },

      cloneContainer(containWidget) {
        if (containWidget.type === "grid") {
          let newGrid = baseRefUtil.deepClone(this.getContainerByType("grid"));
          newGrid.id = newGrid.type + baseRefUtil.generateId();
          newGrid.options.name = newGrid.id;
          containWidget.cols.forEach((gridCol) => {
            let newGridCol = baseRefUtil.deepClone(
              this.getContainerByType("grid-col")
            );
            let tmpId = baseRefUtil.generateId();
            newGridCol.id = "grid-col-" + tmpId;
            newGridCol.options.name = "gridCol" + tmpId;
            newGridCol.options.span = gridCol.options.span;
            newGrid.cols.push(newGridCol);
          });

          return newGrid;
        } else if (containWidget.type === "table") {
          let newTable = baseRefUtil.deepClone(
            this.getContainerByType("table")
          );
          newTable.id = newTable.type + baseRefUtil.generateId();
          newTable.options.name = newTable.id;
          containWidget.rows.forEach((tRow) => {
            let newRow = baseRefUtil.deepClone(tRow);
            newRow.id = "table-row-" + baseRefUtil.generateId();
            newRow.cols.forEach((col) => {
              col.id = "table-cell-" + baseRefUtil.generateId();
              col.options.name = col.id;
              col.widgetList = []; //清空组件列表
            });
            newTable.rows.push(newRow);
          });

          return newTable;
        } else if (containWidget.type === "h5-table") {
          let newTable = baseRefUtil.deepClone(
            this.getContainerByType("h5-table")
          );
          newTable.id = newTable.type + baseRefUtil.generateId();
          newTable.options.name = newTable.id;
          containWidget.rows.forEach((tRow) => {
            let newRow = baseRefUtil.deepClone(tRow);
            newRow.id = "table-row-" + baseRefUtil.generateId();
            newRow.cols.forEach((col) => {
              col.id = "table-cell-" + baseRefUtil.generateId();
              col.options.name = col.id;
              col.widgetList = []; //清空组件列表
            });
            newTable.rows.push(newRow);
          });

          return newTable;
        } else {
          //其他容器组件不支持clone操作
          return null;
        }
      },

      moveUpWidget(parentList, indexOfParentList) {
        if (!!parentList) {
          if (indexOfParentList === 0) {
            this.vueInstance.$message(
              this.vueInstance.i18nt("designer.hint.moveUpFirstChildHint")
            );
            return;
          }

          let tempWidget = parentList[indexOfParentList];
          parentList.splice(indexOfParentList, 1);
          parentList.splice(indexOfParentList - 1, 0, tempWidget);
        }
      },

      moveDownWidget(parentList, indexOfParentList) {
        if (!!parentList) {
          if (indexOfParentList === parentList.length - 1) {
            this.vueInstance.$message(
              this.vueInstance.i18nt("designer.hint.moveDownLastChildHint")
            );
            return;
          }

          let tempWidget = parentList[indexOfParentList];
          parentList.splice(indexOfParentList, 1);
          parentList.splice(indexOfParentList + 1, 0, tempWidget);
        }
      },
      copyNewFieldWidget(origin) {
        let newWidget = baseRefUtil.deepClone(origin);
        let sourceType = newWidget.type;
        newWidget.type = newWidget.targetType || newWidget.type;
        newWidget.sourceType = sourceType;
        let tempId = baseRefUtil.generateId();
        newWidget.id = newWidget.type.replace(/-/g, "") + tempId;
        if (newWidget.hasOwnProperty("tableField")) {
          newWidget.tableField = newWidget.id; //表字段
        }

        // newWidget.options.name = newWidget.id;
        // newWidget.options.label = newWidget.options.label || newWidget.type.toLowerCase();

        newWidget.nameReadonly
          ? newWidget.options.label &&
            newWidget.options.label.indexOf(".") > -1 &&
            (newWidget.options.label = newWidget.options.label.substring(
              newWidget.options.label.indexOf(".") + 1
            ))
          : ((newWidget.options.name = newWidget.id),
            (newWidget.options.label =
              newWidget.options.label || newWidget.type.toLowerCase()));
        delete newWidget.displayName;
        if (!newWidget.nameReadonly) {
          newWidget.options.keyNameEnabled = true;
          if (!newWidget.options.keyName)
            newWidget.options.keyName = newWidget.id;
          if (
            newWidget.type === "vabUpload" ||
            newWidget.type === "baseAttachment"
          ) {
            let keyNameSuffix = this.createKeyNameSuffix(newWidget.type);
            // this.createKeyNameSuffix()
            newWidget.options.keyName = this.createKeyName(
              newWidget.type,
              keyNameSuffix
            );
            newWidget.options.keyNameSuffix = keyNameSuffix;
          }
        }
        if (newWidget.type === "dropdown") {
          let dropdownItem1 = this.copyNewFieldWidget(
            this.getFieldWidgetByType("dropdown-item")
          );
          dropdownItem1.options.label = "下拉按钮1";
          let dropdownItem2 = this.copyNewFieldWidget(
            this.getFieldWidgetByType("dropdown-item")
          );
          dropdownItem2.options.label = "下拉按钮2";
          newWidget.widgetList.push(dropdownItem1);
          newWidget.widgetList.push(dropdownItem2);
        }
        this.emitEvent("canvas-add-field", newWidget.options.name);
        return newWidget;
      },
      createKeyName(type, suffix) {
        let keyNameSuffix = suffix ? suffix : this.createKeyNameSuffix(type);
        let keyNamePrefix = this.getKeyNamePrefix(type);
        let keyName = null;
        if (keyNamePrefix) {
          keyName = keyNamePrefix + keyNameSuffix;
        } else {
          keyName = keyNameSuffix;
        }
        return keyName;
      },
      createKeyNameSuffix(type) {
        let suffix = createUUID();
        /*if (type === "vabUpload" || type === "baseAttachment") {
          let formCode = vueInstance.reportTemplate.formCode;
          suffix = formCode + "_" + suffix;
        }*/
        return suffix;
      },
      getKeyNamePrefix(type) {
        return keyNamePrefixMap[type] ?? null;
      },
      getFormCodePrefix(type) {
        let prefix = this.getKeyNamePrefix(type) || "";
        let attachmentPrefix =
          prefix + vueInstance.reportTemplate.formCode + "_";
        return attachmentPrefix;
      },
      createAttachmentSuffix() {
        let type = "vabUpload";
        return this.createKeyNameSuffix(type);
      },
      getAttachmentPrefix() {
        let type = "vabUpload";
        return this.getKeyNamePrefix(type);
      },
      getAttachmentFormCodePrefix() {
        let type = "vabUpload";
        let attachmentPrefix = this.getFormCodePrefix(type);
        return attachmentPrefix;
      },
      createAttachmentKeyName(suffix) {
        let type = "vabUpload";
        let keyName = this.createKeyName(type, suffix);
        return keyName;
      },
      copyNewContainerWidget(origin) {
        let newCon = baseRefUtil.deepClone(origin);
        let sourceType = newCon.type;
        newCon.type = newCon.targetType || newCon.type;
        newCon.sourceType = sourceType;
        newCon.id = newCon.type.replace(/-/g, "") + baseRefUtil.generateId();
        newCon.options.name = newCon.id;
        if ((newCon.options.keyNameEnabled = true)) {
          newCon.options.keyName = newCon.id;
        }
        if (newCon.hasOwnProperty("tableField")) {
          newCon.tableField = newCon.id; //表字段
        }
        if (newCon.type === "grid") {
          let newCol = baseRefUtil.deepClone(
            this.getContainerByType("grid-col")
          );
          let tmpId = baseRefUtil.generateId();
          newCol.id = "grid-col-" + tmpId;
          newCol.options.name = "gridCol" + tmpId;
          newCon.cols.push(newCol);
          //
          newCol = baseRefUtil.deepClone(newCol);
          tmpId = baseRefUtil.generateId();
          newCol.id = "grid-col-" + tmpId;
          newCol.options.name = "gridCol" + tmpId;
          newCon.cols.push(newCol);
        } else if (newCon.type === "table") {
          let newRow = {
            cols: [],
          };
          newRow.id = "table-row-" + baseRefUtil.generateId();
          newRow.merged = false;
          for (let i = 0; i < 4; i++) {
            let newCell = baseRefUtil.deepClone(
              this.getContainerByType("table-cell")
            );
            newCell.id = "table-cell-" + baseRefUtil.generateId();
            newCell.options.name = newCell.id;
            newCell.merged = false;
            newCell.options.colspan = 1;
            newCell.options.rowspan = 1;
            newRow.cols.push(newCell);
          }
          newCon.rows.push(newRow);
        } else if (newCon.type === "tab") {
          let newTabPane = baseRefUtil.deepClone(
            this.getContainerByType("tab-pane")
          );
          newTabPane.id = "tab-pane-" + baseRefUtil.generateId();
          newTabPane.options.name = "tab1";
          newTabPane.options.label = "tab 1";
          newCon.tabs.push(newTabPane);
        } else if (newCon.type === "data-table") {
          let add_button = this.copyNewFieldWidget(
            this.getFieldWidgetByType("add_button")
          );
          add_button.options.onClick =
            "this.getWidgetRef('" +
            newCon.options.name +
            "').openEditDialog();";
          newCon.buttons.push(add_button);
        } else if (newCon.type === "detail") {
          let buttonCon1 = this.copyNewFieldWidget(
            this.getFieldWidgetByType("reset_button")
          );
          buttonCon1.options.label = "重置";

          let buttonCon2 = this.copyNewFieldWidget(
            this.getFieldWidgetByType("save_button")
          );
          buttonCon2.options.label = "保存";

          newCon.widgetList.push(buttonCon1);
          newCon.widgetList.push(buttonCon2);

          let newCol = baseRefUtil.deepClone(
            this.getContainerByType("detail-pane")
          );
          let tmpId = baseRefUtil.generateId();
          newCol.id = "detail-pane-" + tmpId;
          newCol.options.name = "detailPane" + tmpId;
          newCol.options.label = "隐藏信息";
          newCol.options.hidden = true;

          let tableCon = this.copyNewContainerWidget(
            this.getContainerByType("table")
          );
          newCol.widgetList.push(tableCon);
          newCon.panes.push(newCol);

          newCol = baseRefUtil.deepClone(
            this.getContainerByType("detail-pane")
          );
          tmpId = baseRefUtil.generateId();
          newCol.id = "detail-pane-" + tmpId;
          newCol.options.name = "detailPane" + tmpId;
          newCol.options.label = "基础信息";

          tableCon = this.copyNewContainerWidget(
            this.getContainerByType("table")
          );
          newCol.widgetList.push(tableCon);
          newCon.panes.push(newCol);
          //
          newCol = baseRefUtil.deepClone(
            this.getContainerByType("detail-pane")
          );
          tmpId = baseRefUtil.generateId();
          newCol.id = "detail-pane-" + tmpId;
          newCol.options.name = "detailPane" + tmpId;
          newCol.options.label = "明细信息";
          newCol.options.tableRef = tableCon.id;
          let dataTableCon = this.copyNewContainerWidget(
            this.getContainerByType("data-table")
          );
          newCol.widgetList.push(dataTableCon);
          newCol.options.tableRef = dataTableCon.id;

          let buttonCon3 = this.copyNewFieldWidget(
            this.getFieldWidgetByType("button")
          );
          buttonCon3.options.label = "新增";
          buttonCon3.options.icon = "el-icon-search";
          // buttonCon3.options.onClick = "this.getWidgetRef('" + dataTableCon.options.name + "').addTableData();"
          buttonCon3.options.clickBindEvent = "2";
          Object.assign(buttonCon3.options.addTableDataConfig, {
            tableRef: dataTableCon.options.name,
          });

          newCol.buttonWidgetList.push(buttonCon3);
          newCon.panes.push(newCol);

          newCol = baseRefUtil.deepClone(
            this.getContainerByType("detail-pane")
          );
          tmpId = baseRefUtil.generateId();
          newCol.id = "detail-pane-" + tmpId;
          newCol.options.name = "detailPane" + tmpId;
          newCol.options.label = "附件信息";
          let vabUploadCon = this.copyNewFieldWidget(
            this.getFieldWidgetByType("vabUpload")
          ); //vabUpload
          newCol.widgetList.push(vabUploadCon);
          newCon.panes.push(newCol);
        } else if (newCon.type === "table-column") {
          newCon.options.label = "tableColumn";
        } else if (newCon.type === "h5-card") {
          let newCol = baseRefUtil.deepClone(
            this.getContainerByType("h5-card-pane")
          );
          let tmpId = baseRefUtil.generateId();
          newCol.id = "h5-card-pane-" + tmpId;
          newCol.options.name = "h5CardPane" + tmpId;
          newCol.options.label = "基本信息";
          newCon.panes.push(newCol);
        } else if (newCon.type === "detail-h5") {
          /*let newTab = this.copyNewContainerWidget(this.getContainerByType('tab'));
          newCon.panes.push(newTab)

          newTab.options.tabClass = "tab-box";
          let newTabPane = newTab.tabs[0];
          newTabPane.options.label = '基本信息';*/

          //基本信息
          let newCard = this.copyNewContainerWidget(
            this.getContainerByType("h5-card")
          );
          // newTabPane.widgetList.push(newCard);
          newCon.panes.push(newCard);

          //明细信息
          let newCardPane = this.copyNewContainerWidget(
            this.getContainerByType("h5-card-pane")
          );
          newCardPane.options.label = "明细信息";
          newCard.panes.push(newCardPane);

          //列表
          let listH5 = this.copyNewContainerWidget(
            this.getContainerByType("list-h5")
          ); //vabUpload
          newCardPane.widgetList.push(listH5);

          //列表新增按钮
          let buttonCon = this.copyNewFieldWidget(
            this.getFieldWidgetByType("button")
          );
          buttonCon.options.label = "新增";
          buttonCon.options.icon = "el-icon-search";
          buttonCon.options.onClick =
            "this.getWidgetRef('" + listH5.options.name + "').addTableData();";
          newCardPane.buttonWidgetList.push(buttonCon);

          //列表行查看按钮
          buttonCon = this.copyNewFieldWidget(
            this.getFieldWidgetByType("button")
          );
          buttonCon.options.rowFlag = true;
          buttonCon.options.label = "查看";
          buttonCon.options.icon = "el-icon-edit";
          buttonCon.options.onClick =
            "this.getWidgetRef('" +
            listH5.options.name +
            "').openRowDetailDialog(row);";
          listH5.lineButtons.push(buttonCon);

          //附件信息
          newCardPane = this.copyNewContainerWidget(
            this.getContainerByType("h5-card-pane")
          );
          newCardPane.options.label = "附件信息";
          newCard.panes.push(newCardPane);

          let vabUploadCon = this.copyNewFieldWidget(
            this.getFieldWidgetByType("vabUpload")
          ); //vabUpload
          newCardPane.widgetList.push(vabUploadCon);
        } else if (newCon.type === "h5-table") {
          for (let i = 0; i < 4; i++) {
            let newRow = {
              cols: [],
            };
            newRow.id = "table-row-" + baseRefUtil.generateId();
            newRow.merged = false;

            let newCell = baseRefUtil.deepClone(
              this.getContainerByType("h5-table-cell")
            );
            newCell.id = "table-cell-" + baseRefUtil.generateId();
            newCell.options.name = newCell.id;
            newCell.merged = false;
            newCell.options.colspan = 1;
            newCell.options.rowspan = 1;
            newRow.cols.push(newCell);

            let newInput = this.copyNewFieldWidget(
              this.getFieldWidgetByType("input")
            );
            newCell.widgetList.push(newInput);

            newCon.rows.push(newRow);
          }
        } else if (newCon.type === "tree-pane") {
          //初始化列表
          let dataTableCon = this.copyNewContainerWidget(
            this.getContainerByType("data-table")
          );
          dataTableCon.options.showPagination = true;
          dataTableCon.options.showSearchArea = true;
          dataTableCon.options.isQueryTable = true;
          dataTableCon.options.tableHeight = "auto";
          dataTableCon.options.accessReturnType = "2";

          newCon.widgetList.push(dataTableCon);

          let addButton = this.copyNewFieldWidget(
            this.getFieldWidgetByType("add_button")
          );
          addButton.options.onClick =
            "this.getWidgetRef('" +
            dataTableCon.options.name +
            "').openEditDialog();";
          dataTableCon.buttons.push(addButton);

          let tableExportButton = this.copyNewFieldWidget(
            this.getFieldWidgetByType("table-export-button")
          );
          tableExportButton.options.tableExportParam =
            "return { title: '导出', targetRef: '" +
            dataTableCon.options.name +
            "'}";
          dataTableCon.buttons.push(tableExportButton);

          let searchInput = this.copyNewFieldWidget(
            this.getFieldWidgetByType("input")
          );
          searchInput.options.disabled = true;
          searchInput.options.label = newCon.options.treeLabel;
          dataTableCon.widgetList.push(searchInput);

          let searchIdInput = this.copyNewFieldWidget(
            this.getFieldWidgetByType("input")
          );
          searchIdInput.options.disabled = true;
          searchIdInput.options.hidden = true;
          searchIdInput.options.label = `隐藏${newCon.options.treeLabel}ID`;
          dataTableCon.widgetList.push(searchIdInput);

          //列表重置的时候，忽略该字段
          dataTableCon.options.onResetTable = `this.resetEvent({\n  ignoreFields:['${searchInput.options.name}', '${searchIdInput.options.name}']\n});`;

          //初始化树
          let treeCon = this.copyNewContainerWidget(
            this.getContainerByType("tree")
          );
          treeCon.options.onNodeClick = `this.getWidgetRef('${searchInput.options.name}').setValue(data.label);\nthis.getWidgetRef('${searchIdInput.options.name}').setValue(data.id);\nthis.getWidgetRef('${dataTableCon.options.name}').searchEvent();`;

          newCon.options.onTreeLabelClick = `this.getWidgetRef('${treeCon.options.name}').setCurrentKey();\nthis.getWidgetRef('${searchInput.options.name}').setValue(null);\nthis.getWidgetRef('${searchIdInput.options.name}').setValue(null);\nthis.getWidgetRef('${dataTableCon.options.name}').searchEvent();`;
          newCon.leftWidgetList.push(treeCon);
        }
        //newCon.options.customClass = []

        delete newCon.displayName;
        return newCon;
      },

      addContainerByDbClick(container) {
        let newCon = this.copyNewContainerWidget(container);
        this.widgetList.push(newCon);
        this.setSelected(newCon);
      },

      addFieldByDbClick(widget) {
        let newWidget = this.copyNewFieldWidget(widget);
        if (!!this.selectedWidget && this.selectedWidget.type === "tab") {
          //获取当前激活的tabPane
          let activeTab = this.selectedWidget.tabs[0];
          this.selectedWidget.tabs.forEach((tabPane) => {
            if (!!tabPane.options.active) {
              activeTab = tabPane;
            }
          });

          !!activeTab && activeTab.widgetList.push(newWidget);
        } else if (!!this.selectedWidget && !!this.selectedWidget.widgetList) {
          this.selectedWidget.widgetList.push(newWidget);
        } else {
          this.widgetList.push(newWidget);
        }

        this.setSelected(newWidget);
        this.emitEvent("canvas-add-field", newWidget.options.name),
          this.emitHistoryChange();
      },
      deletePaneOfDetail(gridWidget, colIdx) {
        if (!!gridWidget && !!gridWidget.panes) {
          gridWidget.panes.splice(colIdx, 1);
        }
      },
      cloneDetailPane(widget, parentWidget) {
        let newGridCol = baseRefUtil.deepClone(
          this.getContainerByType("detail-pane")
        );
        let tmpId = baseRefUtil.generateId();
        newGridCol.id = "detail-pane-" + tmpId;
        newGridCol.options.name = "detailPane" + tmpId;
        newGridCol.options.label = widget.options.label;
        parentWidget.panes.push(newGridCol);
      },
      cloneH5CardPanePane(widget, parentWidget) {
        let newGridCol = baseRefUtil.deepClone(
          this.getContainerByType("h5-card-pane")
        );
        let tmpId = baseRefUtil.generateId();
        newGridCol.id = "h5-card-pane-" + tmpId;
        newGridCol.options.name = "h5CardPane" + tmpId;
        newGridCol.options.label = widget.options.label;
        parentWidget.panes.push(newGridCol);
      },

      addNewPaneOfDetail(gridWidget) {
        const cols = gridWidget.panes;
        let newGridCol = baseRefUtil.deepClone(
          this.getContainerByType("detail-pane")
        );
        let tmpId = baseRefUtil.generateId();
        newGridCol.id = "detail-pane-" + tmpId;
        newGridCol.options.name = "detailPane" + tmpId;
        newGridCol.options.label = "detailPane" + tmpId;
        gridWidget.panes.push(newGridCol);
      },

      deleteColOfGrid(gridWidget, colIdx) {
        if (!!gridWidget && !!gridWidget.cols) {
          gridWidget.cols.splice(colIdx, 1);
        }
      },

      addNewColOfGrid(gridWidget) {
        const cols = gridWidget.cols;
        let newGridCol = baseRefUtil.deepClone(
          this.getContainerByType("grid-col")
        );
        let tmpId = baseRefUtil.generateId();
        newGridCol.id = "grid-col-" + tmpId;
        newGridCol.options.name = "gridCol" + tmpId;
        if (!!cols && cols.length > 0) {
          let spanSum = 0;
          cols.forEach((col) => {
            spanSum += col.options.span;
          });

          if (spanSum >= 24) {
            //this.$message.info('列栅格之和超出24')
            console.log("列栅格之和超出24");
            gridWidget.cols.push(newGridCol);
          } else {
            newGridCol.options.span = 24 - spanSum > 12 ? 12 : 24 - spanSum;
            gridWidget.cols.push(newGridCol);
          }
        } else {
          gridWidget.cols = [newGridCol];
        }
      },

      addTabPaneOfTabs(tabsWidget) {
        const tabPanes = tabsWidget.tabs;
        let newTabPane = baseRefUtil.deepClone(
          this.getContainerByType("tab-pane")
        );
        newTabPane.id = "tab-pane-" + baseRefUtil.generateId();
        newTabPane.options.name = newTabPane.id;
        newTabPane.options.label = "tab " + (tabPanes.length + 1);
        tabPanes.push(newTabPane);
      },

      deleteTabPaneOfTabs(tabsWidget, tpIdx) {
        tabsWidget.tabs.splice(tpIdx, 1);
      },

      addDropdownItem(tabsWidget) {
        const tabPanes = tabsWidget.widgetList;
        let newTabPane = baseRefUtil.deepClone(
          this.getFieldWidgetByType("dropdown-item")
        );
        newTabPane.id = "dropdown-item-" + baseRefUtil.generateId();
        newTabPane.options.name = newTabPane.id;
        newTabPane.options.label = "dropdown-item " + (tabPanes.length + 1);
        tabPanes.push(newTabPane);
      },

      deleteDropdownItem(tabsWidget, tpIdx) {
        tabsWidget.widgetList.splice(tpIdx, 1);
      },

      emitEvent(evtName, evtData) {
        //用于兄弟组件发射事件
        this.vueInstance.$emit(evtName, evtData);
      },

      handleEvent(evtName, callback) {
        //用于兄弟组件接收事件
        this.vueInstance.$on(evtName, (data) => callback(data));
      },

      setCssClassList(cssClassList) {
        this.cssClassList = cssClassList;
      },

      getCssClassList() {
        return this.cssClassList;
      },

      registerFormWidget(formWidget) {
        this.formWidget = formWidget;
      },

      initHistoryData() {
        this.loadFormContentFromStorage();
        this.historyData.index++;
        this.historyData.steps[this.historyData.index] = {
          widgetList: baseRefUtil.deepClone(this.widgetList),
          formConfig: baseRefUtil.deepClone(this.formConfig),
        };
      },

      emitHistoryChange() {
        //console.log('------------', 'Form history changed!')

        if (this.historyData.index === this.historyData.maxStep - 1) {
          this.historyData.steps.shift();
        } else {
          this.historyData.index++;
        }

        this.historyData.steps[this.historyData.index] = {
          widgetList: baseRefUtil.deepClone(this.widgetList),
          formConfig: baseRefUtil.deepClone(this.formConfig),
        };

        this.saveFormContentToStorage();

        if (this.historyData.index < this.historyData.steps.length - 1) {
          this.historyData.steps = this.historyData.steps.slice(
            0,
            this.historyData.index + 1
          );
        }

        //console.log('history', this.historyData.index)
      },

      saveCurrentHistoryStep() {
        this.historyData.steps[this.historyData.index] = baseRefUtil.deepClone({
          widgetList: this.widgetList,
          formConfig: this.formConfig,
        });

        this.saveFormContentToStorage();
      },

      undoHistoryStep() {
        if (this.historyData.index !== 0) {
          this.historyData.index--;
        }
        //console.log('undo', this.historyData.index)

        this.widgetList = baseRefUtil.deepClone(
          this.historyData.steps[this.historyData.index].widgetList
        );
        this.formConfig = baseRefUtil.deepClone(
          this.historyData.steps[this.historyData.index].formConfig
        );
      },

      redoHistoryStep() {
        if (this.historyData.index !== this.historyData.steps.length - 1) {
          this.historyData.index++;
        }
        //console.log('redo', this.historyData.index)

        this.widgetList = baseRefUtil.deepClone(
          this.historyData.steps[this.historyData.index].widgetList
        );
        this.formConfig = baseRefUtil.deepClone(
          this.historyData.steps[this.historyData.index].formConfig
        );
      },

      undoEnabled() {
        return this.historyData.index > 0 && this.historyData.steps.length > 0;
      },

      redoEnabled() {
        return this.historyData.index < this.historyData.steps.length - 1;
      },

      saveFormContentToStorage() {
        window.localStorage.setItem(
          "widget__list__backup",
          JSON.stringify(this.widgetList)
        );
        window.localStorage.setItem(
          "form__config__backup",
          JSON.stringify(this.formConfig)
        );
      },

      loadFormContentFromStorage() {
        let widgetListBackup = window.localStorage.getItem(
          "widget__list__backup"
        );
        if (!!widgetListBackup) {
          this.widgetList = JSON.parse(widgetListBackup);
        }

        let formConfigBackup = window.localStorage.getItem(
          "form__config__backup"
        );
        if (!!formConfigBackup) {
          //this.formConfig = JSON.parse(formConfigBackup)
          baseRefUtil.overwriteObj(
            this.formConfig,
            JSON.parse(formConfigBackup)
          ); /* 用=赋值，会导致inject依赖注入的formConfig属性变成非响应式 */
        }
      },
      getColumnWidget(row, isEdit) {
        //获取
        let formatS = isEdit ? row.editFormatS : row.formatS;
        let type = columnFormatMap[formatS];
        if (!type) return null;
        if (isEdit) {
          if (row.editWidget) {
            return row.editWidget;
          }
          if (row.editColumnOption) {
            let fieldWidget = this.copyNewFieldWidget(
              this.getFieldWidgetByType(type)
            );
            fieldWidget.options = row.editColumnOption;
            return fieldWidget;
          }
        } else {
          if (row.widget) {
            return row.widget;
          }
          if (row.columnOption) {
            let fieldWidget = this.copyNewFieldWidget(
              this.getFieldWidgetByType(type)
            );
            fieldWidget.options = row.columnOption;
            return fieldWidget;
          }
        }
        return this.createColumnWidget(row, isEdit);
      },
      getIsFileWidget(type) {
        return type === "vabUpload" || type === "baseAttachment";
      },
      createColumnWidget(row, isEdit) {
        let formatS = isEdit ? row.editFormatS : row.formatS;
        let type = columnFormatMap[formatS];
        if (!type) return null;

        let columnSelectedWidget = null;
        if (type) {
          columnSelectedWidget = this.copyNewFieldWidget(
            this.getFieldWidgetByType(type)
          );

          if (columnSelectedWidget.options.hasOwnProperty("required")) {
            columnSelectedWidget.options.required = row.required || false;
          }

          if ("editDelete" === formatS) {
            columnSelectedWidget.options.prefixIcon = "el-icon-delete";
            columnSelectedWidget.options.label = "删除";
            columnSelectedWidget.options.labelHidden = true;
            columnSelectedWidget.options.hiddenByWf = true;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nlet tableRef = this.getWidgetRef(this.parentWidget.options.name);\ntableRef.deleteRow(tableParam.row,tableParam.rowIndex);";
          } else if ("editButton" === formatS) {
            columnSelectedWidget.options.prefixIcon = "el-icon-edit";
            columnSelectedWidget.options.label = "查看";
            columnSelectedWidget.options.labelHidden = true;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nlet tableRef = this.getWidgetRef(this.parentWidget.options.name);\ntableRef.openEditDialog(tableParam.row)";
          } else if ("addSiblingEditRow" === formatS) {
            columnSelectedWidget.options.prefixIcon = "el-icon-plus";
            columnSelectedWidget.options.label = "新增兄弟节点";
            columnSelectedWidget.options.labelHidden = false;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nthis.getParentTarget().addSiblingTreeRow(null,tableParam);";
          } else if ("addChildTreeRow" === formatS) {
            columnSelectedWidget.options.prefixIcon = "el-icon-plus";
            columnSelectedWidget.options.label = "新增子节点";
            columnSelectedWidget.options.labelHidden = false;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nthis.getParentTarget().addChildTreeRow(null,tableParam);";
          } else if ("moveUpRow" === formatS) {
            columnSelectedWidget.options.label = "↑上移";
            columnSelectedWidget.options.labelHidden = false;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nthis.getParentTarget().moveUpRow(tableParam);";
          } else if ("moveDownRow" === formatS) {
            columnSelectedWidget.options.label = "↓下移";
            columnSelectedWidget.options.labelHidden = false;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nthis.getParentTarget().moveDownRow(tableParam);";
          } else if ("removeTreeRow" === formatS) {
            columnSelectedWidget.options.prefixIcon = "el-icon-delete";
            columnSelectedWidget.options.label = "删除";
            columnSelectedWidget.options.labelHidden = true;
            columnSelectedWidget.options.onClick =
              "let tableParam = this.tableParam;\nthis.getParentTarget().removeTreeRow(tableParam);";
          }

          if (columnSelectedWidget.options.hasOwnProperty("keyName")) {
            if (!this.getIsFileWidget(type)) {
              columnSelectedWidget.options.keyName = row.prop;
            }

            columnSelectedWidget.options.keyNameEnabled = true;
          } else {
            columnSelectedWidget.options.name = row.prop;
          }

          if (type === "dropdown") {
            columnSelectedWidget.options.dropdownType = "link";
          } else if (type !== "button" && type !== "a-link") {
            columnSelectedWidget.options.label = row.label;
            columnSelectedWidget.options.labelHidden = true;
          }
        }
        return columnSelectedWidget;
      },
    };
  };
})();

export const createDesigner = createDesigner0;
