/* eslint-disable */

import lodash from "lodash";
import moment from "moment";
import { Modal, notification } from "antd-v4";
import { message } from "@/utils/common/message";
import * as commonUtils from "@/utils/utils";
import * as commonFunc from "@/components/Common/commonFunc";
import commonConfig from "@/utils/config";
import * as commonServices from "@/services/services";
import * as commonBusiness from "@/components/Common/commonBusiness";
import FaceDetect from "@/components/FaceDetect";

let step = 1; // 步骤计数
let exesqlTodo = []; // 最后需要一起执行的sql
let saveDataTodo = []; // 最后需要一起保存的数据
let sendMsgDataTodo = {}; // 最后需要一起发送的消息
let refreshTableList = []; // 最后需要刷新的表格
let refreshParentTableList = []; // 最后需要刷新的父页面表格
let possibleErrorList = []; // 可能的错误
let changeTabName = "";

// 获取指令对应的方法
const getOprFun = instruct => {
  const { opr } = instruct;
  outputInfo(instruct);
  const myMap = {
    fordo: handleForDo,
    ifdo: handleIfDo,

    filter: handleFilter,
    copy: handleCopy,
    add: instruct.dataset || !instruct.srcDataset ? handleAddNew : handleAdd,
    del: handleDel,
    emptyAll: handleEmptyAll,
    opensql: handleOpenSql,
    exesql: handleExeSql,
    edit: handleEdit,
    console: handleConsole,
    msg: handleMsg,
    sendmsg: handleSendMsg,

    print: handlePrint,
    faceauth: handleFaceAuth,
    popup: handlePopup,
    save: commonUtils.isNotEmptyArr(instruct.data) ? handleMesSave : handleSave,
    refresh: handleRefresh,
    closepop: handleClosePop,
    procedure: handleProcedure,
    changetab: handleChangeTab,
    poprepair: handlePoprepair,
    newempty: handleNewEmpty,
    "": () => ({})
  };

  const result = myMap[opr] || myMap[""];
  return result;
};

// 提示信息
const showMsg = value => {
  let params = { type: "info", content: "" };
  if (typeof value === "object") {
    params = {
      ...params,
      ...value
    };
  } else {
    params.content = value;
  }

  const { type, content } = params;
  const title = type === "error" ? "指令集错误信息" : "指令集提示信息";

  Modal[type]({
    width: 1000,
    title: title,
    content: <div>{content}</div>,
    okText: "知道了"
  });
};

// 基础校验
const instructCheck = props => {
  let { btnConfig } = props;

  if (!btnConfig) {
    const { btnName, masterConfig } = props;
    btnConfig = masterConfig?.gdsconfigformslave?.find(
      item => item.sControlName === btnName
    );
  }

  if (!btnConfig) {
    showMsg("没有找到按钮配置！");
    return false;
  }

  const { sInstruct: sInstructStr } = btnConfig;
  if (!sInstructStr) {
    showMsg("指令集未配置！");
    return false;
  }

  const sInstruct = commonUtils.convertStrToObj(sInstructStr, []);

  if (!sInstruct.length) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>指令集格式错误！</div>
          <div>错误指令集内容：</div>
          <div>{sInstructStr}</div>
        </div>
      )
    });
    return false;
  }

  return sInstruct;
};

// 添加额外数据
const addExtraData = props => {
  // 转换页面定义的表名和sGrd
  const { tableNameCompareJson = {} } = props;
  if (commonUtils.isNotEmptyObject(tableNameCompareJson)) {
    Object.keys(tableNameCompareJson).forEach(key => {
      const value = tableNameCompareJson[key];
      if (props[`${value}Data`]) {
        props[`${key}Data`] = props[`${value}Data`];
        props[`${key}Config`] = props[`${value}Config`];
        props[`${key}DelData`] = props[`${value}DelData`];
        props[`${key}SelectedRowKeys`] = props[`${value}SelectedRowKeys`];
      }
    });
  }

  // 获取当前选中机台任务数据
  props.currentSelectedMachineTask =
    props.app.globalData?.currentSelectedMachineTaskDataRow;

  // 获取当前开工机台任务数据
  props.currentStartWorkMachineTask =
    props.app.globalData?.currentStartWorkMachineTaskDataRow;

  // 获取当前工单信息数据
  props.currentWorkOrderInfo = props.app.globalData?.currentWorkOrderInfo;
};

// 根据datasetList过滤出要保存到页面的数据
const filterDataByDatasetList = (props, addState) => {
  const { tableNameCompareJson = {} } = props;
  const keyList = Object.keys(tableNameCompareJson);

  const { datasetList = [] } = addState;
  const addStateNew = {};
  datasetList.forEach(tableNameOld => {
    const tableName = keyList.includes(tableNameOld)
      ? tableNameCompareJson[tableNameOld]
      : tableNameOld;

    // 获取新增修改数据
    const tableData = addState[`${tableNameOld}Data`];
    if (tableData) {
      addStateNew[`${tableName}Data`] = tableName.includes("master")
        ? tableData[0]
        : tableData;
    }

    // 获取删除的数据
    const tableDelData = addState[`${tableNameOld}DelData`];
    if (tableDelData) {
      addStateNew[`${tableName}DelData`] = tableDelData;
    }
  });
  return addStateNew;
};

/**********************************************************  入口函数  **********************************************************/
const instructSet = async props => {
  if (window.instructSetLock) return; // 防止连点
  try {
    window.instructSetLock = true;
    await instructSetInit(props);
  } catch (error) {
    console.log("=====", error);
    props.onSaveState({ pageLoading: false });
  }
  setTimeout(() => {
    window.instructSetLock = false;
  }, 500);
};

// 入口函数 -> 初始化
const instructSetInit = async props => {
  step = 1;
  exesqlTodo = [];
  saveDataTodo = [];
  sendMsgDataTodo = {};
  refreshTableList = [];
  refreshParentTableList = [];
  possibleErrorList = [];
  changeTabName = "";

  // 基础校验
  const sInstruct = instructCheck(props);
  if (!sInstruct) return;

  // 添加额外数据
  addExtraData(props);

  props.onSaveState({ pageLoading: true });

  console.log("=====sInstruct", sInstruct);

  let addState = {};

  for (let i = 0; i < sInstruct.length; i++) {
    const instruct = sInstruct[i];
    const operationFun = getOprFun(instruct);
    const resultData = await operationFun({ ...props, ...addState }, instruct);

    addState = {
      ...addState,
      ...resultData
    };
  }

  // 是否要关闭弹窗
  const bClosePop = addState.closePop;

  // 根据datasetList过滤出要保存到页面的数据
  const addStateNew = filterDataByDatasetList(props, addState);

  console.log("=====保存到页面的数据", addStateNew);
  console.log("=====最后需要一起执行的sql", exesqlTodo);
  if (possibleErrorList.length) {
    console.log("=====可能存在的问题=====");
    possibleErrorList.forEach(({ instruct, content }, index) => {
      console.log(`=====${index + 1}、指令集`, instruct, content);
    });
  }

  handleExeSqlAll(props, () => {
    handleMesSaveAll(props, () => {
      handleSendMsgAll(props);

      // const { showName } = props.btnConfig;
      // notification.success({
      //   message: `【${showName}】指令集执行完成！`,
      //   placement: "topRight",
      //   duration: 3
      // });
      console.log("=====页面需要刷新的表格：", refreshTableList);
      props.onSaveState({
        ...addStateNew,
        refreshTableList,
        pageLoading: false
      });

      console.log("=====父页面需要刷新的表格：", refreshParentTableList);
      if (refreshParentTableList.length) {
        const { parentProps } = props;
        parentProps.onSaveState({
          refreshTableList: refreshParentTableList
        });
      }

      if (bClosePop) {
        const { app } = props;
        setTimeout(() => {
          app.globalFun.onCloseCommonModal({ type: "commonModal" });
        }, 300);
      }

      if (changeTabName) {
        utils.changeTabName();
      }

      props.callback && props.callback();
    });
  });
};

/**********************************************************  指令集  **********************************************************/

// 循环操作
const handleForDo = async (props, instructTotal) => {
  const { dataset, fordoset = `${dataset}One`, foropr } = instructTotal;
  const { [`${dataset}Data`]: tableData } = props;

  // 最后的返回值
  let forOneResult = {};
  for (let i = 0; i < tableData.length; i++) {
    const fordosetName = fordoset;
    const fordosetData = tableData[i];

    for (let j = 0; j < foropr.length; j++) {
      const instruct = foropr[j];
      const operationFun = getOprFun(instruct);
      forOneResult = {
        ...forOneResult,
        ...(await operationFun(
          { ...props, fordosetName, fordosetData, ...forOneResult },
          instruct
        ))
      };
    }
  }

  console.log("=====【fordo】返回结果: ", forOneResult);
  return forOneResult;
};

