|  | @@ -854,8 +854,6 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          else if (me.isLeafBill(treeNode)) {
 | 
	
		
			
				|  |  |              if (treeNode.children && treeNode.children.length > 0){
 | 
	
		
			
				|  |  | -                // me.calcLeafBillChildren(treeNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |                  // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。(汇总清单所有定额的工料机)
 | 
	
		
			
				|  |  |                  if (me.project.property.billsCalcMode === leafBillGetFeeType.billsPrice)
 | 
	
		
			
				|  |  |                      treeNode.calcType = treeNodeCalcType.ctBillCalcProgram;
 | 
	
	
		
			
				|  | @@ -891,7 +889,7 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          me.saveNodes(nodesArr);
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 多个树结点入库存储,刷新界面显示。
 | 
	
		
			
				|  |  | +    // 存储、刷新零散的多个树结点
 | 
	
		
			
				|  |  |      saveNodes(treeNodes){
 | 
	
		
			
				|  |  |          if (treeNodes.length < 1) return;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -937,14 +935,14 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*    计算所有树结点(分3种情况),并将发生计算改动的结点入库存储。
 | 
	
		
			
				|  |  | +/*    计算所有树结点(分3种情况),并返回发生变动的零散的多个树结点。
 | 
	
		
			
				|  |  |      参数取值如下:
 | 
	
		
			
				|  |  |      calcAllType.catAll       计算所有树结点 (不指定参数时的默认值)
 | 
	
		
			
				|  |  |      calcAllType.catBills     计算所有清单 (改变项目属性中清单取费算法时会用到)
 | 
	
		
			
				|  |  |      calcAllType.catRations   计算所有定额、工料机形式的定额、量价,因为它们都走自己的计算程序 (改变人工系数、费率值、工料机单价时会用到) */
 | 
	
		
			
				|  |  |      calcAllNodes(calcType = calcAllType.catAll){
 | 
	
		
			
				|  |  |          let me = this;
 | 
	
		
			
				|  |  | -        let needSaveNodes = [];
 | 
	
		
			
				|  |  | +        let changedNodes = [];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          function calcNodes(nodes) {
 | 
	
		
			
				|  |  |              for (let node of nodes) {
 | 
	
	
		
			
				|  | @@ -954,33 +952,42 @@ class CalcProgram {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if ((calcType == calcAllType.catAll) || (calcType == node.sourceType)) {
 | 
	
		
			
				|  |  |                      me.calculate(node, false);
 | 
	
		
			
				|  |  | -                    if (node.changed) needSaveNodes.push(node);
 | 
	
		
			
				|  |  | +                    if (node.changed) changedNodes.push(node);
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          calcNodes(me.project.mainTree.roots);
 | 
	
		
			
				|  |  | -        // me.saveNodes(needSaveNodes);   保存要与计算分离,否则实际应用场景中,会产生多次通讯。
 | 
	
		
			
				|  |  | -        return needSaveNodes;
 | 
	
		
			
				|  |  | +        // me.saveNodes(changedNodes);   保存要与计算分离,否则实际应用场景中,会产生多次通讯。
 | 
	
		
			
				|  |  | +        return changedNodes;
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 重新计算叶子清单下的所有子结点:如定额、工料机定额等(calculate算法基于定额、工料机定额的计算结果是正确的,实际上有时它们的计算结果并不是最新的)
 | 
	
		
			
				|  |  | -    calcLeafBillChildren(treeNode){
 | 
	
		
			
				|  |  | +    // 计算叶子清单下的所有子结点(如定额、量价、工料机定额等), 并计算自身和所有父结点。最后打包存储。
 | 
	
		
			
				|  |  | +    calcLeafAndSave(treeNode){
 | 
	
		
			
				|  |  |          let me = this;
 | 
	
		
			
				|  |  |          if(!me.isLeafBill(treeNode)) return;
 | 
	
		
			
				|  |  |          if (treeNode.children && treeNode.children.length > 0) {
 | 
	
		
			
				|  |  | -            let needSaveNodes = [];
 | 
	
		
			
				|  |  | +            let changedNodes = [];
 | 
	
		
			
				|  |  |              for (let child of treeNode.children){
 | 
	
		
			
				|  |  |                  me.calculate(child, false);
 | 
	
		
			
				|  |  | -                if (child.changed) needSaveNodes.push(child);
 | 
	
		
			
				|  |  | +                if (child.changed) changedNodes.push(child);
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            me.calculate(treeNode);
 | 
	
		
			
				|  |  | +            let cur = treeNode;
 | 
	
		
			
				|  |  | +            while (cur) {
 | 
	
		
			
				|  |  | +                if (cur.changed) changedNodes.push(cur);
 | 
	
		
			
				|  |  | +                cur = cur.parent;
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  | -            me.saveNodes(needSaveNodes);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            me.saveNodes(changedNodes);
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    calcRationsAndSave(raitonNodes){//计算批量替换工料机后受影响的定额,同时将结果打包保存
 | 
	
		
			
				|  |  | +    // 计算多条零散的定额,并计算他们所属的清单、父级清单,然后打包存储。如:批量替换工料机后受影响的定额。
 | 
	
		
			
				|  |  | +    calcRationsAndSave(rationNodes){
 | 
	
		
			
				|  |  |          let me = this, leafBills = [], changedNodes = [];
 | 
	
		
			
				|  |  | -        for (let node of raitonNodes) {
 | 
	
		
			
				|  |  | +        for (let node of rationNodes) {
 | 
	
		
			
				|  |  |              me.calculate(node, false);
 | 
	
		
			
				|  |  |              if (node.changed) changedNodes.push(node);
 | 
	
		
			
				|  |  |              let leafBill = node.parent;
 |