Browse Source

feat: 概算汇总计算相关

vian 4 years ago
parent
commit
7f6e188580

+ 7 - 1
public/common_util.js

@@ -142,6 +142,11 @@ function deleteEmptyObject(arr) {
         return null;
     };
 
+    // 获取造价书树或概算汇总树
+    const getActiveTree = () => {
+        return $('#tab-budget-summary').hasClass('active') ? budgetSummaryObj.getTree() : projectObj.project.mainTree;
+    }
+
     return {
         isDef,
         isEmptyVal,
@@ -151,6 +156,7 @@ function deleteEmptyObject(arr) {
         getSortedTreeData,
         isNotEmptyObject,
         handleFullscreen,
-        getEngineeringFeeType
+        getEngineeringFeeType,
+        getActiveTree,
     };
 });

+ 131 - 44
web/building_saas/budget-summary/js/budgetSummarySheet.js

@@ -6,6 +6,8 @@ const budgetSummaryObj = (() => {
 
   // 原始数据
   let rawData = [];
+  // ID与原始数据映射表(主要是恢复用)
+  const orgMap = {};
   // 建设其他费表格对象
   let spread = null;
   // 建设其他费树
@@ -56,21 +58,63 @@ const budgetSummaryObj = (() => {
     return validator[item.data.type || 'text'];
   }
 
+  // 单元格文本转换处理
+  const textFactory = {
+    calcBase(node) {
+      if (node.data.calcBase && node.data.calcBase !== "") {
+        return cbParser.toFExpr(node.data.calcBase);
+      }
+    },
+    'feesIndex.common.unitFee': (node) => {
+      return _.get(node, 'data.feesIndex.common.unitFee', '') || '';
+    },
+    'feesIndex.common.totalFee': (node) => {
+      return _.get(node, 'data.feesIndex.common.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 recover = (sheet, changedCells) => {
+  // 根据节点数据刷新表格数据
+  const refreshData = (sheet, changedCells) => {
     if (!tree) {
       return;
     }
-    changedCells.forEach(({ row, col }) => {
-      const node = tree.items[row];
-      const field = getFieldByCol(col);
-      if (!field || !node) {
-        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 })
       }
-      const orgVal = node.data[field];
-      sheet.setValue(row, col, orgVal);
-    })
+    }
+    refreshData(sheet, changedCells);
   }
 
   // 更新数据
@@ -78,27 +122,6 @@ const budgetSummaryObj = (() => {
     await ajaxPost('/bills/bulkOperation', { bulkData });
   };
 
-  // 计算节点
-  const calcNodes = async (sheet, nodes) => {
-    try {
-      $.bootstrapLoading.start();
-      debugger;
-      const changedNodes = projectObj.project.calcProgram.calcNodes(nodes, false);
-      const dataArr = [];
-      for (const node of changedNodes) {
-        if (node.changed) {
-          const data = calcTools.cutNodeForSave(node);
-          dataArr.push(data);
-        }
-      }
-      console.log(dataArr);
-    } catch (err) {
-      alert(err);
-    } finally {
-      $.bootstrapLoading.end();
-    }
-  }
-
   // 编辑相关
   const edit = async (sheet, changedCells) => {
     if (!changedCells.length) {
@@ -111,7 +134,7 @@ const budgetSummaryObj = (() => {
     });
     // 验证不通过,恢复
     if (!isValid) {
-      recover(sheet, changedCells);
+      refreshData(sheet, changedCells);
     }
     let needCalc = false;
     const nodes = [];
@@ -129,36 +152,87 @@ const budgetSummaryObj = (() => {
         }
         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 {
+          data[field] = value;
+          node.data[field] = value;
+        }
         if (field === 'calcBase') {
-          debugger;
           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;
         }
-        const data = (IDMap[node.data.ID] || (IDMap[node.data.ID] = {}));
-        data[field] = value;
         if (['quantity', 'feesIndex.common.unitFee', 'calcBase', 'feeRate'].includes(field)) {
           needCalc = true;
         }
       });
+      // 重算节点
+      const dataArr = [];
+      if (needCalc && nodes.length) {
+        const changedNodes = projectObj.project.calcProgram.calcNodes(nodes, false, tree);
+        for (const node of changedNodes) {
+          nodes.push(node);
+          if (node.changed) {
+            const data = calcTools.cutNodeForSave(node);
+            dataArr.push(data);
+          }
+        }
+      }
+      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]) => {
           bulkData.push({ type: 'update', data: { ID, ...data } });
         });
       await bulkOperation(bulkData);
-      bulkData.forEach(item => {
-        const node = tree.findNode(item.data.ID);
-        Object.assign(node.data, item.data);
-      });
-      // 重算节点
-      /* if (needCalc && nodes.length) {
-        await calcNodes(sheet, nodes);
-      } */
+      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) {
-      recover(sheet, changedCells);
+      console.log(err);
+      nodes.forEach(node => {
+        const orgItem = orgMap[node.data.ID];
+        if (orgItem) {
+          Object.assign(node.data, orgItem);
+        }
+      });
+      refreshData(sheet, changedCells);
       alert(err);
     } finally {
       $.bootstrapLoading.end();
@@ -312,6 +386,11 @@ const budgetSummaryObj = (() => {
           const cellType = cellTypeFunc(node);
           sheet.getCell(row, col).cellType(cellType);
         }
+        // 单元格文本转换
+        const textFunc = textFactory[field];
+        if (textFunc) {
+          sheet.setValue(row, col, textFunc(node));
+        }
       });
     }
   }