// 条件操作
const handleIfDo = async (props, instruct) => {
  const { fordosetName, fordosetData } = props;
  const { conditions, dataset = "" } = instruct;

  const datasetListExtra = {};
  dataset
    .split(",")
    .filter(item => item)
    .forEach(item => {
      const [tableName, filterType] = item.split("@");
      const filterData = utils.getFilterData(props, tableName, filterType);
      datasetListExtra[tableName] = filterData[0];
    });

  let result = {};
  for (let i = 0; i < conditions.length; i++) {
    const item = conditions[i];
    const { condition, commands } = item;
    // 判断是否满足条件
    const bMatch = utils.bMatchCondition(props, item, datasetListExtra);
    if (!bMatch) continue;

    console.log("=====commands", commands);
    let ifDoResult = {};
    for (let j = 0; j < commands.length; j++) {
      // if (j > 10) continue;
      const command = commands[j];
      const operationFun = getOprFun(command);
      const resultData = await operationFun(
        { ...props, ...ifDoResult },
        command
      );
      if (resultData.stop) {
        continue;
      }
      ifDoResult = {
        ...ifDoResult,
        ...resultData
      };
    }
    result = { ...result, ...ifDoResult };
    console.log("=====ifDoResult", ifDoResult);
  }

  return result;
};

// 过滤操作
const handleFilter = (props, instruct) => {
  const {
    srcDataset,
    newDataset,
    fordoset = `${srcDataset}One`,
    dataset,
    condition
  } = instruct;

  // 源数据
  const [tableName, filterType] = srcDataset.split("@");
  const srcData = utils.getFilterData(props, tableName, filterType);

  // 过滤后数据
  const newData = srcData.filter(item =>
    utils.bMatchCondition(props, instruct, {
      [fordoset]: item
    })
  );

  const result = {
    [`${newDataset}Data`]: newData
  };

  outputResult(result);
  return result;
};

/************************* 复制指令 copy ************************/
const handleCopy = (props, instruct) => {
  const { srcDataset, newDataset } = instruct;

  const { dataList = [] } = utils.getDatasetDataList(
    props,
    instruct,
    "srcDataset"
  );
  let srcData = dataList[0] || [];

  // 如果数据源是循环的那条数据
  const { fordosetName, fordosetData } = props;
  if (fordosetName && srcDataset === fordosetName && fordosetData) {
    srcData = [fordosetData];
  }

  if (!srcData.length) {
    showMsg({
      content: "error",
      content: (
        <div>
          <div>{`【${srcDataset}】数据源为空`}</div>
          <div>请检查该复制指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error(`【${srcDataset}】数据源为空`);
  }

  // 获取赋值后的数据
  let srcDataNew = utils.getDataAfterAssign(props, instruct, srcData);

  srcDataNew = srcDataNew.map(item => ({
    sParentId: props.masterData?.sId || props.currentId || "",
    ...item,
    sId: commonUtils.createSid(),
    handleType: "add"
  }));

  const resultData = [...srcDataNew];

  const result = { [`${newDataset}Data`]: resultData };

  outputResult(result);
  return result;
};

/************************* 新增指令(旧)（没有dataset） add ************************/
const handleAdd = (props, instruct) => {
  const { desDataset, srcDataset } = instruct;
  const {
    [`${srcDataset}Data`]: srcData = [],
    [`${desDataset}Data`]: desData = [],
    datasetList = []
  } = props;

  const datasetListNew = datasetList.includes(desDataset)
    ? datasetList
    : [...datasetList, desDataset];

  const srcDataNew = srcData.map(item => ({
    sParentId: props.masterData?.sId || props.currentId || "",
    ...item,
    sId: commonUtils.createSid(),
    handleType: "add"
  }));

  const result = {
    [`${desDataset}Data`]: [...desData, ...srcDataNew],
    datasetList: datasetListNew
  };
  outputResult(result);
  return result;
};
/************************* 新增指令(新)（有dataset） add ************************/
const handleAddNew = (props, instruct) => {
  const { desDataset, dataset, sValue = "" } = instruct;

  if (!desDataset) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>被新增的数据集desDataset不能为空！</div>
          <div>请检查该新增指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error("被新增的数据集desDataset不能为空！");
  } else if (desDataset.includes("@") || desDataset.includes(",")) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>被新增的数据集desDataset不支持@或,写法！</div>
          <div>请检查该新增指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error("被新增的数据集desDataset不支持@或,写法！");
  }

  const {
    dataobj = {},
    dataNameList = [],
    dataList = []
  } = utils.getDatasetDataList(props, instruct);

  let dataLengthList = [1];
  // 校验是否有空数据集
  const dataLengthListNew = dataList.map((item = [], index) => {
    if (item.length === 0) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>{`【${dataNameList[index]}】数据源为空`}</div>
            <div>请检查该新增指令集：</div>
            <div>{JSON.stringify(instruct)}</div>
          </div>
        )
      });
      throw new Error(`【${dataNameList[index]}】数据源为空`);
    }
    return item.length;
  });
  dataLengthList = dataLengthListNew.length
    ? dataLengthListNew
    : dataLengthList;

  // 校验所有数据集的长度是否一致
  const dataLengthSet = new Set(dataLengthList);
  if (dataLengthSet.size !== 1) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>{`【${dataset}】数据源长度不一致`}</div>
          <div>请检查该新增指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
          <div>过滤后的数据为：</div>
          <div>{JSON.stringify(dataobj)}</div>
        </div>
      )
    });
    throw new Error(`【${dataset}】数据源长度不一致`);
  }

  const addData = [];
  for (let i = 0; i < dataLengthList[0]; i++) {
    let rowData = {};

    // 优先级低的默认参数
    const rowDataAdd0 = {
      sParentId: props.masterData?.sId || props.currentId || ""
    };
    const rowDataAdd = {
      handleType: "add",
      sId: commonUtils.createSid()
    };

    const dataOneObj = dataList.reduce((prev, item, index) => {
      return {
        ...prev,
        [dataNameList[index]]: item[i]
      };
    }, {});

    if (!sValue || sValue === "*") {
      // 全部字段
      rowData = {
        ...rowDataAdd0,
        ...Object.values(dataOneObj).reduce((prev, item) => {
          return {
            ...prev,
            ...item
          };
        }, {}),
        ...rowDataAdd
      };
    } else {
      // 指定字段
      rowData = utils.getRowDataByValue(
        props,
        instruct,
        dataOneObj,
        dataNameList
      );

      rowData = {
        ...rowDataAdd0,
        ...rowData,
        ...rowDataAdd
      };
    }

    addData.push(rowData);
  }

  const { [`${desDataset}Data`]: oldData = [], datasetList = [] } = props;
  const datasetListNew = datasetList.includes(desDataset)
    ? datasetList
    : [...datasetList, desDataset];
  const result = {
    datasetList: datasetListNew,
    [`${desDataset}Data`]: [...oldData, ...addData]
  };
  outputResult(result);

  return result;
};

// 删除指令
const handleDel = (props, instruct) => {
  const { desDataset } = instruct;

  const [tableName] = desDataset.split("@");
  const fordoset = `${tableName}One`;

  const {
    [`${tableName}Data`]: data = [],
    [`${tableName}DelData`]: delData = [],
    datasetList = []
  } = props;

  const { dataList = [] } = utils.getDatasetDataList(
    props,
    instruct,
    "desDataset"
  );

  const filterData = dataList[0];
  if (commonUtils.isEmptyArr(filterData)) {
    possibleErrorList.push({
      instruct,
      content: `【${tableName}】过滤后的数据为空`
    });
  }

  const delDataNew = filterData
    .filter(item =>
      utils.bMatchCondition(props, instruct, {
        [fordoset]: item
      })
    )
    .map(item => ({
      ...item,
      handleType: "del"
    }));

  let result = {};
  if (commonUtils.isNotEmptyArr(delDataNew)) {
    const dataNew = data.filter(
      item => !delDataNew.some(del => del.sId === item.sId)
    );

    const datasetListNew = datasetList.includes(tableName)
      ? datasetList
      : [...datasetList, tableName];

    result = {
      datasetList: datasetListNew,
      [`${tableName}Data`]: dataNew,
      [`${tableName}DelData`]: [...delData, ...delDataNew]
    };
  }
  outputResult(result);
  return result;
};

