| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925 | 
let budgetSummaryTreeSetting;/* 建设其他费表格相关 */const budgetSummaryObj = (() => {  const { isEmptyVal, isDef, isNumber } = window.commonUtil;  const { fixedFlag, BudgetArea, BudgetType } = window.commonConstants;  let curBudgetType = BudgetType.BUILDING;  // 原始数据  let rawData = [];  // ID与原始数据映射表(主要是恢复用)  const orgMap = {};  // 建设其他费表格对象  let spread = null;  // 建设其他费树  let tree = null;  // 计算相关  const calcSetting = {    costGrowthRate: 0,    growthPeriod: 0,  };  // 单位设置下拉框  const setUnitCombo = (sheet, data) => {    const unitCol = budgetSummaryTreeSetting.cols.findIndex(item => item.data.field === 'unit');    if (unitCol >= 0) {      TREE_SHEET_HELPER.massOperationSheet(sheet, () => {        const comboBox = sheetCommonObj.getDynamicCombo();        comboBox          .itemHeight(10)          .items(['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',            '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀'])          .editable(true);        data.forEach((item, index) => {          sheet.getCell(index, unitCol).cellType(comboBox);        })      });    }  }  const getFieldByCol = (col) => {    const item = budgetSummaryTreeSetting.cols[col];    return item && item.data && item.data.field || null;  }  // 单元格值验证器  const validator = {    text() {      return true    },    number(val) {      return !isDef(val) || isNumber(val);    },  };  const getValidator = (col) => {    const item = budgetSummaryTreeSetting.cols[col];    if (!item) {      return 'text';    }    return validator[item.data.type || 'text'];  }  // 单元格文本转换处理  const textFactory = {    calcBase(node) {      if (node.data.calcBase && node.data.calcBase !== "") {        return cbParser.toFExpr(node.data.calcBase);      }      return '';    },    'feesIndex.common.unitFee': (node) => {      if (node && node.data.area === BudgetArea.CONSTRUCTION_FEE) {        // 实时计算显示单价        const totalFee = _.get(node, 'data.feesIndex.common.totalFee', 0);        const quantity = node.data.quantity || 0;        if (!totalFee || !quantity) {          return '';        }        return scMathUtil.roundForObj(totalFee / quantity, 2); // 小数位数写死2位置      }      if (node && node.data.area === BudgetArea.CONSTRUCTION_OTHER_FEE) {        return _.get(node, 'data.feesIndex.common.unitFee', '') || '';      }      return '';    },    'feesIndex.common.totalFee': (node) => {      return _.get(node, 'data.feesIndex.common.totalFee', '') || '';    },    'feesIndex.estimation.totalFee': (node) => {      return _.get(node, 'data.feesIndex.estimation.totalFee', '') || '';    },    'feesIndex.building.totalFee': (node) => {      return _.get(node, 'data.feesIndex.building.totalFee', '') || '';    },    'feesIndex.installation.totalFee': (node) => {      return _.get(node, 'data.feesIndex.installation.totalFee', '') || '';    },    'feesIndex.equipment.totalFee': (node) => {      return _.get(node, 'data.feesIndex.equipment.totalFee', '') || '';    },    'feesIndex.other.totalFee': (node) => {      return _.get(node, 'data.feesIndex.other.totalFee', '') || '';    },  };  /* 表格事件相关 */  // 根据节点数据刷新表格数据  const refreshData = (sheet, changedCells) => {    if (!tree) {      return;    }    TREE_SHEET_HELPER.massOperationSheet(sheet, () => {      changedCells.forEach(({ row, col }) => {        const node = tree.items[row];        const field = getFieldByCol(col);        if (!field || !node) {          return;        }        const textFunc = textFactory[field];        const val = textFunc ? textFunc(node) : node.data[field] || '';        sheet.setValue(row, col, val);      });    });  }  // 刷新整个表格  const refreshAll = (sheet) => {    const changedCells = [];    const colCount = budgetSummaryTreeSetting.cols.length;    for (let row = 0; row < tree.items.length; row++) {      for (let col = 0; col < colCount; col++) {        changedCells.push({ row, col })      }    }    refreshData(sheet, changedCells);  }  // 更新数据  const bulkOperation = async (bulkData) => {    if (bulkData.length) {      await ajaxPost('/bills/bulkOperation', { bulkData });    }  };  // 计算汇总估算总额  const calcEstimate = (nodes) => {    const dataArr = [];    const parentIDs = new Set();    nodes.forEach(node => parentIDs.add(node.data.ParentID));    const parentNodes = [];    parentIDs.forEach(parentID => {      const node = tree.findNode(parentID);      if (!node) {        return;      }      parentNodes.push(node);      if (!node.children || !node.children.length) {        return;      }      let estimateFee = 0;      node.children.forEach(child => {        const childEstimateItem = child.data.fees && child.data.fees.find(item => item.fieldName === 'estimation') || null;        const childEstimateFee = childEstimateItem ? childEstimateItem.totalFee : 0;        estimateFee = scMathUtil.roundForObj(estimateFee + childEstimateFee, decimalObj.bills.totalPrice);      });      const estimateItem = node.data.fees && node.data.fees.find(item => item.fieldName === 'estimation') || null;      const orgEstimateFee = estimateItem ? estimateItem.totalFee : 0;      if (orgEstimateFee !== estimateFee) {        if (estimateItem) {          estimateItem.totalFee = estimateFee;        } else {          node.data.fees.push({ fieldName: 'estimation', totalFee: estimateFee, unitFee: 0 });        }        dataArr.push({ ID: node.data.ID, fees: node.data.fees });      }    });    if (parentNodes.length) {      dataArr.push(...calcEstimate(parentNodes));    }    return dataArr;  };  // 编辑相关  const edit = async (sheet, changedCells, calcNodes = null) => {    if (!changedCells.length && !calcNodes) {      return;    }    if (changedCells.length) {      // 单元格值验证      const isValid = changedCells.every(({ row, col }) => {        const val = sheet.getValue(row, col);        return getValidator(col)(val);      });      // 验证不通过,恢复      if (!isValid) {        refreshData(sheet, changedCells);        return;      }    }    let needCalc = false;    const calcEstimateNodes = [];    const nodes = [];    try {      $.bootstrapLoading.start();      const IDMap = {};      const bulkData = [];      changedCells.forEach(({ row, col }) => {        const node = tree.items[row];        if (!node) {          return;        }        if (!nodes.find(n => n.data.ID !== node.data.ID)) {          nodes.push(node);        }        const field = getFieldByCol(col);        const value = sheet.getValue(row, col) || '';        const data = (IDMap[node.data.ID] || (IDMap[node.data.ID] = {}));        if (['feesIndex.common.unitFee'].includes(field)) {          const fees = node.data.fees || [];          const feeItem = fees.find(item => item.fieldName === 'common');          if (feeItem) {            feeItem.unitFee = value;          } else {            fees.push({ fieldName: 'common', totalFee: 0, unitFee: +value });          }          data[field] = fees;          node.data[field] = fees;          node.data.feesIndex = getFeeIndex(node.data.fees);        } else if (field === 'feesIndex.estimation.totalFee') {          const fees = node.data.fees || [];          const feeItem = fees.find(item => item.fieldName === 'estimation');          if (feeItem) {            feeItem.totalFee = value;          } else {            fees.push({ fieldName: 'estimation', totalFee: +value, unitFee: 0 });          }          data.fees = fees;          node.data.fees = fees;          node.data.feesIndex = getFeeIndex(node.data.fees);          calcEstimateNodes.push(node);        } else {          data[field] = value;          node.data[field] = value;        }        if (field === 'calcBase') {          node.data.userCalcBase = value;          projectObj.project.calcBase.calculate(node, null, false);          if (!projectObj.project.calcBase.success) {            throw projectObj.project.calcBase.errMsg;          } else if (isEmptyVal(value)) {            // 删除清单基数,单价要清空            calcTools.setFieldValue(node, 'feesIndex.common.unitFee', 0);          }          data.calcBase = node.data.calcBase;          data.calcBaseValue = node.data.calcBaseValue;          data.tenderCalcBaseValue = node.data.tenderCalcBaseValue;        }        if (['quantity', 'feesIndex.common.unitFee', 'calcBase', 'feeRate'].includes(field) && node.data.area !== BudgetArea.CONSTRUCTION_FEE) {          needCalc = true;        }      });      calcNodes = calcNodes ? calcNodes : needCalc ? nodes : [];      // 重算节点      const dataArr = [];      if (calcNodes && calcNodes.length) {        const changedNodes = projectObj.project.calcProgram.calcNodes(calcNodes, false, tree);        for (const node of changedNodes) {          nodes.push(node);          if (node.changed) {            const data = calcTools.cutNodeForSave(node);            dataArr.push(data);          }        }      }      // 汇总估算总额      if (calcEstimateNodes.length) {        dataArr.push(...calcEstimate(calcEstimateNodes));      }            dataArr.forEach(item => {        delete item.projectID;        const data = IDMap[item.ID];        if (data) {          Object.assign(data, item);        } else {          IDMap[item.ID] = item;        }      });      // 保存节点      Object        .entries(IDMap)        .forEach(([ID, data]) => {          const node = tree.findNode(ID);          if (!node) {            return;          }          // 处理被计算程序计算冲掉的估算总额          const orgData = orgMap[ID];          const orgEstimationItem = orgData.fees && orgData.fees.find(item => item.fieldName === 'estimation');          const orgEstimationFee = orgEstimationItem ? orgEstimationItem.totalFee : 0;          const estimationItem = data.fees && data.fees.find(item => item.fieldName === 'estimation');          const estimationFee = estimationItem ? estimationItem.totalFee : 0;          if (orgEstimationFee !== estimationFee) {            if (!estimationItem && data.fees) {              data.fees.push({ fieldName: 'estimation', totalFee: orgEstimationFee });            }          }                    // 处理其他费用          if (node.isBelongToFlags([fixedFlag.CONSTRUCTION_OTHER_FEE])) {            const fees = data.fees || [];            const commonFeeItem = fees.find(item => item.fieldName === 'common');            const otherFeeItem = fees.find(item => item.fieldName === 'other');            if (otherFeeItem) {              otherFeeItem.totalFee = commonFeeItem && commonFeeItem.totalFee || 0;            } else {              fees.push({ fieldName: 'other', totalFee: commonFeeItem && commonFeeItem.totalFee || 0 });            }          }          const actualID = node.data.area === BudgetArea.CONSTRUCTION_FEE ? node.data.orgProjectID : ID;          const updateType = node.data.area === BudgetArea.CONSTRUCTION_FEE ? 'updateProject' : 'update';          bulkData.push({ type: updateType, data: { ...data, ID: actualID } });        });      await bulkOperation(bulkData);      Object        .entries(IDMap)        .forEach(([ID, data]) => {          const node = tree.findNode(ID);          if (node) {            Object.assign(node.data, data);            node.data.feesIndex = getFeeIndex(node.data.fees);            orgMap[ID] = _.cloneDeep(node.data);          }        });      refreshAll(sheet);    } catch (err) {      console.log(err);      nodes.forEach(node => {        const orgItem = orgMap[node.data.ID];        if (orgItem) {          node.data = _.cloneDeep(orgItem);          // Object.assign(node.data, orgItem);        }      });      refreshData(sheet, changedCells);      alert(err);    } finally {      $.bootstrapLoading.end();    }  }  // 是否是属于工程费用区域的节点  const isConstructionFeeArea = (node) => {    return node && node.data && node.data.area === BudgetArea.CONSTRUCTION_FEE;  }  // 工具栏可操作性  let upLevelDisabled = false;  let downLevelDisabled = false;  let upMoveDisabled = false;  let downMoveDisabled = false;  const refreshToolsBar = (node) => {    upLevelDisabled = !node || !node.canUpLevel() || isConstructionFeeArea(node) || (node.nextSibling && node.data.calcBase);    downLevelDisabled = !node || !node.canDownLevel() || isConstructionFeeArea(node) || isConstructionFeeArea(node.preSibling) || (node.preSibling && node.preSibling.data.calcBase);    upMoveDisabled = !node || !node.canUpMove() || isConstructionFeeArea(node) || isConstructionFeeArea(node.preSibling);    downMoveDisabled = !node || !node.canDownMove() || isConstructionFeeArea(node) || isConstructionFeeArea(node.nextSibling);    if (upLevelDisabled) {      $('#budget-upLevel').addClass('disabled');    } else {      $('#budget-upLevel').removeClass('disabled');    }    if (downLevelDisabled) {      $('#budget-downLevel').addClass('disabled');    } else {      $('#budget-downLevel').removeClass('disabled');    }    if (upMoveDisabled) {      $('#budget-upMove').addClass('disabled');    } else {      $('#budget-upMove').removeClass('disabled');    }    if (downMoveDisabled) {      $('#budget-downMove').addClass('disabled');    } else {      $('#budget-downMove').removeClass('disabled');    }  };  // 表格选中相关  const selectCell = (row, col, setCell = false) => {    const node = tree.items[row];    refreshToolsBar(node);    tree.selected = node;    console.log(node);    const sheet = spread.getSheet(0);    if (setCell) {      sheet.setActiveCell(row, col);    }    //设置选中行底色和恢复前选中行底色    const refreshNodes = [node];    if (!tree.preSelected) {      refreshNodes.push(tree.items[0]);    } else {      refreshNodes.push(tree.preSelected);    }    tree.preSelected = node;    projectObj.setNodesStyle(sheet, refreshNodes, tree);  };  // 事件列表  const events = {    EnterCell(sender, args) {      args.sheet.repaint();    },    SelectionChanged(sender, args) {      const newSel = args.newSelections[0] ? { row: args.newSelections[0].row, col: args.newSelections[0].col } : { row: 0, col: 0 };      selectCell(newSel.row, newSel.col);    },    ValueChanged(sender, args) {      if (isEmptyVal(args.oldValue) && isEmptyVal(args.newValue)) {        return;      }      edit(args.sheet, [{ row: args.row, col: args.col }]);    },    RangeChanged(sender, args) {      edit(args.sheet, args.changedCells);    }  }  const bindEvents = (sheet) => {    Object.entries(events).forEach(([ev, evFunc]) => {      sheet.bind(GC.Spread.Sheets.Events[ev], evFunc);    });  }  /* 只读相关 */  // 单元格锁定判断  const lockFactory = {    code(node) {      return !!(node && (node.getFlag() || node.data.area === BudgetArea.CONSTRUCTION_FEE));    },    name(node) {      return !!(node && (node.getFlag() || node.data.area === BudgetArea.CONSTRUCTION_FEE));    },    'feesIndex.estimation.totalFee'(node) {      return !!(!node || node.children.length);    },    'feesIndex.common.unitFee'(node) {      return !!(node && (node.data.area === BudgetArea.CONSTRUCTION_FEE));    },    calcBase(node) {      return !!(node && (node.children.length  || node.data.area === BudgetArea.CONSTRUCTION_FEE));    },    feeRate(node) {      return !!(node && (node.children.length || node.data.area === BudgetArea.CONSTRUCTION_FEE));    },    remark(node) {      return !!(node && node.data.area === BudgetArea.CONSTRUCTION_FEE);    }  };  const lockData = (sheet, nodes, isMass = true) => {    const lock = () => {      if (projectReadOnly) {        sheet.getRange(0, 0, nodes.length, budgetSummaryTreeSetting.cols.length, GC.Spread.Sheets.SheetArea.viewport).locked(true);        return 0;      }      // 工程费用区域,只读      /* const constructionFeeNode = nodes.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_FEE);      if (!constructionFeeNode) {        return 0;      }      const endIndex =  constructionFeeNode.posterityCount() + 1;      sheet.getRange(0, 0, endIndex, budgetSummaryTreeSetting.cols.length, GC.Spread.Sheets.SheetArea.viewport).locked(true);      // 除第一行,章编号 节编号可编辑      if (curBudgetType === BudgetType.RAIL) {        const chapterCodeCol = budgetSummaryTreeSetting.cols.findIndex(item => item.data.field === 'chapterCode');        const sectionCodeCol = budgetSummaryTreeSetting.cols.findIndex(item => item.data.field === 'sectionCode');        for (let row = 1; row < endIndex; row++) {          if (chapterCodeCol > -1) {            sheet.getCell(row, chapterCodeCol).locked(false);          }          if (sectionCodeCol > -1) {            sheet.getCell(row, sectionCodeCol).locked(false);          }        }      }      return endIndex; */    }    if (isMass) {      TREE_SHEET_HELPER.massOperationSheet(sheet, () => {        return lock();      });    } else {      return lock();    }  }  /* 单元格类型 */  const calcBaseButtonCallback = (hitInfo) => {    calcBaseView.onCalcBaseButtonClick(hitInfo, 'budget');  };  const cellTypeFactory = {    calcBase(node) {      const locked = lockFactory.calcBase(node);      return sheetCommonObj.getCusButtonCellType(calcBaseButtonCallback, locked);    }  }  /* 设置可编辑区域节点的只读性和单元格类型 */  const setCells = (sheet, startRow, nodes) => {    for (let row = startRow; row < nodes.length; row++) {      const node = nodes[row];      budgetSummaryTreeSetting.cols.forEach((item, col) => {        const field = item.data.field;        // 锁定单元格        const lockFunc = lockFactory[field];        if (lockFunc) {          const isLocked = lockFunc(node);          sheet.getCell(row, col).locked(isLocked);        }        // 设置单元格类型        const cellTypeFunc = cellTypeFactory[field];        if (cellTypeFunc) {          const cellType = cellTypeFunc(node);          sheet.getCell(row, col).cellType(cellType);        }        // 单元格文本转换        const textFunc = textFactory[field];        if (textFunc) {          sheet.setValue(row, col, textFunc(node));        }      });    }  }  /* 初始化表格 */  const initSpread = () => {    if (!spread) {      // spread = sheetCommonObj.createSpread($('#budget-summary-sheet')[0], 1);      spread = SheetDataHelper.createNewSpread($('#budget-summary-sheet')[0]);      sheetCommonObj.spreadDefaultStyle(spread);      // 设置表头      const sheet = spread.getSheet(0);      bindEvents(sheet);      const headers = sheetCommonObj.getHeadersFromTreeSetting(budgetSummaryTreeSetting);      sheetCommonObj.setHeader(sheet, headers);      // 右键菜单      initContextMenu();    } else {      spread.refresh();    }    return spread;  }  // 初始化树  const initTree = (data, sheet, setting) => {    tree = idTree.createNew({ id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true });    const controller = TREE_SHEET_CONTROLLER.createNew(tree, sheet, setting, false, true);    tree.loadDatas(data);    tree.items.forEach(node => {      node.source = node;      node.sourceType = ModuleNames.bills;    });    controller.showTreeData();    sheet.setRowCount(data.length);    setUnitCombo(sheet, data);    TREE_SHEET_HELPER.massOperationSheet(sheet, () => {      const startRow = lockData(sheet, tree.items, false);      setCells(sheet, 0, tree.items);      // 表格格式化      budgetSummaryTreeSetting.cols.forEach((item, index) => {        sheet.setFormatter(-1, index, item.formatter || '@', GC.Spread.Sheets.SheetArea.viewport);      });    });    selectCell(sheet.getActiveRowIndex(), sheet.getActiveColumnIndex());  }  /* 右键菜单 */  // 更新树结构数据  const updateTree = (sheet, updateData) => {    // 更新数据    updateData.forEach(item => {      if (item.type === 'new') {        orgMap[item.data.ID] = _.cloneDeep(item.data);        rawData.push(item.data)      } else if (item.type === 'update') {        if (orgMap[item.data.ID]) {          Object.assign(orgMap[item.data.ID], item.data);        }        const node = tree.findNode(item.data.ID);        if (node) {          Object.assign(node.data, item.data);        }      } else {        delete orgMap[item.data.ID];        const removeIndex = rawData.findIndex(d => d.ID === item.data.ID);        if (removeIndex > -1) {          rawData.splice(removeIndex, 1);        }      }    });    // 重新初始化树    initTree(rawData, sheet, budgetSummaryTreeSetting);  }  let loading = false;  // 插入  const insert = async (sheet, selected) => {    try {      if (loading) {        return;      }      loading = true;      $.bootstrapLoading.start();      const updateData = tree.getInsertData(selected.data.ParentID, selected.data.NextSiblingID, uuid.v1());      const newData = updateData.filter(item => item.type === 'new');      newData.forEach(item => {        item.data.fees = [];        item.data.flags = [];        item.feesIndex = {};        item.flagsIndex = {};        item.data.type = selected.data.type;        item.data.projectID = projectObj.project.property.rootProjectID;      });      await bulkOperation(updateData);      updateTree(sheet, updateData);      selectCell(sheet.getActiveRowIndex() + selected.posterityCount() + 1, sheet.getActiveColumnIndex(), true);    } catch (err) {      alert(err);    } finally {      $.bootstrapLoading.end();      loading = false;    }  }  // 删除  const remove = async (sheet, selected) => {    try {      if (loading) {        return;      }      loading = true;      $.bootstrapLoading.start();      const updateData = tree.getDeleteData(selected);      await bulkOperation(updateData);      updateTree(sheet, updateData);    } catch (err) {      alert(err);    } finally {      $.bootstrapLoading.end();      loading = false;    }  }  // 升级  const upLevel = async (selected) => {    if (!spread || !tree) {      return;    }    const sheet = spread.getSheet(0);    selected = selected ? selected : tree.selected;    try {      if (loading || upLevelDisabled) {        return;      }      loading = true;      $.bootstrapLoading.start();      const updateData = selected.getUpLevelData();      await bulkOperation(updateData);      updateTree(sheet, updateData);    } catch (err) {      alert(err);    } finally {      $.bootstrapLoading.end();      loading = false;    }  }  // 降级  const downLevel = async (selected) => {    if (!spread || !tree) {      return;    }    const sheet = spread.getSheet(0);    selected = selected ? selected : tree.selected;    try {      if (loading || downLevelDisabled) {        return;      }      loading = true;      $.bootstrapLoading.start();      const updateData = selected.getDownLevelData();      await bulkOperation(updateData);      updateTree(sheet, updateData);    } catch (err) {      alert(err);    } finally {      $.bootstrapLoading.end();      loading = false;    }  }  // 上移  const upMove = async (selected) => {    if (!spread || !tree) {      return;    }    const sheet = spread.getSheet(0);    selected = selected ? selected : tree.selected;    try {      if (loading || upMoveDisabled) {        return;      }      loading = true;      $.bootstrapLoading.start();      const updateData = selected.getUpMoveData();      await bulkOperation(updateData);      updateTree(sheet, updateData);      const prev = selected.preSibling;      const row = sheet.getActiveRowIndex() - prev.posterityCount() - 1;      selectCell(row, sheet.getActiveColumnIndex(), true);      sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);    } catch (err) {      alert(err);    } finally {      $.bootstrapLoading.end();      loading = false;    }  }  // 下移  const downMove = async (selected) => {    if (!spread || !tree) {      return;    }    const sheet = spread.getSheet(0);    selected = selected ? selected : tree.selected;    try {      if (loading || downMoveDisabled) {        return;      }      loading = true;      $.bootstrapLoading.start();      const updateData = selected.getDownMoveData();      await bulkOperation(updateData);      updateTree(sheet, updateData);      const next = selected.nextSibling;      const row = sheet.getActiveRowIndex() + next.posterityCount() + 1;      selectCell(row, sheet.getActiveColumnIndex(), true);      sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);    } catch (err) {      alert(err);    } finally {      $.bootstrapLoading.end();      loading = false;    }  }  // 初始化右键菜单  const initContextMenu = () => {    if (!spread) {      return;    }    let curRow;    let curNode;    const sheet = spread.getSheet(0);    $.contextMenu({      selector: '#budget-summary-sheet',      build: function ($trigger, e) {        const target = SheetDataHelper.safeRightClickSelection($trigger, e, spread);        curRow = target.row;        curNode = tree && tree.items[curRow] || null;        selectCell(target.row, target.col, true);        return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;      },      items: {        insert: {          name: '插入行',          icon: 'fa-sign-in',          disabled() {            return !curNode || (curNode.data.area === BudgetArea.CONSTRUCTION_FEE && curNode.getFlag() !== fixedFlag.CONSTRUCTION_FEE);          },          callback() {            insert(sheet, curNode);          }        },        remove: {          name: '删除行',          icon: 'fa-remove',          disabled() {            return !curNode || isConstructionFeeArea(curNode) || curNode.getFlag();          },          callback() {            remove(sheet, curNode);          }        },        refresh: {          name: '刷新数据',          icon: 'fa-refresh',          callback() {            init(projectObj.project.property.rootProjectID);          }        },      }    });  }  // 初始化  const init = async (constructionID) => {    try {      $.bootstrapLoading.start();      // 得先计算费用汇总(概算汇总计算基于费用汇总算出来的总金额)      await projectObj.project.calcProgram.getGatherFeeData();      const { budgetType, treeData, costGrowthRate, growthPeriod } = await ajaxPost('/bills/initialBudgetSummary', { constructionID });      budgetSummaryTreeSetting = budgetType === BudgetType.BUILDING ? budgetInstallationSetting : budgetRailSetting;      curBudgetType = budgetType;      calcSetting.costGrowthRate = costGrowthRate;      calcSetting.growthPeriod = growthPeriod;      $('#costGrowthRate').val(costGrowthRate);      $('#growthPeriod').val(growthPeriod);      rawData = treeData;      rawData.forEach((item) => {        if (item.quantity) {          item.quantity = parseFloat(item.quantity);        }        item.feesIndex = getFeeIndex(item.fees);        item.flagsIndex = {};        if (item.flags) {          item.flags.forEach((flag) => {            item.flagsIndex[flag.fieldName] = flag;          });        }      });      const spread = initSpread();      const sheet = spread.getSheet(0);      rawData.forEach(item => {        orgMap[item.ID] = _.cloneDeep(item);      });      initTree(rawData, sheet, budgetSummaryTreeSetting);      calcBase.initBudget();      // 造价计算      await edit(sheet, [], tree.roots.slice(1));    } catch (err) {      console.log(err);      alert(err);    } finally {      $.bootstrapLoading.end();    }  }  // 点击tab,重新初始化  $('#tab-budget-summary').click(function () {    if (!$(this).hasClass('active')) {      init(projectObj.project.property.rootProjectID);    }  });  $('#budget-upLevel').click(() => {    upLevel();  });  $('#budget-downLevel').click(() => {    downLevel();  });  $('#budget-upMove').click(() => {    upMove();  });  $('#budget-downMove').click(() => {    downMove();  });  /* 建设项目设置 */  $('#openConstructionSet').click(() => {    $('#constructionSet').modal('show');  });  function isKeyNumber(keyCode) {    // 数字    if (keyCode >= 48 && keyCode <= 57) {      return true;    } else if (keyCode >= 96 && keyCode <= 105) { //小键盘数字      return true;    } else if (keyCode == 8 || keyCode == 46 || keyCode == 37 || keyCode == 39 || keyCode == 108 || keyCode == 110) {  // Backspace, del, 左右方向键      return true;    } else if (keyCode >= 112 && keyCode <= 123) { //F1 -F12      return true;    }    return false;  }  //年造价增涨率  $('#costGrowthRate').keydown(function (e) {    return isKeyNumber(e.keyCode);  });  //计费年限  $("#growthPeriod").keydown(function (e) {    return isKeyNumber(e.keyCode);  });  // 确认设置  $('#construction-set-ok').click(async () => {    try {      $.bootstrapLoading.start();      const curCostGrowthRate = $('#costGrowthRate').val();      const curGrowthPeriod = $('#growthPeriod').val();      const bulkData = [        {          type: 'updateProject',          data: {            ID: projectObj.project.property.rootProjectID,            'property.costGrowthRate': curCostGrowthRate,            'property.growthPeriod': curGrowthPeriod,          }        }      ];      await bulkOperation(bulkData);      calcSetting.costGrowthRate = curCostGrowthRate;      calcSetting.growthPeriod = curGrowthPeriod;    } catch (err) {      alert(err);      $('#costGrowthRate').val(calcSetting.costGrowthRate);      $('#growthPeriod').val(calcSetting.growthPeriod);    } finally {      $.bootstrapLoading.end();    }  });  // 对外暴露  return {    getTree: () => tree,    getSheet: () => spread.getSheet(0),    calcSetting,    edit,  };})();
 |