| 
					
				 | 
			
			
				@@ -510,20 +510,23 @@ class CalcProgram { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         project.registerModule(ModuleNames.calc_program, me); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 兼容Project框架方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     getSourceType () { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return ModuleNames.calc_program; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    };    // 兼容Project框架方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 兼容Project框架方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     loadData (datas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.datas = datas; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.compileAllTemps(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    };   // 兼容Project框架方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 兼容Project框架方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     doAfterUpdate (err, data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(!err){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             $.bootstrapLoading.end(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    };  // 兼容Project框架方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // 经测试,全部编译一次耗时0.003~0.004秒。耗时基本忽略不计。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     compileAllTemps(){ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -697,8 +700,56 @@ class CalcProgram { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // 仅内部调用。注意:外部不能直接使用,因为这里传入的树节点必须有一定的初始化。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    innerCalc(treeNode){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 存储、刷新零散的多个结点。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    saveNodes(treeNodes){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (treeNodes.length < 1) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        me.project.beginUpdate(''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (let node of treeNodes){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (node.changed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let data = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ID: node.data.ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    projectID: me.project.ID(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    /*  subType、quantity、calcBase、programID、marketUnitFee等等字段较为特殊,它们的改变一定会触发计算并导致计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    结果的变化,从而引发保存动作。将这些字段放在该位置跟计算结果一起保存,可减少前端跟后端的通讯频率。              */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    subType: node.data.subType, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    quantity: node.data.quantity, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    calcBase: node.data.calcBase, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    calcBaseValue: node.data.calcBaseValue, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    programID: node.data.programID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    marketUnitFee: node.data.marketUnitFee, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    marketTotalFee: node.data.marketTotalFee, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    fees: node.data.fees, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    isFromDetail:node.data.isFromDetail, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    feeRate: node.data.feeRate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    feeRateID: node.data.feeRateID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    contain:node.data.contain, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    quantityEXP:node.data.quantityEXP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if(node.sourceType==ModuleNames.ration && node.data.type==rationType.gljRation){//定额类型的工料机做特殊处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    data.code=node.data.code; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    data.projectGLJID = node.data.projectGLJID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    delete data.marketUnitFee; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let newData = {'updateType': 'ut_update', 'updateData': data}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                me.project.push(node.sourceType, [newData]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        me.project.endUpdate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (let node of treeNodes){delete node.changed}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        projectObj.mainController.refreshTreeNode(treeNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (activeSubSheetIs(subSheetIndex.ssiCalcProgram)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            calcProgramObj.showData(me.project.mainTree.selected, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 只计算treeNode自身。changedArr: 外部传来的一个数组,专门存储发生变动的节点。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    innerCalc(treeNode, changedArr){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 仅用作树节点显示的工料机不能参与计算。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (treeNode.sourceType === me.project.ration_glj.getSourceType()) return; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -923,126 +974,34 @@ class CalcProgram { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /*// 计算公式结点(叶子清单的计算基数计算)。仅内部调用。注意:外部不能直接使用,因为这里传入的树节点必须有一定的初始化。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    innerCalcFormula(treeNode){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.calcType = treeNodeTools.getCalcType(treeNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (treeNode.calcType != treeNodeCalcType.ctCalcBaseValue) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        delete treeNode.data.gljList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (treeNode.data.programID) treeNode.data.programID = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let f = treeNode.data.feeRate ? treeNode.data.feeRate : 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!treeNode.data.quantity) treeNode.data.quantity = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let q = treeNode.data.quantity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let b = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let uf = (b * f * q / 100).toDecimal(decimalObj.bills.unitPrice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let tuf = uf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let tf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (b * f / 100).toDecimal(decimalObj.bills.totalPrice) : (uf * q).toDecimal(decimalObj.bills.totalPrice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let ttf = tf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        delete treeNode.data.fees;    // 直接删掉再新增,不用一个个费判断更新,效率更高。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        delete treeNode.data.feesIndex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNodeTools.initFeeField(treeNode, 'common'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.data.feesIndex.common.unitFee = uf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.data.feesIndex.common.totalFee = tf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.data.feesIndex.common.tenderUnitFee = tuf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.data.feesIndex.common.tenderTotalFee = ttf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.changed = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        treeNode.data.calcTemplate = {"calcItems": []}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    };*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 计算本节点(默认同时递归计算所有父节点,可选) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 计算本节点、所有父节点(默认,可选)、公式引用节点。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calculate(treeNode, calcParents = true){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let changedNodes = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        me.innerCalc(treeNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        me.innerCalc(treeNode, changedNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (treeNode.changed) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (!changedNodes.includes(treeNode)) changedNodes.push(treeNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 计算父结点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (calcParents){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 let curNode = treeNode.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 while (curNode){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    me.innerCalc(curNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (curNode.changed && !changedNodes.includes(curNode)) changedNodes.push(curNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    me.innerCalc(curNode, changedNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     curNode = curNode.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // 父结点算完,再算所有的公式结点(必须先算完父结点,再算公式结点) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 父结点算完,再计算所有的公式结点(必须先算完父结点,再算公式结点) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             me.calcFormulaNodes(changedNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return changedNodes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 存储、刷新本节点(默认存储刷新所有父节点,可选) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    saveNode(treeNode, saveParents = true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!treeNode.changed) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let nodesArr = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let curNode = treeNode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        while (curNode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (curNode.changed){nodesArr.push(curNode)}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (saveParents) curNode = curNode.parent 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        me.saveNodes(nodesArr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 存储、刷新零散的多个树结点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    saveNodes(treeNodes){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (treeNodes.length < 1) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        me.project.beginUpdate(''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (let node of treeNodes){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (node.changed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                let data = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ID: node.data.ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    projectID: me.project.ID(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    /*  subType、quantity、calcBase、programID、marketUnitFee等等字段较为特殊,它们的改变一定会触发计算并导致计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    结果的变化,从而引发保存动作。将这些字段放在该位置跟计算结果一起保存,可减少前端跟后端的通讯频率。              */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    subType: node.data.subType, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    quantity: node.data.quantity, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    calcBase: node.data.calcBase, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    calcBaseValue: node.data.calcBaseValue, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    programID: node.data.programID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    marketUnitFee: node.data.marketUnitFee, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    marketTotalFee: node.data.marketTotalFee, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    fees: node.data.fees, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    isFromDetail:node.data.isFromDetail, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    feeRate: node.data.feeRate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    feeRateID: node.data.feeRateID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    contain:node.data.contain, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    quantityEXP:node.data.quantityEXP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if(node.sourceType==ModuleNames.ration && node.data.type==rationType.gljRation){//定额类型的工料机做特殊处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    data.code=node.data.code; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    data.projectGLJID = node.data.projectGLJID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    delete data.marketUnitFee; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                let newData = {'updateType': 'ut_update', 'updateData': data}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                me.project.push(node.sourceType, [newData]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        me.project.endUpdate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (let node of treeNodes){delete node.changed}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        projectObj.mainController.refreshTreeNode(treeNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (activeSubSheetIs(subSheetIndex.ssiCalcProgram)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            calcProgramObj.showData(me.project.mainTree.selected, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /* 计算所有树结点(分3种情况),并返回发生变动的零散的多个树结点。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     参数取值如下: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calcAllType.catAll       计算所有树结点 (不指定参数时的默认值) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1071,7 +1030,7 @@ class CalcProgram { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // 计算全部公式项。 (参数意义:将通过本方法后发生改变的节点存入changedNodesArr中) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    calcFormulaNodes(changedNodesArr){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    calcFormulaNodes(changedArr){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let me = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let formulaNodes = treeNodeTools.getFormulaNodes(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (formulaNodes.length == 0) return; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1080,15 +1039,13 @@ class CalcProgram { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             projectObj.project.calcBase.calculate(formulaNode, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (projectObj.project.calcBase.success){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 计算公式结点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                me.innerCalc(formulaNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (formulaNode.changed && !changedNodesArr.includes(formulaNode)) changedNodesArr.push(formulaNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                me.innerCalc(formulaNode, changedArr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 计算父结点 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (formulaNode.changed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     let curNode = formulaNode.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     while (curNode){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        me.innerCalc(curNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (curNode.changed && !changedNodesArr.includes(curNode)) changedNodesArr.push(curNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        me.innerCalc(curNode, changedArr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         curNode = curNode.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 }; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1122,26 +1079,21 @@ class CalcProgram { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calcRationsAndSave(rationNodes){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let me = this, leafBills = [], changedNodes = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for (let node of rationNodes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            me.calculate(node, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (node.changed) changedNodes.push(node); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            me.innerCalc(node, changedNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             let leafBill = node.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (leafBill && leafBills.indexOf(leafBill) < 0) leafBills.push(leafBill);      // 多条定额同属一条叶子清单时,避免叶子清单重复计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 多条定额同属一条叶子清单时,避免叶子清单重复计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (leafBill && leafBills.indexOf(leafBill) < 0) leafBills.push(leafBill); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for (let node of leafBills){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             me.calculate(node); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            let cur = node; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            while (cur) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (cur.changed && changedNodes.indexOf(cur) < 0) changedNodes.push(cur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                cur = cur.parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         me.saveNodes(changedNodes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // 计算并保存指定的一个树节点。修改一个树节点,实际上要计算和保存的是一批树结点:层层父结点、被其它结点(的公式)引用的公式结点。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // 这个方法实际上封装了calculate()和saveNodes()两个方法,方便外部调用,少写一点代码。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 这个方法实际上封装了calculate()和saveNodes()两个方法,主要目的是为了外部调用方便,少写一点累赘代码。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calcAndSave(treeNode){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let changedNodes = this.calculate(treeNode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.saveNodes(changedNodes); 
			 |