// 清空数据集
const handleEmptyAll = (props, instruct) => {
  const { desDataset } = instruct;
  const list = desDataset.split(",");

  const { datasetList = [] } = props;

  const datasetListNew = [...datasetList];

  const result = {};
  list.forEach(tableName => {
    result[`${tableName}Data`] = [];
    if (!datasetListNew.includes(tableName)) {
      datasetListNew.push(tableName);
    }
  });

  result.datasetList = datasetListNew;

  outputResult(result);
  return result;
};

/************************* 编辑指令 edit  todo ************************/
const handleEdit = (props, instruct) => {
  const editData = utils.getDataAfterConditionAndAssign(
    props,
    instruct,
    "desDataset"
  );

  const editDataNew = editData.map(item => ({
    ...item,
    handleType: item.handleType || "update"
  }));

  const { datasetList = [] } = props;
  const { desDataset } = instruct;

  const [tableName] = desDataset.split("@");
  let tableData = props[`${tableName}Data`];

  tableData = Array.isArray(tableData) ? tableData : [tableData];

  const tableDataNew = tableData.map(rowData => {
    const iIndex = editDataNew.findIndex(item => item.sId === rowData.sId);
    if (iIndex !== -1) {
      return editDataNew[iIndex];
    } else {
      return rowData;
    }
  });

  const datasetListNew = datasetList.includes(tableName)
    ? datasetList
    : [...datasetList, tableName];
  const result = {
    datasetList: datasetListNew,
    [`${tableName}Data`]: tableDataNew
  };

  outputResult(result);
  return result;
};

// 弹窗指令
const handlePopup = (props, instruct) => {
  const { sActiveId, sActiveName } = props.btnConfig;
  const { title = sActiveName, dataset } = instruct;

  // 获取sqlCondition值
  let sParentConditions = {};
  if (dataset) {
    dataset
      .split(",")
      .filter(item => item)
      .forEach(item => {
        const [tableName, filterType] = item.split("@");
        const filterData = utils.getFilterData(props, tableName, filterType);
        const record = filterData[0];
        sParentConditions = {
          ...sParentConditions,
          ...props.getSqlCondition(props.btnConfig, tableName, record)
        };
      });
  }

  props.onOpenCommonModal({
    type: "commonModal",
    sActiveId,
    title,
    sParentConditions,
    parentProps: props,
    onOk: data => {
      console.log("=====onOk", data);
    },
    onCancel: () => {
      console.log("=====onCancel");
    }
  });

  return {};
};

// 保存指令（表单模式保存）（指令里没有data属性）
const handleSave = (props, instruct) => {
  props.onSaveState({ pageLoading: true });
  // 获取主表数据
  const { masterData, masterConfig } = props;
  if (commonUtils.isEmpty(masterConfig)) {
    throw new Error("请先配置主表后再保存！");
  }
  // 校验主表数据
  if (!commonBusiness.validateMaster(masterConfig, masterData, props)) {
    props.onSaveState({ pageLoading: false });
    throw new Error("主表校验失败！");
  }
  // 获取从表数据
  const allSlaveData = commonFunc.getAllTableData(props);
  // 校验从表数据
  const keyList = Object.keys(allSlaveData).filter(item => item !== "master");
  for (let i = 0; i < keyList.length; i++) {
    const key = keyList[i];
    const slaveConfig = props[`${key}Config`];
    const slaveData = allSlaveData[key];
    if (!commonBusiness.validateTable(slaveConfig, slaveData, props)) {
      props.onSaveState({ pageLoading: false });
      throw new Error("从表校验失败！");
    }
  }
  // 保存接口
  const data = [];
  Object.keys(allSlaveData).forEach(key => {
    const config = props[`${key}Config`];
    const saveTmpData = key === "master" ? [masterData] : props[`${key}Data`];
    const delTmpData = key === "master" ? null : props[`${key}DelData`];
    data.push(
      commonBusiness.mergeData(key, config.sTbName, saveTmpData, delTmpData)
    );
  });

  if (masterData.sId) {
    utils.saveData(props, {
      data,
      sClientType: "1",
      sSysLogSrcId: masterData.sId
    });
  }

  return {};
};

/************************* 保存指令（单表保存）（指令里有data属性） save ************************/
const handleMesSave = (props, instruct) => {
  const { data = [], doNotRefresh } = instruct;
  const saveData = [];

  const name2maxBillNoMap = {};

  for (let i = 0; i < data.length; i++) {
    const item = data[i];
    const { tablename, srcDataset, maxBillNo } = item;
    name2maxBillNoMap[srcDataset] = maxBillNo;
    if (!tablename || !srcDataset) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>
              保存指令集data中的tablename和srcDataset为必填项，请检查该指令集配置！
            </div>
            <div>{JSON.stringify(instruct)}</div>
          </div>
        )
      });
      throw new Error(
        "保存指令集data中的tablename和srcDataset为必填项，请检查该指令集配置！"
      );
    }
    const {
      [`${srcDataset}Data`]: tableData = [],
      [`${srcDataset}DelData`]: delData = [],
      [`${srcDataset}Config`]: config = {}
    } = props;

    const saveTmpData =
      srcDataset.includes("master") && !Array.isArray(tableData)
        ? [tableData]
        : tableData;
    const delTmpData = srcDataset.includes("master") ? null : delData;

    if (
      commonUtils.isNotEmptyObject(config) &&
      !commonBusiness.validateTable(config, saveTmpData, props)
    ) {
      throw new Error("数据校验失败！");
    }

    saveData.push(
      commonBusiness.mergeData(srcDataset, tablename, saveTmpData, delTmpData)
    );
  }

  saveDataTodo = [
    ...saveDataTodo,
    ...saveData
      .filter(item => commonUtils.isNotEmptyArr(item.column))
      .map(({ sTable, name, column }) => {
        if (!doNotRefresh) {
          handleRefresh(props, { dataset: name });
        }
        return {
          tablename: sTable,
          srcDataset: column,
          maxBillNo: name2maxBillNoMap[name]
        };
      })
  ];
  console.log("=====saveDataTodo", saveDataTodo);
  return {};
};

// 保存指令（单表保存）-> 批量保存
const handleMesSaveAll = async (props, onSucess) => {
  if (!saveDataTodo.length) {
    onSucess && onSucess();
    return;
  }

  const { sModelsId, app } = props;
  const { token } = app;
  const dataUrl = `${
    commonConfig.server_host
  }instruct/save?sModelsId=${sModelsId}`;
  const values = {
    opr: "save",
    data: saveDataTodo
  };
  const dataReturn = (await commonServices.postValueService(
    token,
    values,
    dataUrl
  )).data;

  if (dataReturn.code === 1) {
    onSucess && onSucess();
  } else {
    props.onSaveState({ pageLoading: false });
    showMsg({
      type: "error",
      content: (
        <div>
          <div>save接口报错！</div>
          <div>请求地址：</div>
          <div>{dataUrl}</div>
          <div>传入参数：</div>
          <div>{JSON.stringify(values)}</div>
          <div>报错信息</div>
          <div>{JSON.stringify(dataReturn)}</div>
        </div>
      )
    });
  }
};

/************************* 刷新指令 refresh ************************/
const handleRefresh = (props, instruct) => {
  const { dataset = "*" } = instruct;

  // 全部刷新
  if (dataset === "*") {
    refreshTableList.push("*");
    return {};
  }

  const tableList = dataset.split(",");

  // 指定表格刷新(当前页面)
  tableList
    .filter(item => item && !item.includes("parent."))
    .forEach(tableName => {
      let tableNameNew = tableName;
      const { tableNameCompareJson = {} } = props;
      if (commonUtils.isNotEmptyObject(tableNameCompareJson)) {
        tableNameNew = tableNameCompareJson[tableName] || tableName;
      }

      const tableConfig = props[`${tableNameNew}Config`];
      if (!tableConfig) {
        possibleErrorList.push({
          instruct,
          content: `未找到【${tableName}】对应的表格/表单`
        });
      }

      if (refreshTableList.includes(tableNameNew)) return;
      refreshTableList.push(tableNameNew);
    });

  // 指定表格刷新(父页面)
  tableList
    .filter(item => item && item.includes("parent."))
    .forEach(tableName => {
      let tableNameNew = tableName.replace("parent.", "");
      const { parentProps = {} } = props;
      const { tableNameCompareJson = {} } = parentProps;
      if (commonUtils.isNotEmptyObject(tableNameCompareJson)) {
        tableNameNew = tableNameCompareJson[tableNameNew] || tableNameNew;
      }

      const tableConfig = parentProps[`${tableNameNew}Config`];
      if (!tableConfig) {
        possibleErrorList.push({
          instruct,
          content: `未找到【${tableName}】对应的表格/表单`
        });
      }

      if (refreshParentTableList.includes(tableNameNew)) return;
      refreshParentTableList.push(tableNameNew);
    });

  return {};
};