@@ -363,13 +442,18 @@ const budgetSummaryObj = (() => {
     // 更新数据
     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);
@@ -640,6 +724,9 @@ const budgetSummaryObj = (() => {
       });
       const spread = initSpread();
       const sheet = spread.getSheet(0);
+      rawData.forEach(item => {
+        orgMap[item.ID] = _.cloneDeep(item);
+      });
       initTree(rawData, sheet, budgetSummaryTreeSetting);
       calcBase.initBudget();
     } catch (err) {

+ 8 - 5
web/building_saas/main/js/models/calc_base.js

@@ -61,8 +61,8 @@ let cbTools = {
     },
     //通过ID获取节点
     getNodeByID: function (ID) {
-        const nodes = $('#tab-budget-summary').hasClass('active') ? budgetSummaryObj.getTree().nodes : calcBase.project.mainTree.nodes;
-        return this.isDef(nodes['id_' + ID]) ? nodes['id_' + ID] : null;
+        const tree = commonUtil.getActiveTree();
+        return this.isDef(tree.nodes['id_' + ID]) ? tree.nodes['id_' + ID] : null;
     },
     //获取该节点所有父节点
     getParents: function (node) {
@@ -365,6 +365,7 @@ let cbTools = {
     },
     //获取清单(有基数计算)引用了的其他清单,(循环引用栈中的一块)
     getStackBlock: function (billID) {
+        const tree = commonUtil.getActiveTree();
         let tempBases = [], block = [];//存引用的清单ID
         let node = getBill(billID);
         if (!node) {
@@ -419,7 +420,7 @@ let cbTools = {
             }
         }
         function getBill(ID) {
-            let nodes = calcBase.project.mainTree.nodes;
+            let nodes = tree.nodes;
             let node = nodes['id_' + ID];
             if (cbTools.isDef(node) && node.sourceType === calcBase.project.Bills.getSourceType()) {
                 return node;
@@ -1627,13 +1628,14 @@ let cbParser = {
     },
     //将行引用转换成ID引用
     toIDExpr: function (exp) {
+        const tree = commonUtil.getActiveTree();
         let exps = [];
         //获得行引用
         let fArr = this.getFArr(exp);
         for (let i = 0, len = fArr.length; i < len; i++) {
             let r = this.getXNum([fArr[i]]);
             if (r.length === 1) {
-                let node = cbTools.getBillByRow(calcBase.project.mainTree.items, r[0] - 1);
+                let node = cbTools.getBillByRow(tree.items, r[0] - 1);
                 if (cbTools.isUnDef(node)) {
                     //continue;
                     calcBase.errMsg = '行引用错误';
@@ -1653,13 +1655,14 @@ let cbParser = {
     },
     //将ID引用转换成行引用
     toFExpr: function (exp) {
+        const tree = commonUtil.getActiveTree();
         let exps = [];
         //获得ID引用
         let fidArr = this.getFIDArr(exp);
         for (let i = 0, len = fidArr.length; i < len; i++) {
             let id = this.getUID([fidArr[i]]);
             if (id.length === 1) {
-                let row = cbTools.getRowByID(calcBase.project.mainTree.items, id[0]);
+                let row = cbTools.getRowByID(tree.items, id[0]);
                 if (cbTools.isUnDef(row)) {
                     continue;
                 }

+ 5 - 5
web/building_saas/main/js/models/calc_program.js

@@ -1026,7 +1026,7 @@ let calcTools = {
             let r = projectObj.project.FeeRate.getFeeRateByID(node.data.feeRateID);
             if (r) return scMathUtil.roundForObj(r.rate, decimal);
         };
-        if (node.data.feeRate || node.data.feeRate == 0)
+        if (node.data.feeRate || node.data.feeRate === 0 || node.data.feeRate === '0')
             return scMathUtil.roundForObj(node.data.feeRate,decimal);
 
         return 100;
@@ -2231,7 +2231,7 @@ class CalcProgram {
     // 计算零散的、混杂的树节点:清单、定额混合等(如:用到某一计算程序的定额和清单)。
     // 计算多条零散的定额,并计算他们所属的清单、父清单、引用清单。如:批量替换工料机后受影响的定额。
     // 计算多条零散的清单,并计算他们的父清单、引用清单。如:花选删除树结点(如花选清单、定额等,不区分树结点类型)。
-    calcNodes(nodes, tender){
+    calcNodes(nodes, tender, tree){
         let me = this, rationNodes = [], billNodes = [], leafBills = [], allChangedNodes = [];
         for (let node of nodes) {
             if (node.sourceType == ModuleNames.ration)
@@ -2255,7 +2255,7 @@ class CalcProgram {
             allChangedNodes.merge(changeBills);
         };
 
-        me.calcFormulaNodes(allChangedNodes, tender);
+        me.calcFormulaNodes(allChangedNodes, tender, tree);
         return allChangedNodes;
     };
 
@@ -2266,9 +2266,9 @@ class CalcProgram {
     };
 
     // 计算全部公式项。 (changedArr:将通过本方法后发生改变的节点存入changedArr中)
-    calcFormulaNodes(changedArr, tender){
+    calcFormulaNodes(changedArr, tender, tree = projectObj.project.mainTree){
         let me = this;
-        let formulaNodes = cbTools.getFormulaNodes(true);
+        let formulaNodes = cbTools.getFormulaNodes(true, tree);
         if (formulaNodes.length == 0) return;
         for (let formulaNode of formulaNodes){
             formulaNode.data.userCalcBase = formulaNode.data.calcBase;    // 这句不该出现,projectObj.project.calcBase中要改进。