// console指令
const handleConsole = (props, instruct) => {
  const { srcDataset = "" } = instruct;
  if (!srcDataset) return {};
  const datasetList = srcDataset.split(",");
  datasetList.map(tableName => {
    const { [`${tableName}Data`]: data } = props;
    console.log(`=====数据源【${tableName}】: `, data);
  });
  return {};
};

/************************* 消息指令 msg ************************/
const handleMsg = async (props, instruct) => {
  const { msg: msgOld, code, time = 3 } = instruct;

  let msg = msgOld;
  if (msg && msg.includes("${")) {
    msg = handleComputeData(props, msg, {
      ...utils.getDatasetDataList(props, instruct).dataOneObj
    });
  }

  if (code === 1) {
    message.success(msg, time);
  } else if (code === -1) {
    message.error(msg, time);
    throw new Error(msg);
  } else if (code === 2) {
    Modal.info({
      title: "温馨提示:",
      content: <div>{msg}</div>,
      okText: "确认",
      onOk() {}
    });
  } else if (code === -7) {
    const result = await new Promise(resolve => {
      Modal.confirm({
        title: "温馨提示:",
        content: <div>{msg}</div>,
        okText: "确认",
        cancelText: "取消",
        onOk() {
          resolve(true);
        },
        onCancel() {
          resolve(false);
        }
      });
    });
    if (!result) {
      throw new Error();
    }
  } else if (code === -8) {
    Modal.error({
      title: "错误提示:",
      content: <div>{msg}</div>,
      okText: "确认",
      onOk() {}
    });
    throw new Error(msg);
  } else {
    message.warning(msg, time);
  }

  return {};
};

/************************* 发送消息指令 sendmsg ************************/
// 发送消息 -> 暂存消息，数据保存完后一起执行
const handleSendMsg = (props, instruct) => {
  const { dataList } = utils.getDatasetDataList(props, instruct, "srcDataset");
  const result = {
    ...instruct,
    srcDataset: dataList[0]
  };
  sendMsgDataTodo = result;
  outputResult(result);
  return {};
};

const handleSendMsgAll = async props => {
  if (commonUtils.isEmptyObject(sendMsgDataTodo)) return;

  const { sModelsId, app } = props;
  const { token } = app;
  const dataUrl = `${
    commonConfig.server_host
  }instruct/sendmsg?sModelsId=${sModelsId}`;
  const values = sendMsgDataTodo;
  const dataReturn = (await commonServices.postValueService(
    token,
    values,
    dataUrl
  )).data;

  if (dataReturn.code === 1) {
    message.success(dataReturn.msg || "消息发送成功！");
  } else {
    props.onSaveState({ pageLoading: false });
    showMsg({
      type: "error",
      content: (
        <div>
          <div>sendmsg接口报错！</div>
          <div>请求地址：</div>
          <div>{dataUrl}</div>
          <div>传入参数：</div>
          <div>{JSON.stringify(values)}</div>
          <div>报错信息</div>
          <div>{JSON.stringify(dataReturn)}</div>
        </div>
      )
    });
  }
};

/************************* 打印指令 print ************************/
const handlePrint = (props, instruct) => {
  const { sModelsId, app } = props;
  const { token } = app;

  const { reportName, reportType } = instruct;

  const { dataObj = {} } = utils.getDatasetDataList(
    props,
    instruct,
    "srcDataset"
  );

  for (const tableName in dataObj) {
    const tableData = dataObj[tableName];
    if (commonUtils.isEmptyArr(tableData)) {
      possibleErrorList.push({
        instruct,
        content: `未获取到数据源【${tableName}】的数据`
      });
    }
  }

  if (!reportName) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>报表名称不能为空！</div>
          <div>请检查打印报表指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error("打印报表名称不能为空！");
  }

  const dataUrl = `${
    commonConfig.server_host
  }printReport/printInstruct/${reportName}`;

  const params = {
    sModelsId,
    token,
    slaveOneData: JSON.stringify(dataObj),
    reportType
  };
  console.log("=====打印时form表单提交的参数", params);

  handleOpenPost(dataUrl, params);

  return {};
};

// 打印指令 -> 打开打印页面
const handleOpenPost = (
  url,
  { sModelsId, token, slaveOneData, reportType }
) => {
  const newWin = window.open();
  let formStr = "";
  formStr =
    `<form style="visibility:hidden;" method="POST" action="${url}">` +
    `<input type="hidden" name="sModelsId" value='${sModelsId}' />` +
    `<input type="hidden" name="token" value='${token}' />` +
    `<input type="hidden" name="slaveOneData" value='${slaveOneData}' />` +
    `<input type="hidden" name="reportType" value='${reportType}' />` +
    "</form>";
  newWin.document.body.innerHTML = formStr;
  newWin.document.forms[0].submit();
  return newWin;
};

// 人脸识别
const handleFaceAuth = async (props, instruct) => {
  let result = {};
  result = await new Promise(resolve => {
    const modal = Modal.info({
      title: "人脸识别",
      content: (
        <FaceDetect
          loginAfterInit
          onIdentifySuccess={e => {
            const resultRowData = e.dataset.rows[0];
            const { newDataset } = instruct;
            const { datasetList = [] } = props;
            const datasetListNew = datasetList.includes(newDataset)
              ? datasetList
              : [...datasetList, newDataset];
            const resultData = {
              datasetList: datasetListNew,
              [`${newDataset}Data`]: [resultRowData]
            };
            resolve(resultData);
            modal.destroy();
          }}
          actionType={"identifyFace"}
        />
      ),
      wrapClassName: "xlyFaceAuthModal",
      okText: "取消",
      onOk() {
        resolve({
          stop: true
        });
      }
    });
  });
  outputResult(result);
  return result;
};

/************************* 查询sql opnsql ************************/
const handleOpenSql = async (props, instruct) => {
  const {
    app,
    currentSelectedMachineTask,
    currentStartWorkMachineTask,
    currentWorkOrderInfo
  } = props;
  const { userinfo } = app;

  let { data = [] } = instruct;
  if (!data.length) {
    data = [instruct];
  }

  let result = {};

  for (let i = 0; i < data.length; i++) {
    const item = data[i];

    let srcDatasetRow = {};
    const { dataNameList = [], dataList = [] } = utils.getDatasetDataList(
      props,
      item,
      "srcDataset"
    );

    if (!dataList.length) {
      const { sSqlCondition } = item;
      if (sSqlCondition.includes("userinfo")) {
        srcDatasetRow = {
          ...srcDatasetRow,
          ...userinfo
        };
      }
      if (sSqlCondition.includes("currentWorkOrderInfo")) {
        srcDatasetRow = {
          ...srcDatasetRow,
          ...currentWorkOrderInfo
        };
      }
      if (sSqlCondition.includes("currentSelectedMachineTask")) {
        srcDatasetRow = {
          ...srcDatasetRow,
          ...currentSelectedMachineTask
        };
      }
      if (sSqlCondition.includes("currentStartWorkMachineTask")) {
        srcDatasetRow = {
          ...srcDatasetRow,
          ...currentStartWorkMachineTask
        };
      }
    }

    dataList.forEach((data = [], index) => {
      if (!data.length) {
        showMsg({
          type: "error",
          content: (
            <div>
              <div>{`获取${dataNameList[index]}数据集数据为空！`}</div>
              <div>错误指令集内容：</div>
              <div>{JSON.stringify(instruct)}</div>
            </div>
          )
        });
        throw new Error(`获取${dataNameList[index]}数据集数据为空！`);
      }
      srcDatasetRow = {
        ...srcDatasetRow,
        ...data[0]
      };
    });

    const resultData = await handleGetSqlValue(props, item, srcDatasetRow);

    resultData.forEach((item = {}) => {
      const itemNew = {};
      Object.keys(item).forEach(key => {
        if (!key.endsWith("Data")) {
          itemNew[`${key}Data`] = item[key];
        } else {
          itemNew[key] = item[key];
        }
      });

      result = { ...result, ...itemNew };
    });
  }

  outputResult(result);
  return result;
};

// 查询sql -> 调用查询接口
const handleGetSqlValue = async (props, data, srcDatasetRow = {}) => {
  const { sModelsId, app } = props;
  const { token } = app;
  const dataUrl = `${
    commonConfig.server_host
  }instruct/opensql?sModelsId=${sModelsId}`;
  const values = {
    opr: "opensql",
    data: [
      {
        ...data,
        srcDataset: [srcDatasetRow]
      }
    ]
  };
  const dataReturn = (await commonServices.postValueService(
    token,
    values,
    dataUrl
  )).data;

  if (dataReturn.code === 1) {
    const { rows = [] } = dataReturn.dataset;

    if (!rows.length) {
      possibleErrorList.push({
        instruct: values,
        content: "返回结果为空"
      });
    }
    return rows;
  } else {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>opensql查询接口报错！</div>
          <div>请求地址：</div>
          <div>{dataUrl}</div>
          <div>传入参数：</div>
          <div>{JSON.stringify(values)}</div>
          <div>报错信息</div>
          <div>{JSON.stringify(dataReturn)}</div>
        </div>
      )
    });
    throw new Error("opensql指令执行失败！");
  }
};

/************************* 执行sql exesql ************************/
// 执行sql -> 暂存sql，全部执行完后一起执行
const handleExeSql = (props, instruct) => {
  let { data = [] } = instruct;
  if (!data.length) {
    data = [instruct];
  }
  const result = [];
  data.forEach(item => {
    const { sql, srcDataset } = item;

    const { dataList = [] } = utils.getDatasetDataList(
      props,
      item,
      "srcDataset"
    );

    const resultData = dataList[0] || [];

    if (srcDataset && dataList.length && commonUtils.isEmptyArr(dataList[0])) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>{`获取${srcDataset}数据集数据为空！`}</div>
            <div>错误指令集内容：</div>
            <div>{JSON.stringify(instruct)}</div>
          </div>
        )
      });
      throw new Error(`获取${srcDataset}数据集数据为空！`);
    }

    result.push({
      sql,
      srcDataset: resultData
    });
  });

  outputResult(result);
  exesqlTodo = [...exesqlTodo, ...result];
  return {};
};

/************************* 关闭弹窗指令 closepop ************************/
const handleClosePop = (props, instruct) => {
  return { closePop: true };
};

/************************* 执行存储过程 procedure ************************/
const handleProcedure = async (props, instruct) => {
  const { config = {}, bRefresh = false } = instruct;

  if (commonUtils.isEmptyObject(config)) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>存储过程配置为空！</div>
          <div>请检查该指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error("存储过程配置为空！");
  }

  const result = await new Promise(resolve => {
    props.onProcedureCall({
      btnConfig: { sButtonParam: JSON.stringify(config) },
      onSuccess: () => {
        resolve(true);
      },
      onConfirm: () => {
        resolve(true);
      },
      onError: () => {
        resolve(false);
      },
      nextProps: props
    });
  });

  if (!result) {
    throw new Error("存储过程执行失败！");
  } else if (bRefresh) {
    // 等待刷新后继续执行剩余指令集
    const { btnConfig, tableLineParams, callback } = props;
    const { sInstruct: sInstructStr } = btnConfig;
    let sInstructNew = commonUtils.convertStrToObj(sInstructStr, []);
    const iIndex = sInstructNew.findIndex(item => item.opr === "procedure");
    sInstructNew = sInstructNew.filter((_, index) => index > iIndex);

    const addState = {};
    if (sInstructNew.length) {
      addState.onDoInstructAfterProcedure = () => {
        props.onExecInstructSet({
          btnConfig: { ...btnConfig, sInstruct: JSON.stringify(sInstructNew) },
          tableLineParams,
          callback
        });
      };
    }

    props.onSaveState({ refreshTableList: ["*"], ...addState });
    throw new Error("存储过程执行成功！");
  } else {
    console.log("=====执行存储过程成功（未刷新页面）");
    return {};
  }
};

/************************* 跳转tab页 changetab ************************/
const handleChangeTab = (props, instruct) => {
  const { tabName } = instruct;
  if (!tabName) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>跳转tab页指令未配置tabName!</div>
          <div>请检查该指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error("跳转tab页指令未配置tabName！");
  }
  changeTabName = tabName;
  return {};
};

/************************* 弹窗修改字段 poprepair ************************/
const handlePoprepair = async (props, instruct) => {
  const { title, fieldNames, srcDataset } = instruct;

  if (!title || !fieldNames) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>跳转弹窗修改字段指令未配置title/fieldNames！</div>
          <div>请检查该指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error("跳转弹窗修改字段指令未配置title/fieldNames！");
  }

  const { tableLineParams = {} } = props;
  let { name: tableName, record, index } = tableLineParams;

  if (!tableName) {
    tableName = srcDataset;
    record = {};
    index = 0;
  }

  const {
    [`${tableName}Config`]: config,
    [`${tableName}Data`]: tableData
  } = props;

  if (tableName) {
    index = tableData.findIndex(item => item.sId === record.sId);
  }

  const fieldNameList = fieldNames.split(",");

  const filterConfig = config?.gdsconfigformslave?.filter(item => {
    return fieldNameList.includes(item.sName);
  });

  if (!filterConfig || filterConfig.length === 0) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div
          >{`未找到字段集合【${fieldNames}】对应的配置，请确认配置是否正确！`}</div>
          <div>请检查该指令集：</div>
          <div>{JSON.stringify(instruct)}</div>
        </div>
      )
    });
    throw new Error(
      `未找到字段集合【${fieldNames}】对应的配置，请确认配置是否正确！`
    );
  }

  const { dataOneObj = {}, dataNameList = [] } = utils.getDatasetDataList(
    props,
    instruct
  );
  const extraData = utils.getRowDataByValue(
    props,
    instruct,
    dataOneObj,
    dataNameList
  );

  const { confirmBtnName } = instruct;
  const returnData = await new Promise(resolve => {
    props.onSaveState({
      commonRepairModalParams: {
        visible: true,
        title,
        tableName,
        config,
        record: { ...record, ...tableData[index], ...extraData },
        filterConfig,
        confirmBtnName,
        callback: rowData => {
          resolve(rowData);
        }
      }
    });
  });

  let result = {};

  // 如果是确认返回
  if (returnData && commonUtils.isNotEmptyObject(returnData)) {
    const { datasetList = [], [`${tableName}Data`]: tableData = [] } = props;
    const datasetListNew = datasetList.includes(tableName)
      ? datasetList
      : [...datasetList, tableName];

    const tableDataNew = JSON.parse(JSON.stringify(tableData));
    tableDataNew[index] = {
      ...returnData,
      handleType: tableDataNew[index].handleType || "update"
    };

    result = {
      datasetList: datasetListNew,
      [`${tableName}Data`]: tableDataNew
    };
  } else {
    throw new Error("======弹窗指令终止");
  }

  outputResult(result);
  return result;
};

/************************* 新增空数据集 newempry ************************/
const handleNewEmpty = (props, instruct) => {
  const { newDataset, desDataset } = instruct;

  const tableName = desDataset || newDataset;
  const bUpdate = !!desDataset;

  let result = {};
  if (bUpdate) {
    const { datasetList = [] } = props;
    const datasetListNew = datasetList.includes(tableName)
      ? datasetList
      : [...datasetList, tableName];
    result = {
      ...result,
      datasetList: datasetListNew,
      [`${tableName}Data`]: [
        {
          sId: commonUtils.createSid(),
          handleType: "add",
          sParentId: props.masterData?.sId || props.currentId || ""
        }
      ]
    };
  } else {
    result = {
      ...result,
      [`${tableName}Data`]: [{}]
    };
  }

  outputResult(result);
  return result;
};

// 执行sql -> 执行所有sql
const handleExeSqlAll = async (props, onSucess) => {
  if (!exesqlTodo.length) {
    onSucess && onSucess();
    return;
  }

  const { sModelsId, app } = props;
  const { token } = app;
  const dataUrl = `${
    commonConfig.server_host
  }instruct/exesql?sModelsId=${sModelsId}`;
  const values = {
    opr: "exesql",
    data: exesqlTodo
  };
  const dataReturn = (await commonServices.postValueService(
    token,
    values,
    dataUrl
  )).data;

  if (dataReturn.code === 1) {
    onSucess && onSucess();
  } else {
    props.onSaveState({ pageLoading: false });
    showMsg({
      type: "error",
      content: (
        <div>
          <div>exesql接口报错！</div>
          <div>请求地址：</div>
          <div>{dataUrl}</div>
          <div>传入参数：</div>
          <div>{JSON.stringify(values)}</div>
          <div>报错信息</div>
          <div>{JSON.stringify(dataReturn)}</div>
        </div>
      )
    });
  }
};

// 赋值时的js运算
const handleComputeData = (props, str, datasetList) => {
  const {
    fordosetName,
    fordosetData = {},
    app,
    currentSelectedMachineTask,
    currentStartWorkMachineTask,
    currentWorkOrderInfo
  } = props;
  const { userinfo } = app;

  // 定义变量（给eval中的变量用）
  const tempDataOld = {
    [fordosetName]: fordosetData,
    ...datasetList,
    userinfo,
    currentSelectedMachineTask,
    currentStartWorkMachineTask,
    currentWorkOrderInfo
  };

  const tempData = {};
  Object.keys(tempDataOld).forEach(key => {
    if (!key || key.includes("undefined")) return;
    tempData[key] = tempDataOld[key];
    if (
      key.includes("@") ||
      [
        "userinfo",
        "currentSelectedMachineTask",
        "currentStartWorkMachineTask",
        "currentWorkOrderInfo"
      ].includes(key)
    )
      return;
    if (!key.endsWith("One")) {
      tempData[`${key}One`] = tempDataOld[key];
    } else {
      tempData[key.substring(0, key.length - 3)] = tempDataOld[key];
    }
  });

  // 将变量fordosetName替换
  let strNew = str;
  Object.keys(tempData).forEach(key => {
    const reg = new RegExp(`${key}\\.`, "g");
    strNew = strNew.replace(reg, `tempData["${key}"].`);
  });

  tempData.moment = moment;
  strNew = strNew.replace(/moment\(/g, `tempData.moment(`);
  strNew = strNew.replace(/moment\./g, `tempData.moment.`);

  let result = "";
  try {
    // 将conditionNew中的变量赋值
    const evalStr = eval("`" + strNew + "`");
    // 执行判断条件
    result = eval(evalStr);
    result = result === undefined ? "" : result;
    console.log("======赋值js运算结果", {
      str,
      strNew,
      evalStr,
      result
    });
  } catch (error) {
    showMsg({
      type: "error",
      content: (
        <div>
          <div>赋值运算错误！</div>
          <div>请检查赋值运算语法！</div>
          <div>赋值运算内容:</div>
          <div>{str}</div>
          <div>赋值运算被替代后的结果：</div>
          <div>{JSON.stringify(strNew)}</div>
          <div>赋值运算可能用到的数据集：</div>
          <div>{JSON.stringify(tempData)}</div>
        </div>
      )
    });
    console.log("=====err", { str, strNew, error });
    throw new Error("js运算错误");
  }
  return result;
};

const outputInfo = instruct => {
  const { opr } = instruct;
  console.log(`=====步骤${step},操作类型【${opr}】,指令: `, instruct);
  step++;
};

const outputResult = result => {
  console.log(`=====步骤${step - 1}结果: `, result);
};

const utils = {
  // 保存数据
  saveData: async (props, params) => {
    const { token, sModelsId, currentId, masterData, app } = props;
    const { userinfo } = app;
    const BtnSave = commonFunc.showMessage(
      app.commonConst,
      "BtnSave"
    ); /* 保存 */
    params.optName = BtnSave;
    const returnData = await commonBusiness.saveData({
      token,
      value: params,
      sModelsId
    });

    if (commonUtils.isEmptyObject(returnData)) {
      props.onSaveState({
        loading: false
      });
      return false;
    }

    /* 防呆校验 */
    if (returnData.code === -7) {
      confirm({
        title: "单据校验" /* 防呆校验 */,
        content: returnData.msg,
        onOk() {
          params.iFlag = 1;
          utils.saveData(params);
        },
        onCancel() {},
        okText: "保存",
        cancelText: "不保存"
      });
      props.onSaveState({
        loading: false
      });
      return true;
    }
    props.onSendSocketMessage(
      "release",
      "noAction",
      currentId,
      userinfo.sId,
      null,
      null
    );
    props.onSaveState({
      enabled: false,
      currentId: masterData.sId,
      loading: false
    });
    return true;
  },
  // 获取过滤后的数据
  getDatasetDataList: (props, instruct, datasetName = "dataset") => {
    const { [datasetName]: dataset = "" } = instruct;
    const dataNameList = []; // 名称列表
    const dataList = []; // 数据列表
    const dataObj = {}; // 对象 格式：名称: 数据列表
    const dataOneObj = {}; // 对象 格式：名称: 数据列表第一条
    dataset
      .split(",")
      .filter(item => item)
      .forEach(itemOld => {
        const item = itemOld.replace(/\s/g, "");
        const [tableName, filterType] = item.split("@");
        const filterData = utils.getFilterData(props, tableName, filterType);
        dataNameList.push(tableName);
        dataList.push(filterData);
        dataObj[tableName] = filterData;
        dataOneObj[tableName] = filterData[0] || {};
      });
    return {
      dataNameList,
      dataList,
      dataObj,
      dataOneObj
    };
  },
  // 过滤数据
  getFilterData: (props, tableName, filterTypeOld = "") => {
    if (tableName === "userinfo") {
      return [props.app.userinfo];
    }

    let _props = props;

    let filterType = filterTypeOld;
    if (filterType && filterType.includes("parent")) {
      filterType = filterType.replace("parent", "");
      _props = props.parentProps;
    }

    const { tableLineParams, fordosetName, fordosetData } = _props;
    let { [`${tableName}Data`]: tableDataOld = [] } = _props;

    if (tableName === fordosetName) {
      tableDataOld = [fordosetData];
    }

    // 将{}类型的数据转成[{}]类型的数据
    const tableData = Array.isArray(tableDataOld)
      ? tableDataOld
      : [tableDataOld];

    let { [`${tableName}SelectedRowKeys`]: selectedRowKeys = [] } = _props;
    if (
      commonUtils.isEmptyArr(selectedRowKeys) ||
      !tableData.some(
        item =>
          item.sId === selectedRowKeys[0] ||
          item.sSlaveId === selectedRowKeys[0]
      )
    ) {
      selectedRowKeys = tableData[0] ? [tableData[0].sId] : [];
    }

    // if (
    //   filterType === "line" ||
    //   (filterType === "sec" &&
    //     tableLineParams &&
    //     tableLineParams.name === tableName &&
    //     tableLineParams.record)
    // ) {
    //   // 表格按钮所在行数据
    //   return [tableLineParams.record];
    // } else
    if (filterType === "sec") {
      // 选中数据
      return tableData.filter(
        item =>
          selectedRowKeys.includes(item.sId) ||
          selectedRowKeys.includes(item.sSlaveId)
      );
    } else if (filterType === "first") {
      // 数据集第一条数据
      // todo
      return tableData[0];
    }

    return tableData;
  },
  // 获取赋值后的数据
  getDataAfterAssign: (props, instruct, tableDataOld) => {
    const tableDataOldClone = lodash.cloneDeep(tableDataOld);
    const { srcDataset, sValue, fordoset = `${srcDataset}One` } = instruct;

    // 没有sValue时，返回全部
    if (!sValue) return tableDataOldClone;

    const tableDataNew = sValue.includes("*") ? tableDataOldClone : [];

    // 过滤掉列表里的*
    const list = sValue.split(",").filter(item => item && item !== "*");

    list.forEach(item => {
      const [sFieldNameNew, ...rest] = item.split(":");
      const sFieldName = rest.join(":") || sFieldNameNew;

      tableDataOld.forEach((rowData, index) => {
        if (!tableDataNew[index]) {
          tableDataNew[index] = {};
        }

        let result = "";
        if (sFieldName && sFieldName.includes("${")) {
          // 如果有js运算
          result = handleComputeData(props, sFieldName, {
            [fordoset]: rowData,
            ...utils.getDatasetDataList(props, instruct).dataOneObj
            // ...handleGetDataSetData(props, instruct)
          });
        } else {
          // 普通赋值
          result = rowData[sFieldName];
        }
        tableDataNew[index][sFieldNameNew] = result;
      });
    });

    return tableDataNew;
  },
  // 根据sValue获取行数据
  getRowDataByValue: (props, instruct, dataOneObj, dataNameList) => {
    const { sValue = "" } = instruct;

    let rowData = {};
    sValue.split(",").forEach(item => {
      const partValue = item.trim();

      const regexTest = (reg, str) => {
        let tempResult = false;
        try {
          tempResult = reg.test(str);
        } catch (error) {}
        return tempResult;
      };

      const [
        regex1,
        regex2,
        regex3,
        regex4,
        regex5,
        regex6,
        regex7
      ] = utils.getRegex();

      if (partValue.includes(".*")) {
        // 如果是 数据集名称.* 格式（某个数据集的全部数据）
        const [tableName] = partValue.split(".*");
        rowData = {
          ...rowData,
          ...dataOneObj[tableName]
        };
      } else if (regexTest(regex3, partValue)) {
        // 合计某个字段的值
        const [assignField, ...rest] = partValue.split(":");
        let jsStr = rest.join(":");
        rowData = {
          ...rowData,
          [assignField]: utils.getSumData(props, jsStr)
        };
      } else if (regexTest(regex4, partValue)) {
        // 合并某个字段的值
        const [assignField, ...rest] = partValue.split(":");
        let jsStr = rest.join(":");
        rowData = {
          ...rowData,
          [assignField]: utils.getMergeData(props, jsStr)
        };
      } else if (regexTest(regex5, partValue)) {
        // 取最大值
        const [assignField, ...rest] = partValue.split(":");
        let jsStr = rest.join(":");
        rowData = {
          ...rowData,
          [assignField]: utils.getMaxData(props, jsStr)
        };
      } else if (regexTest(regex6, partValue)) {
        // 获取数据集条数
        const [assignField, ...rest] = partValue.split(":");
        let jsStr = rest.join(":");
        rowData = {
          ...rowData,
          [assignField]: utils.getCountData(props, jsStr)
        };
      } else if (regexTest(regex7, partValue)) {
        // 取数组中某个字段分组后的组数
        const [assignField, ...rest] = partValue.split(":");
        let jsStr = rest.join(":");
        rowData = {
          ...rowData,
          [assignField]: utils.getGroupCountData(props, jsStr)
        };
      } else if (partValue.includes("${")) {
        // 如果是 赋值字段名称:js计算 格式
        const [assignField, ...rest] = partValue.split(":");
        const jsStr = rest.join(":");
        rowData = {
          ...rowData,
          [assignField]: handleComputeData(props, jsStr, {
            ...dataOneObj
          })
        };
      } else if (regex1.test(partValue)) {
        // 如果是 赋值字段名称:数据集名称.数据集字段名称 格式
        const [assignField, tableValues] = partValue.split(":");
        const [tableName, fieldName] = tableValues.split(".");
        rowData = {
          ...rowData,
          [assignField]: dataOneObj[tableName][fieldName]
        };
      } else if (regex2.test(partValue)) {
        // 如果是 赋值字段名称:数据集字段名称 格式
        const [assignField, fieldName] = partValue.split(":");
        const tableName = dataNameList[0];
        rowData = {
          ...rowData,
          [assignField]: dataOneObj[tableName][fieldName]
        };
      }
    });
    return rowData;
  },
  // 获取conditon过滤并赋值后的数据
  getDataAfterConditionAndAssign: (
    props,
    instruct,
    datasetName = "desDataset"
  ) => {
    const { [datasetName]: targetDatasetOld, condition, sValue } = instruct;

    const [targetDataset] = targetDatasetOld.split("@");

    if (!sValue) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>数据集的赋值字段sValue不能为空！</div>
            <div>请检查该指令集：</div>
            <div>{JSON.stringify(instruct)}</div>
          </div>
        )
      });
      throw new Error("数据集的赋值字段sValue不能为空！");
    }

    const {
      dataObj = {},
      dataNameList = [],
      dataList = []
    } = utils.getDatasetDataList(props, instruct, datasetName);
    let filterData = dataList[0];

    const { dataOneObj = {} } = utils.getDatasetDataList(props, instruct);

    if (commonUtils.isEmptyArr(filterData)) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>{`${targetDataset}】数据源为空`}</div>
            <div>过滤出的数据集为：</div>
            <div>{JSON.stringify(dataObj)}</div>
            <div>请检查该指令集：</div>
            <div>{JSON.stringify(instruct)}</div>
          </div>
        )
      });
      throw new Error(`${targetDataset}】数据源为空`);
    }

    // const tableDataOld = props[`${targetDataset}Data`] || [];

    // 没有配置condition, 返回原数据
    // if (!condition) return tableDataOld;

    const fordoset = `${targetDataset}One`;
    filterData = filterData.filter(item =>
      utils.bMatchCondition(props, instruct, {
        [fordoset]: item
      })
    );

    const returnData = [];
    filterData.forEach(item => {
      let rowData = item;
      if (sValue === "*") {
        // 全部字段
        rowData = {
          ...item
        };
      } else {
        const dataOneObjNew = {
          ...dataOneObj,
          [targetDataset]: item
        };
        rowData = {
          ...rowData,
          ...utils.getRowDataByValue(
            props,
            instruct,
            dataOneObjNew,
            dataNameList
          )
        };
      }
      returnData.push(rowData);
    });

    return returnData;
  },
  // 判断是否满足条件
  bMatchCondition: (props, instruct, datasetListExtra = {}) => {
    const {
      fordosetName,
      fordosetData = {},
      app,
      currentSelectedMachineTask,
      currentStartWorkMachineTask,
      currentWorkOrderInfo
    } = props;
    const { userinfo } = app;

    const {
      conditionNotEmpty,
      conditionEmpty,
      condition,
      dataset = ""
    } = instruct;

    // 如果都不为空，继续执行
    if (conditionNotEmpty !== undefined) {
      let temp = true;
      conditionNotEmpty.split(",").forEach(item => {
        const [tableName, filterType] = item.split("@");
        const tableData = utils.getFilterData(props, tableName, filterType);
        temp = temp && tableData.length > 0;
      });
      return temp;
    }

    // 如果都为空，继续执行
    if (conditionEmpty !== undefined) {
      let temp = true;
      conditionEmpty.split(",").forEach(item => {
        const [tableName, filterType] = item.split("@");
        const tableData = utils.getFilterData(props, tableName, filterType);
        temp = temp && tableData.length === 0;
      });
      return temp;
    }

    // 如果没有条件，默认全部为true
    if (!condition) return true;

    // 如果包含#，则将 #内容# 部分进行特殊处理
    let conditionNew = condition;
    if (condition.includes("#")) {
      const regex = /#[^#]+#/g;
      conditionNew = conditionNew.replace(regex, match => {
        const content = match.substring(1, match.length - 1);
        return utils.getRegexResult(props, content);
      });
    }

    // 定义变量（给eval中的变量用）
    const tempDataOld = {
      [fordosetName]: fordosetData,
      ...datasetListExtra,
      userinfo,
      currentSelectedMachineTask,
      currentStartWorkMachineTask,
      currentWorkOrderInfo
    };

    const tempData = {};
    Object.keys(tempDataOld).forEach(key => {
      if (!key || key === "undefined") return;
      tempData[key] = tempDataOld[key];
      if (
        key.includes("@") ||
        [
          "userinfo",
          "currentSelectedMachineTask",
          "currentStartWorkMachineTask",
          "currentWorkOrderInfo"
        ].includes(key)
      )
        return;
      if (!key.endsWith("One")) {
        tempData[`${key}One`] = tempDataOld[key];
      } else {
        tempData[key.substring(0, key.length - 3)] = tempDataOld[key];
      }
    });

    const datasetList = dataset.split(",").filter(item => !!item);
    datasetList.forEach(item => {
      const [tableName, filterType] = item.split("@");
      const tableData = utils.getFilterData(props, tableName, filterType);
      if (commonUtils.isNotEmptyArr(tableData)) {
        tempData[item] = tableData[0];
        tempData[tableName] = tableData[0];
      }
    });

    console.log("=====tempData", tempData);

    // 将变量fordosetName替换
    Object.keys(tempData).forEach(key => {
      const reg = new RegExp(`${key}\\.`, "g");
      conditionNew = conditionNew.replace(reg, `tempData["${key}"].`);
    });

    // 替换时间函数moment
    tempData.moment = moment;
    conditionNew = conditionNew.replace(/moment\(/g, `tempData.moment(`);
    conditionNew = conditionNew.replace(/moment\./g, `tempData.moment.`);

    let bMatch = false;
    try {
      // 将conditionNew中的变量赋值
      const evalStr = eval("`" + conditionNew + "`");
      // 执行判断条件
      bMatch = eval(evalStr);
      console.log("======判断条件返回结果", {
        condition,
        conditionNew,
        evalStr,
        bMatch
      });
    } catch (error) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>conditon条件运算错误！</div>
            <div>1、请检查condition语法！</div>
            <div>2、请检查ccondition用到的数据集是否在dataset中正确配置！</div>
            <div>conditon所在指令集：</div>
            <div>{JSON.stringify(instruct)}</div>
            <div>conditon内容:</div>
            <div>{condition}</div>
            <div>condition被替代后的结果：</div>
            <div>{JSON.stringify(conditionNew)}</div>
            <div>condition可能用到的数据集：</div>
            <div>{JSON.stringify(tempData)}</div>
          </div>
        )
      });
      console.log("=====err", { condition, conditionNew, error });
      throw new Error("js运算错误");
    }

    return bMatch;
  },
  // 汇总某个表格的某个字段
  getSumData: (props, jsStr) => {
    const jsStrNew = jsStr.substring(2, jsStr.length - 1);
    const [tableName, temp1] = jsStrNew.split("@");
    const [temp2, sFieldName] = temp1.split(".");
    const decimal = temp2.split("sum")[1];

    const { [`${tableName}Data`]: tableData } = props;
    let sum = 0;
    tableData.forEach(rowData => {
      const value = commonUtils.convertStrToNumber0(rowData[sFieldName]);
      sum += value;
    });

    const result = decimal ? sum.toFixed(decimal) : sum.toString();

    return result;
  },
  // 合并某个字段的值
  getMergeData: (props, jsStr) => {
    const jsStrNew = jsStr.substring(2, jsStr.length - 1);
    const [tableName, temp1] = jsStrNew.split("@");
    const [temp2, sFieldName] = temp1.split(".");
    const temp3 = temp2.split("merge")[1];
    const joinerType = temp3.replace("quo", "");
    const bHasQuo = temp3?.includes("quo");

    const { [`${tableName}Data`]: tableData } = props;
    let tempList = [];
    tableData.forEach(rowData => {
      const value = commonUtils.strUndefinedToEmpty(rowData[sFieldName]);
      if (bHasQuo) {
        tempList.push(`'${value}'`);
      } else {
        tempList.push(value);
      }
    });

    const joinerJson = {
      "": "",
      dot: ",",
      plus: "+",
      minus: "-",
      divide: "/",
      underline: "_"
    };
    const joiner = joinerJson[joinerType] || "";

    const result = tempList.join(joiner);

    return result;
  },
  // 取最大值
  getMaxData: (props, jsStr) => {
    const jsStrNew = jsStr.substring(2, jsStr.length - 1);
    const [tableName, temp1] = jsStrNew.split("@");
    const [, sFieldName] = temp1.split(".");

    const { [`${tableName}Data`]: tableData } = props;
    let maxValue = 0;
    tableData.forEach(rowData => {
      const value = commonUtils.convertStrToNumber0(rowData[sFieldName]);
      maxValue = Math.max(maxValue, value);
    });

    return maxValue;
  },
  // 获取数据集条数
  getCountData: (props, jsStr) => {
    const jsStrNew = jsStr.substring(2, jsStr.length - 1);
    const [tableName] = jsStrNew.split("@");
    const { [`${tableName}Data`]: tableData = [] } = props;
    return tableData.length;
  },
  // 取数组中某个字段分组后的组数
  getGroupCountData: (props, jsStr) => {
    const jsStrNew = jsStr.substring(2, jsStr.length - 1);
    const [tableName, temp1] = jsStrNew.split("@");
    const [, sFieldName] = temp1.split(".");

    const { [`${tableName}Data`]: tableData } = props;
    const tempMap = new Map();
    tableData.forEach(rowData => {
      tempMap.set(rowData[sFieldName], true);
    });

    return tempMap.size;
  },
  // 跳转页面
  changeTabName: () => {
    console.log("=====跳转页面", changeTabName);
    setTimeout(() => {
      const oTabs = document.querySelectorAll(
        `.ant-tabs-tab-btn[id*="${changeTabName}"]`
      );
      let oTab = null;
      if (oTabs.length === 0) {
        showMsg({
          type: "error",
          content: <div>{`未找到tab页面【${changeTabName}】`}</div>
        });
        throw new error(`未找到tab页面【${changeTabName}】`);
      } else if (oTabs.length === 1) {
        oTab = oTabs[0];
      } else if (oTabs.length > 1) {
        oTabs.forEach(item => {
          const { innerHTML } = item;
          if (innerHTML === changeTabName) {
            oTab = item;
          }
        });
      }

      if (!oTab) {
        showMsg({
          type: "error",
          content: <div>{`未找到tab页面【${changeTabName}】`}</div>
        });
        throw new error(`未找到tab页面【${changeTabName}】`);
      }

      oTab.click();
    }, 500);
  },
  // 获取指令集中所有数据
  getAllData: (props, dataset) => {
    const { app, fordosetName, fordosetData } = props;
    const { userinfo, globalData = {} } = app;
    const {
      currentSelectedMachineTaskDataRow: currentSelectedMachineTask = {},
      currentStartWorkMachineTaskDataRow: currentStartWorkMachineTask = {},
      currentWorkOrderInfo = {}
    } = globalData;

    // 全局参数
    let allData = {
      userinfo,
      currentSelectedMachineTask,
      currentStartWorkMachineTask,
      currentWorkOrderInfo,
      moment: moment
    };

    // 循环参数
    if (fordosetName) {
      allData[fordosetName] = fordosetData || {};
    }

    // 所有Data结尾数据的第一条
    Object.keys(props)
      .filter(key => {
        if (!key) return false;
        const bEndWithData = key.endsWith("Data");
        if (!bEndWithData) return false;
        const data = props[key];
        return typeof data === "object" && commonUtils.isNotEmptyObject(data);
      })
      .forEach(key => {
        const tableName = key.substring(0, key.length - 4);
        const data = props[`${tableName}Data`];
        allData[tableName] = Array.isArray(data) ? data[0] : data;
      });

    // dataset过滤后数据的第一条
    const { dataOneObj } = utils.getDatasetDataList(props, { dataset });
    allData = { ...allData, ...dataOneObj };
    return allData;
  },
  // 获取正则规则及其对应方法
  getRegex: () => {
    const regex1 = /^([^\s:]+):([^\s.]+)\.([^\s.]+)$/;
    const regex2 = /^([^\s:]+):([^\s.]+)$/;
    const regex3 = /\$\{[^{}@]+@sum\d+\.[^{}]+\}/g; // ${任意@sum任意数字.任意}
    const regex4 = /\$\{[^{}@]+@merge.*\.[^{}]+\}/g; // ${任意@merge类型.任意}
    const regex5 = /\$\{[^{}@]+@max\.[^{}]+\}/g; // ${任意@max.任意}
    const regex6 = /\$\{[^{}@]+@count\}/g; // ${任意@count}
    const regex7 = /\$\{[^{}@]+@groupCount\.[^{}]+\}/g; // ${任意@groupCount.任意}
    return [regex1, regex2, regex3, regex4, regex5, regex6, regex7];
  },
  getRegexResult: (props, jsStr) => {
    const [
      regex1,
      regex2,
      regex3,
      regex4,
      regex5,
      regex6,
      regex7
    ] = utils.getRegex();

    const regexTest = (reg, str) => {
      let tempResult = false;
      try {
        tempResult = reg.test(str);
      } catch (error) {}
      return tempResult;
    };

    let result = "";
    if (regexTest(regex3, jsStr)) {
      // 合计某个字段的值
      result = utils.getSumData(props, jsStr);
    } else if (regexTest(regex4, jsStr)) {
      // 合并某个字段的值
      result = utils.getMergeData(props, jsStr);
    } else if (regexTest(regex5, jsStr)) {
      // 取最大值
      result = utils.getMaxData(props, jsStr);
    } else if (regexTest(regex6, jsStr)) {
      // 获取数据集条数
      result = utils.getCountData(props, jsStr);
    } else if (regexTest(regex7, jsStr)) {
      // 取数组中某个字段分组后的组数
      result = utils.getGroupCountData(props, jsStr);
    }

    return result;
  },
  // 通用解析
  getEvalResult: (props, { stringValue, dataset, bBooleanMode = false }) => {
    // 获取当前页面所有数据
    const tempData = utils.getAllData(props, dataset);

    // 替换变量
    let strNew = stringValue;
    Object.keys(tempData).forEach(key => {
      const reg = new RegExp(`${key}\\.`, "g");
      strNew = strNew.replace(reg, `tempData["${key}"].`);
    });

    // 替换时间函数moment
    tempData.moment = moment;
    strNew = strNew.replace(/moment\(/g, `tempData.moment(`);
    strNew = strNew.replace(/moment\./g, `tempData.moment.`);

    let result = "";
    try {
      // 调试模式
      if (window.debuggerValue && stringValue.includes(window.debuggerValue)) {
        debugger;
      }

      // 第一遍运算（将变量转换成对应的值）
      const evalStr = eval("`" + strNew + "`");
      // 第二遍运算（将字符串进行js运算）
      result = eval(evalStr);
      result = bBooleanMode ? !!result : result;
      console.log("======赋值js运算结果", {
        传入内容: stringValue,
        替换变量后结果: strNew,
        第一遍运算后结果: evalStr,
        第二遍运算后结果: result
      });
    } catch (error) {
      showMsg({
        type: "error",
        content: (
          <div>
            <div>js运算错误！</div>
            <div>请检查js运算语法！</div>
            <div>js运算内容:</div>
            <div>{stringValue}</div>
            <div>赋值运算被替代后的结果：</div>
            <div>{JSON.stringify(strNew)}</div>
            <div>请联系开发人员或用window.debuggerValue功能调试！</div>
          </div>
        )
      });
      throw new Error("js运算错误");
    }
  }
};

export default instructSet;
