|  | @@ -3,92 +3,6 @@
 | 
	
		
			
				|  |  |   * 计算程序。所有定额、清单、父清单的计算都从此入。
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*  新版GLD 取消了默认清单模板,所以这里废弃。先留着,预防不时之需。
 | 
	
		
			
				|  |  | -let defaultBillTemplate = {
 | 
	
		
			
				|  |  | -    ID: 15,
 | 
	
		
			
				|  |  | -    name: "清单公式",
 | 
	
		
			
				|  |  | -    calcItems: [
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 1,
 | 
	
		
			
				|  |  | -            code: "1",
 | 
	
		
			
				|  |  | -            name: "定额直接费",
 | 
	
		
			
				|  |  | -            dispExpr: "F2+F3+F4",
 | 
	
		
			
				|  |  | -            statement: "人工费+材料费+机械费",
 | 
	
		
			
				|  |  | -            feeRate: null,
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 2,
 | 
	
		
			
				|  |  | -            code: "1.1",
 | 
	
		
			
				|  |  | -            name: "人工费",
 | 
	
		
			
				|  |  | -            dispExpr: "HJ",
 | 
	
		
			
				|  |  | -            statement: "合计",
 | 
	
		
			
				|  |  | -            feeRate: 50,
 | 
	
		
			
				|  |  | -            fieldName: 'labour',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 3,
 | 
	
		
			
				|  |  | -            code: "1.2",
 | 
	
		
			
				|  |  | -            name: "材料费",
 | 
	
		
			
				|  |  | -            dispExpr: "HJ",
 | 
	
		
			
				|  |  | -            statement: "合计",
 | 
	
		
			
				|  |  | -            feeRate: 30,
 | 
	
		
			
				|  |  | -            fieldName: 'material',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 4,
 | 
	
		
			
				|  |  | -            code: "1.3",
 | 
	
		
			
				|  |  | -            name: "机械费",
 | 
	
		
			
				|  |  | -            dispExpr: "HJ",
 | 
	
		
			
				|  |  | -            statement: "合计",
 | 
	
		
			
				|  |  | -            feeRate: 20,
 | 
	
		
			
				|  |  | -            fieldName: 'machine',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 5,
 | 
	
		
			
				|  |  | -            code: "2",
 | 
	
		
			
				|  |  | -            name: "企业管理费",
 | 
	
		
			
				|  |  | -            dispExpr: "F1",
 | 
	
		
			
				|  |  | -            statement: "定额直接费",
 | 
	
		
			
				|  |  | -            feeRate: null,
 | 
	
		
			
				|  |  | -            fieldName: 'manage',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 6,
 | 
	
		
			
				|  |  | -            code: "3",
 | 
	
		
			
				|  |  | -            name: "利润",
 | 
	
		
			
				|  |  | -            dispExpr: "F1",
 | 
	
		
			
				|  |  | -            statement: "定额直接费",
 | 
	
		
			
				|  |  | -            feeRate: null,
 | 
	
		
			
				|  |  | -            fieldName: 'profit',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 7,
 | 
	
		
			
				|  |  | -            code: "4",
 | 
	
		
			
				|  |  | -            name: "风险费用",
 | 
	
		
			
				|  |  | -            dispExpr: "F1",
 | 
	
		
			
				|  |  | -            statement: "定额直接费",
 | 
	
		
			
				|  |  | -            feeRate: null,
 | 
	
		
			
				|  |  | -            fieldName: 'risk',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            ID: 8,
 | 
	
		
			
				|  |  | -            code: "5",
 | 
	
		
			
				|  |  | -            name: "综合单价",
 | 
	
		
			
				|  |  | -            dispExpr: "F1+F5+F6+F7",
 | 
	
		
			
				|  |  | -            statement: "定额直接费+企业管理费+利润+风险费用",
 | 
	
		
			
				|  |  | -            feeRate: null,
 | 
	
		
			
				|  |  | -            fieldName: 'common',
 | 
	
		
			
				|  |  | -            memo: ''
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    ]
 | 
	
		
			
				|  |  | -};*/
 | 
	
		
			
				|  |  |  let calcTools = {
 | 
	
		
			
				|  |  |      getNodeByFlag: function (flag) {
 | 
	
		
			
				|  |  |          let bill = cbTools.findBill(flag);
 | 
	
	
		
			
				|  | @@ -284,7 +198,7 @@ let calcTools = {
 | 
	
		
			
				|  |  |          if (!feeObj) return;
 | 
	
		
			
				|  |  |          if (feeObj.fieldName == '') return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // 初始化前先拦截末定义的情况
 | 
	
		
			
				|  |  | +        // 初始化前,先拦截属性末定义、又要给该属性赋0的情况
 | 
	
		
			
				|  |  |          if (!treeNode.data.feesIndex || !treeNode.data.feesIndex[feeObj.fieldName]){
 | 
	
		
			
				|  |  |              if (feeObj.unitFee == 0 && feeObj.totalFee == 0 && feeObj.tenderUnitFee == 0 && feeObj.tenderTotalFee == 0) return;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -1126,12 +1040,14 @@ let calcTools = {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          return totalFee > maxPrice;
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      getTenderCalcType: function () {
 | 
	
		
			
				|  |  |          let tenderSetting = projectObj.project.property.tenderSetting;
 | 
	
		
			
				|  |  |          let ct = tenderSetting && tenderSetting.calcPriceOption? tenderSetting.calcPriceOption : "coeBase";
 | 
	
		
			
				|  |  |          if (ct == 'priceBase') ct = 'priceBase_RCJ';   // 兼容旧项目
 | 
	
		
			
				|  |  |          return ct;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  let rationCalcBases = {
 | 
	
	
		
			
				|  | @@ -1372,8 +1288,8 @@ let analyzer = {
 | 
	
		
			
				|  |  |              for (let base of arrBase){
 | 
	
		
			
				|  |  |                  let baseName = base.slice(1, -1);
 | 
	
		
			
				|  |  |                  if (!rationCalcBases[baseName]){
 | 
	
		
			
				|  |  | -                    analyzer.error = `定额基数${hintBox.font('[' +baseName + ']')}末定义!`;
 | 
	
		
			
				|  |  | -                    // hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}末定义!`, 1);
 | 
	
		
			
				|  |  | +                    analyzer.error = `定额基数${hintBox.font('[' +baseName + ']')}未定义!`;
 | 
	
		
			
				|  |  | +                    // hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}未定义!`, 1);
 | 
	
		
			
				|  |  |                      return false;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              };
 | 
	
	
		
			
				|  | @@ -1587,7 +1503,7 @@ let executeObj = {
 | 
	
		
			
				|  |  |              return calcTools.marketPriceToBase(me.treeNode, baseName, isTender)
 | 
	
		
			
				|  |  |          else{
 | 
	
		
			
				|  |  |              if (!rationCalcBases[baseName]){
 | 
	
		
			
				|  |  | -                hintBox.infoBox('系统提示', '定额基数“' + baseName + '”末定义,计算错误。 (模板 ' + me.template.ID + ',规则 ' + me.tempCalcItem.ID +')', 1);
 | 
	
		
			
				|  |  | +                hintBox.infoBox('系统提示', '定额基数“' + baseName + '”未定义,计算错误。 (模板 ' + me.template.ID + ',规则 ' + me.tempCalcItem.ID +')', 1);
 | 
	
		
			
				|  |  |                  return 0;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              else
 | 
	
	
		
			
				|  | @@ -1641,7 +1557,7 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          me.compiledFeeTypeMaps = {};
 | 
	
		
			
				|  |  |          me.compiledFeeTypeNames = [];
 | 
	
		
			
				|  |  |          me.compiledCalcBases = {};
 | 
	
		
			
				|  |  | -        // me.saveForReports = [];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          me.feeRates = this.project.FeeRate.datas.rates;
 | 
	
		
			
				|  |  |          me.labourCoes = this.project.labourCoe.datas.coes;
 | 
	
	
		
			
				|  | @@ -1656,19 +1572,6 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          for (let t of me.templates){
 | 
	
		
			
				|  |  |              me.compileTemplate(t);
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // 存储费率临时数据,报表用。
 | 
	
		
			
				|  |  | -        // if (isInit && me.saveForReports.length > 0){
 | 
	
		
			
				|  |  | -        //     let saveDatas = {};
 | 
	
		
			
				|  |  | -        //     saveDatas.projectID = projectObj.project.projectInfo.ID;
 | 
	
		
			
				|  |  | -        //     saveDatas.calcItems = me.saveForReports;
 | 
	
		
			
				|  |  | -        //     CommonAjax.post('/calcProgram/saveCalcItems', saveDatas, function (result) {
 | 
	
		
			
				|  |  | -        //         if (result){
 | 
	
		
			
				|  |  | -        //             me.saveForReports = [];
 | 
	
		
			
				|  |  | -        //         };
 | 
	
		
			
				|  |  | -        //     });
 | 
	
		
			
				|  |  | -        // };
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      compilePublics(){
 | 
	
	
		
			
				|  | @@ -1805,275 +1708,278 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    // 删掉多余的费用。例如:①切换取费类别 ②从其它计算方式(有很多费)切换到公式计算方式(只需要common费),多出来的费要删除。
 | 
	
		
			
				|  |  | +    // 如果指定了保留字段,则按用户指定的来。如果没指定保留字段,则按默认的来:总造价清单只留common, estimate两个费用类别。其它公式清单只留common。
 | 
	
		
			
				|  |  | +    deleteUselessFees(treeNode, fieldNameArr){
 | 
	
		
			
				|  |  | +        if (!(treeNode.data.fees && treeNode.data.fees.length > 0)) return;
 | 
	
		
			
				|  |  | +        let keeps = fieldNameArr ? fieldNameArr : [];
 | 
	
		
			
				|  |  | +        // 这两个默认是要保留的
 | 
	
		
			
				|  |  | +        if (!keeps.includes('common')) keeps.push('common');
 | 
	
		
			
				|  |  | +        if (!keeps.includes('estimate')) keeps.push('estimate');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for (let i = 0; i < treeNode.data.fees.length; i++) {
 | 
	
		
			
				|  |  | +            if (!keeps.includes(treeNode.data.fees[i].fieldName)) {
 | 
	
		
			
				|  |  | +                delete treeNode.data.feesIndex[treeNode.data.fees[i].fieldName];
 | 
	
		
			
				|  |  | +                treeNode.data.fees.splice(i, 1);
 | 
	
		
			
				|  |  | +                treeNode.changed = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 不能直接删除该属性,否则无法冲掉库中已存储的值。下同。
 | 
	
		
			
				|  |  | +    deleteProperties (treeNode, propNamesArr){
 | 
	
		
			
				|  |  | +        for (let pn of propNamesArr){
 | 
	
		
			
				|  |  | +            if (treeNode.data[pn]){
 | 
	
		
			
				|  |  | +                treeNode.data[pn] = null;
 | 
	
		
			
				|  |  | +                treeNode.changed = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      // 只计算treeNode自身。changedArr: 外部传来的一个数组,专门存储发生变动的节点。
 | 
	
		
			
				|  |  |      innerCalc(treeNode, changedArr, tenderType){
 | 
	
		
			
				|  |  | +        if (treeNode.sourceType === ModuleNames.ration_glj) return;             // 仅用作树节点显示的工料机不能参与计算。
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          let me = this;
 | 
	
		
			
				|  |  | -        // 仅用作树节点显示的工料机不能参与计算。
 | 
	
		
			
				|  |  | -        if (treeNode.sourceType === ModuleNames.ration_glj) return;
 | 
	
		
			
				|  |  |          //设置定额工料机映射表
 | 
	
		
			
				|  |  |          me.setRationMap();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          treeNode.calcType = calcTools.getCalcType(treeNode);
 | 
	
		
			
				|  |  | -        let nQ = calcTools.uiNodeQty(treeNode);
 | 
	
		
			
				|  |  | -        let nTQ = calcTools.uiNodeTenderQty(treeNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        function isBaseFeeType(type){
 | 
	
		
			
				|  |  | -            return ['labour', 'material', 'machine', 'mainMaterial', 'equipment'].indexOf(type) > -1;
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | +        // 父清单汇总子清单的费用类别
 | 
	
		
			
				|  |  | +        if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees)
 | 
	
		
			
				|  |  | +            me.innerCalcBill(treeNode, 2)
 | 
	
		
			
				|  |  | +        // 叶子清单汇总定额的费用类别
 | 
	
		
			
				|  |  | +        else if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees)
 | 
	
		
			
				|  |  | +            me.innerCalcBill(treeNode, 1)
 | 
	
		
			
				|  |  | +        // 叶子清单:公式计算
 | 
	
		
			
				|  |  | +        else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue)
 | 
	
		
			
				|  |  | +            me.innerCalcBillExpr(treeNode)
 | 
	
		
			
				|  |  | +        // 叶子清单:手工修改单价或金额(无定额、无公式计算,什么都没有时)。
 | 
	
		
			
				|  |  | +        else if (treeNode.calcType == treeNodeCalcType.ctNull)
 | 
	
		
			
				|  |  | +            me.innerCalcBillCustom(treeNode)
 | 
	
		
			
				|  |  | +        // 定额:计算程序
 | 
	
		
			
				|  |  | +        else
 | 
	
		
			
				|  |  | +            me.innerCalcRation(treeNode, tenderType);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // 不能直接删除该属性,否则无法冲掉库中已存储的值。下同。
 | 
	
		
			
				|  |  | -        function deleteProperties (treeNode, propNamesArr){
 | 
	
		
			
				|  |  | -            for (let pn of propNamesArr){
 | 
	
		
			
				|  |  | -                if (treeNode.data[pn]){
 | 
	
		
			
				|  |  | -                    treeNode.data[pn] = null;
 | 
	
		
			
				|  |  | -                    treeNode.changed = true;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | +        if (!calcTools.isTotalCostBill(treeNode))  // 已在上面的分支中计算过
 | 
	
		
			
				|  |  | +            calcTools.estimateFee(treeNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // 删掉多余的费用。例如:①切换取费类别 ②从其它计算方式(有很多费)切换到公式计算方式(只需要common费),多出来的费要删除。
 | 
	
		
			
				|  |  | -        // 如果指定了保留字段,则按用户指定的来。如果没指定保留字段,则按默认的来:总造价清单只留common, estimate两个费用类别。其它公式清单只留common。
 | 
	
		
			
				|  |  | -        function deleteUselessFees(treeNode, fieldNameArr){
 | 
	
		
			
				|  |  | -            if (!(treeNode.data.fees && treeNode.data.fees.length > 0)) return;
 | 
	
		
			
				|  |  | -            let keeps = fieldNameArr ? fieldNameArr : [];
 | 
	
		
			
				|  |  | -            // 这两个默认是要保留的
 | 
	
		
			
				|  |  | -            if (!keeps.includes('common')) keeps.push('common');
 | 
	
		
			
				|  |  | -            if (!keeps.includes('estimate')) keeps.push('estimate');
 | 
	
		
			
				|  |  | +        if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            for (let i = 0; i < treeNode.data.fees.length; i++) {
 | 
	
		
			
				|  |  | -                if (!keeps.includes(treeNode.data.fees[i].fieldName)) {
 | 
	
		
			
				|  |  | -                    delete treeNode.data.feesIndex[treeNode.data.fees[i].fieldName];
 | 
	
		
			
				|  |  | -                    treeNode.data.fees.splice(i, 1);
 | 
	
		
			
				|  |  | -                    treeNode.changed = true;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | +    // 清单部分抽取出来,供分摊清单公用。commonCalcType:1 叶子清单汇总定额的费用类别; 2 父清单汇总子清单的费用类别。3: 分摊:叶子清单汇总定额的费用类别。
 | 
	
		
			
				|  |  | +    innerCalcBill(treeNode, commonCalcType, tender = tenderTypes.ttCalc){
 | 
	
		
			
				|  |  | +        let me = this;
 | 
	
		
			
				|  |  | +        treeNode.data.programID = null;
 | 
	
		
			
				|  |  | +        calcTools.initFees(treeNode);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let nodes = [];
 | 
	
		
			
				|  |  | +        if (commonCalcType == 1){
 | 
	
		
			
				|  |  | +            calcTools.getGLJList(treeNode, true);
 | 
	
		
			
				|  |  | +            nodes = me.project.Ration.getRationNodes(treeNode);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else if (commonCalcType == 2)
 | 
	
		
			
				|  |  | +            nodes = treeNode.children
 | 
	
		
			
				|  |  | +        else if (commonCalcType == 3)
 | 
	
		
			
				|  |  | +            nodes = treeNode.children;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        function isBaseFeeType(type){
 | 
	
		
			
				|  |  | +            return ['labour', 'material', 'machine', 'mainMaterial', 'equipment'].indexOf(type) > -1;
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        // 叶子清单汇总定额、父清单汇总子清单的费用类别
 | 
	
		
			
				|  |  | -        if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees || treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){
 | 
	
		
			
				|  |  | -            treeNode.data.programID = null;
 | 
	
		
			
				|  |  | -            calcTools.initFees(treeNode);
 | 
	
		
			
				|  |  | +        let rst = [];
 | 
	
		
			
				|  |  | +        for (let ft of cpFeeTypes) {
 | 
	
		
			
				|  |  | +            let ftObj = {};
 | 
	
		
			
				|  |  | +            ftObj.fieldName = ft.type;
 | 
	
		
			
				|  |  | +            ftObj.name = ft.name;
 | 
	
		
			
				|  |  | +            let buf = 0, btf = 0, btuf = 0, bttf = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            let nodes = [];
 | 
	
		
			
				|  |  | -            if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){
 | 
	
		
			
				|  |  | -                calcTools.getGLJList(treeNode, true);
 | 
	
		
			
				|  |  | -                nodes = me.project.Ration.getRationNodes(treeNode);
 | 
	
		
			
				|  |  | -            } else { //固定清单材料(工程设备)暂估价比较特殊,不进行父项汇总(需求)
 | 
	
		
			
				|  |  | -                nodes = me.project.Bills.getGatherNodes(treeNode);
 | 
	
		
			
				|  |  | +            let nQ = calcTools.uiNodeQty(treeNode);
 | 
	
		
			
				|  |  | +            let nTQ = calcTools.uiNodeTenderQty(treeNode);
 | 
	
		
			
				|  |  | +            let bq = nQ ? nQ : 1;
 | 
	
		
			
				|  |  | +            let btq = nTQ ? nTQ : 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (commonCalcType == 2){
 | 
	
		
			
				|  |  | +                for (let node of nodes) {
 | 
	
		
			
				|  |  | +                    if (node.data.feesIndex && node.data.feesIndex[ft.type]) {
 | 
	
		
			
				|  |  | +                        btf = (btf + parseFloatPlus(node.data.feesIndex[ft.type].totalFee)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                        bttf = (bttf + parseFloatPlus(node.data.feesIndex[ft.type].tenderTotalFee)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                    };
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            //else nodes = treeNode.children;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            let rst = [];
 | 
	
		
			
				|  |  | -            for (let ft of cpFeeTypes) {
 | 
	
		
			
				|  |  | -                let ftObj = {};
 | 
	
		
			
				|  |  | -                ftObj.fieldName = ft.type;
 | 
	
		
			
				|  |  | -                ftObj.name = ft.name;
 | 
	
		
			
				|  |  | -                let buf = 0, btf = 0, btuf = 0, bttf = 0;
 | 
	
		
			
				|  |  | -                let bq = nQ ? nQ : 1;
 | 
	
		
			
				|  |  | -                let btq = nTQ ? nTQ : 1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                if (treeNode.calcType == treeNodeCalcType.ctGatherBillsFees){
 | 
	
		
			
				|  |  | -                    for (let node of nodes) {
 | 
	
		
			
				|  |  | -                        if (node.data.feesIndex && node.data.feesIndex[ft.type]) { // 父清单不要汇总综合单价。
 | 
	
		
			
				|  |  | -                            btf = (btf + parseFloatPlus(node.data.feesIndex[ft.type].totalFee)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                            bttf = (bttf + parseFloatPlus(node.data.feesIndex[ft.type].tenderTotalFee)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | +            else if ((commonCalcType == 1) || (commonCalcType == 3)){
 | 
	
		
			
				|  |  | +                let sum_rtf = 0, sum_rttf = 0;
 | 
	
		
			
				|  |  | +                for (let node of nodes) {
 | 
	
		
			
				|  |  | +                    let ruf = 0, rtuf = 0, rtf = 0, rttf = 0;
 | 
	
		
			
				|  |  | +                    if (node.data.feesIndex && node.data.feesIndex[ft.type]) {
 | 
	
		
			
				|  |  | +                        ruf = parseFloatPlus(node.data.feesIndex[ft.type].unitFee).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | +                        rtuf = parseFloatPlus(node.data.feesIndex[ft.type].tenderUnitFee).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | +                        rtf = parseFloatPlus(node.data.feesIndex[ft.type].totalFee).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +                        rttf = parseFloatPlus(node.data.feesIndex[ft.type].tenderTotalFee).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  |                      };
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                else if (treeNode.calcType == treeNodeCalcType.ctGatherRationsFees){     // 这里的算法要配合冷姐姐的神图才能看懂^_^
 | 
	
		
			
				|  |  | -                    let sum_rtf = 0, sum_rttf = 0;
 | 
	
		
			
				|  |  | -                    for (let node of nodes) {
 | 
	
		
			
				|  |  | -                        let ruf = 0, rtuf = 0, rtf = 0, rttf = 0;
 | 
	
		
			
				|  |  | -                        if (node.data.feesIndex && node.data.feesIndex[ft.type]) {
 | 
	
		
			
				|  |  | -                            ruf = parseFloatPlus(node.data.feesIndex[ft.type].unitFee).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | -                            rtuf = parseFloatPlus(node.data.feesIndex[ft.type].tenderUnitFee).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | -                            rtf = parseFloatPlus(node.data.feesIndex[ft.type].totalFee).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -                            rttf = parseFloatPlus(node.data.feesIndex[ft.type].tenderTotalFee).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | -                        // 取费方式为子目含量,清单行/列的XX单价应 =ROUND( ∑ROUND(定额XX单价*含量,清单单价精度),清单单价精度)
 | 
	
		
			
				|  |  | -                        if (me.project.property.billsCalcMode === leafBillGetFeeType.rationContent) {
 | 
	
		
			
				|  |  | -                            buf = (buf + (ruf * parseFloatPlus(node.data.contain)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                            node.data.tenderContaion = (node.data.tenderQuantity / bq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                            btuf = (btuf + (rtuf * parseFloatPlus(node.data.tenderContaion)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                        };
 | 
	
		
			
				|  |  | -                        sum_rtf = (sum_rtf + rtf).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                        sum_rttf = (sum_rttf + rttf).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                    // 取费方式为子目含量,清单行/列的XX单价应 =ROUND( ∑ROUND(定额XX单价*含量,清单单价精度),清单单价精度)
 | 
	
		
			
				|  |  | +                    if (me.project.property.billsCalcMode === leafBillGetFeeType.rationContent) {
 | 
	
		
			
				|  |  | +                        buf = (buf + (ruf * parseFloatPlus(node.data.contain)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                        node.data.tenderContaion = (node.data.tenderQuantity / bq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                        btuf = (btuf + (rtuf * parseFloatPlus(node.data.tenderContaion)).toDecimal(decimalObj.bills.unitPrice)).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  |                      };
 | 
	
		
			
				|  |  | +                    sum_rtf = (sum_rtf + rtf).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                    sum_rttf = (sum_rttf + rttf).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    if (me.project.property.billsCalcMode == leafBillGetFeeType.rationPriceConverse ||
 | 
	
		
			
				|  |  | -                        me.project.property.billsCalcMode == leafBillGetFeeType.rationPrice) {
 | 
	
		
			
				|  |  | -                        buf = (sum_rtf / bq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                        btuf = (sum_rttf / btq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                    if (isBaseFeeType(ft.type) ||
 | 
	
		
			
				|  |  | -                        (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice && ft.type == "common")){
 | 
	
		
			
				|  |  | -                        btf = sum_rtf;
 | 
	
		
			
				|  |  | -                        bttf = sum_rttf;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                    else{
 | 
	
		
			
				|  |  | -                        btf = (buf.toDecimal(decimalObj.bills.unitPrice) * bq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                        bttf = (btuf.toDecimal(decimalObj.bills.unitPrice) * btq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | +                if (me.project.property.billsCalcMode == leafBillGetFeeType.rationPriceConverse ||
 | 
	
		
			
				|  |  | +                    me.project.property.billsCalcMode == leafBillGetFeeType.rationPrice) {
 | 
	
		
			
				|  |  | +                    buf = (sum_rtf / bq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                    btuf = (sum_rttf / btq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  | +                if (isBaseFeeType(ft.type) ||
 | 
	
		
			
				|  |  | +                    (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice && ft.type == "common")){
 | 
	
		
			
				|  |  | +                    btf = sum_rtf;
 | 
	
		
			
				|  |  | +                    bttf = sum_rttf;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else{
 | 
	
		
			
				|  |  | +                    btf = (buf.toDecimal(decimalObj.bills.unitPrice) * bq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                    bttf = (btuf.toDecimal(decimalObj.bills.unitPrice) * btq).toDecimal(decimalObj.process);
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                ftObj.totalFee = btf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -                ftObj.tenderTotalFee = bttf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -                ftObj.unitFee = buf.toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | -                ftObj.tenderUnitFee = btuf.toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | +            ftObj.totalFee = btf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +            ftObj.tenderTotalFee = bttf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +            ftObj.unitFee = buf.toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | +            ftObj.tenderUnitFee = btuf.toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                calcTools.checkFeeField(treeNode, ftObj);
 | 
	
		
			
				|  |  | +            calcTools.checkFeeField(treeNode, ftObj);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                rst.push(ftObj);
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            treeNode.data.calcTemplate = {"calcItems": rst};
 | 
	
		
			
				|  |  | +            rst.push(ftObj);
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        treeNode.data.calcTemplate = {"calcItems": rst};
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    innerCalcBillExpr(treeNode){
 | 
	
		
			
				|  |  | +        delete treeNode.data.gljList;
 | 
	
		
			
				|  |  | +        let me = this;
 | 
	
		
			
				|  |  | +        me.deleteProperties(treeNode, ['programID']);
 | 
	
		
			
				|  |  | +        me.deleteUselessFees(treeNode, ['common', 'rationCommon']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let nQ = calcTools.uiNodeQty(treeNode);
 | 
	
		
			
				|  |  | +        let nTQ = calcTools.uiNodeTenderQty(treeNode);
 | 
	
		
			
				|  |  | +        let f = calcTools.getFeeRateByNode(treeNode);
 | 
	
		
			
				|  |  | +        let b = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0;
 | 
	
		
			
				|  |  | +        let tb = treeNode.data.tenderCalcBaseValue ? treeNode.data.tenderCalcBaseValue : 0;
 | 
	
		
			
				|  |  | +        let q = nQ ? nQ : 1;
 | 
	
		
			
				|  |  | +        let tq = nTQ ? nTQ : 1;
 | 
	
		
			
				|  |  | +        let uf = (b * f * 0.01 / q).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | +        let tuf = (tb * f * 0.01 / tq).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | +        let tf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (b * f / 100) : (uf * q);
 | 
	
		
			
				|  |  | +        tf = tf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +        let ttf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (tb * f / 100) : (tuf * tq);
 | 
	
		
			
				|  |  | +        ttf = ttf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        calcTools.checkFeeField(treeNode, {'fieldName': 'common', 'unitFee': uf, 'totalFee': tf, 'tenderUnitFee': tuf, 'tenderTotalFee': ttf});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 总造价清单还要做单项工程、建设项目的四大项金额汇总
 | 
	
		
			
				|  |  | +        if (calcTools.isTotalCostBill(treeNode)){
 | 
	
		
			
				|  |  | +            // 公式叶子清单没有暂估费,但总造价清单除外。
 | 
	
		
			
				|  |  | +            calcTools.estimateFee(treeNode);
 | 
	
		
			
				|  |  | +            calcTools.initSummaryFee(treeNode);
 | 
	
		
			
				|  |  | +            treeNode.data.summaryFees.totalFee = tf;
 | 
	
		
			
				|  |  | +            treeNode.data.summaryFees.estimateFee = calcTools.getFee(treeNode, 'estimate.totalFee');
 | 
	
		
			
				|  |  | +            treeNode.data.summaryFees.safetyFee = calcTools.getFee(calcTools.getNodeByFlag(fixedFlag.SAFETY_CONSTRUCTION), 'common.totalFee');
 | 
	
		
			
				|  |  | +            treeNode.data.summaryFees.chargeFee = calcTools.getFee(calcTools.getNodeByFlag(fixedFlag.CHARGE), 'common.totalFee');
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        // 叶子清单无子结点、无公式计算(啥都没有时)
 | 
	
		
			
				|  |  | -        else if (treeNode.calcType == treeNodeCalcType.ctNull){
 | 
	
		
			
				|  |  | -            delete treeNode.data.gljList;
 | 
	
		
			
				|  |  | -            deleteProperties(treeNode, ['calcBase', 'calcBaseValue', 'tenderCalcBaseValue', 'programID']);
 | 
	
		
			
				|  |  | -            deleteUselessFees(treeNode, ['rationCommon']);
 | 
	
		
			
				|  |  | -            // 不能直接删除该属性,否则无法冲掉库中已存储的值。下同。
 | 
	
		
			
				|  |  | -/*            if (treeNode.data.calcBase){
 | 
	
		
			
				|  |  | -                treeNode.data.calcBase = null;
 | 
	
		
			
				|  |  | -                treeNode.changed = true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (treeNode.data.calcBaseValue){
 | 
	
		
			
				|  |  | -                treeNode.data.calcBaseValue = null;
 | 
	
		
			
				|  |  | -                treeNode.changed = true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        treeNode.data.calcTemplate = {"calcItems": []};
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (treeNode.data.tenderCalcBaseValue){
 | 
	
		
			
				|  |  | -                treeNode.data.tenderCalcBaseValue = null;
 | 
	
		
			
				|  |  | +    innerCalcBillCustom(treeNode){
 | 
	
		
			
				|  |  | +        let me = this;
 | 
	
		
			
				|  |  | +        delete treeNode.data.gljList;
 | 
	
		
			
				|  |  | +        me.deleteProperties(treeNode, ['calcBase', 'calcBaseValue', 'tenderCalcBaseValue', 'programID']);
 | 
	
		
			
				|  |  | +        me.deleteUselessFees(treeNode, ['rationCommon']);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 2017-09-27 需求改了,除了第 1 、 2.2部分以外,都可以手工修改综合单价、综合合价并参与计算
 | 
	
		
			
				|  |  | +        // 在没有公式的情况下可以手工修改综合单价并参与计算
 | 
	
		
			
				|  |  | +        if(calcTools.canCalcToTalFeeByOwn(treeNode)){
 | 
	
		
			
				|  |  | +            if (treeNode.data.feesIndex && treeNode.data.feesIndex.common){
 | 
	
		
			
				|  |  | +                let ftObj = {fieldName: 'common'};
 | 
	
		
			
				|  |  | +                let nQ = calcTools.uiNodeQty(treeNode);
 | 
	
		
			
				|  |  | +                let nTQ = calcTools.uiNodeTenderQty(treeNode);
 | 
	
		
			
				|  |  | +                ftObj.unitFee = parseFloatPlus(treeNode.data.feesIndex.common.unitFee);
 | 
	
		
			
				|  |  | +                ftObj.totalFee = (ftObj.unitFee * nQ).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +                ftObj.tenderUnitFee = ftObj.unitFee;
 | 
	
		
			
				|  |  | +                ftObj.tenderTotalFee = (ftObj.tenderUnitFee * nTQ).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | +                calcTools.checkFeeField(treeNode, ftObj);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } else{
 | 
	
		
			
				|  |  | +            if (treeNode.data.fees && treeNode.data.fees.length > 0){
 | 
	
		
			
				|  |  | +                treeNode.data.fees = null;
 | 
	
		
			
				|  |  | +                treeNode.data.feesIndex = null;
 | 
	
		
			
				|  |  |                  treeNode.changed = true;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (treeNode.data.programID) {
 | 
	
		
			
				|  |  | -                treeNode.data.programID = null;
 | 
	
		
			
				|  |  | -                treeNode.changed = true;
 | 
	
		
			
				|  |  | -            };*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // 第1、2部分以外的叶子清单在没有公式的情况下可以手工修改综合单价并参与计算。
 | 
	
		
			
				|  |  | -            // 2017-09-27 需求改了,除了第 1 、 2.2部分以外,都可以手工修改综合单价、综合合价并参与计算
 | 
	
		
			
				|  |  | -            //if(!calcTools.isFBFX(treeNode) && !calcTools.isTechMeasure(treeNode)){ // if(!calcTools.isInheritFrom(treeNode, [fixedFlag.SUB_ENGINERRING, fixedFlag.MEASURE]))
 | 
	
		
			
				|  |  | -            // 在没有公式的情况下可以手工修改综合单价并参与计算
 | 
	
		
			
				|  |  | -            if(calcTools.canCalcToTalFeeByOwn(treeNode)){
 | 
	
		
			
				|  |  | -                if (treeNode.data.feesIndex && treeNode.data.feesIndex.common){
 | 
	
		
			
				|  |  | -                    let ftObj = {};
 | 
	
		
			
				|  |  | -                    ftObj.fieldName = 'common';
 | 
	
		
			
				|  |  | -                    ftObj.unitFee = parseFloatPlus(treeNode.data.feesIndex.common.unitFee);
 | 
	
		
			
				|  |  | -                    ftObj.totalFee = (ftObj.unitFee * nQ).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -                    ftObj.tenderUnitFee = ftObj.unitFee;
 | 
	
		
			
				|  |  | -                    ftObj.tenderTotalFee = (ftObj.tenderUnitFee * nTQ).toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -                    calcTools.checkFeeField(treeNode, ftObj);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            } else{
 | 
	
		
			
				|  |  | -                if (treeNode.data.fees && treeNode.data.fees.length > 0){
 | 
	
		
			
				|  |  | -                    treeNode.data.fees = null;
 | 
	
		
			
				|  |  | -                    treeNode.data.feesIndex = null;
 | 
	
		
			
				|  |  | +        treeNode.data.calcTemplate = {"calcItems": []};
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 定额部分抽取出来,供分摊定额公用。
 | 
	
		
			
				|  |  | +    innerCalcRation(treeNode, tenderType = tenderTypes.ttCalc){
 | 
	
		
			
				|  |  | +        let me = this;
 | 
	
		
			
				|  |  | +        let fnArr = [];
 | 
	
		
			
				|  |  | +        calcTools.getGLJList(treeNode, true);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let nQ = calcTools.uiNodeQty(treeNode);
 | 
	
		
			
				|  |  | +        let nTQ = calcTools.uiNodeTenderQty(treeNode);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
 | 
	
		
			
				|  |  | +            // 量价、工料机类型的定额要求"市场合价"
 | 
	
		
			
				|  |  | +            if (calcTools.isVP_or_GLJR(treeNode)){
 | 
	
		
			
				|  |  | +                let u = treeNode.data.marketUnitFee ? treeNode.data.marketUnitFee : 0;
 | 
	
		
			
				|  |  | +                let t = (u * nQ).toDecimal(decimalObj.ration.totalPrice);
 | 
	
		
			
				|  |  | +                if (treeNode.data.marketTotalFee != t){
 | 
	
		
			
				|  |  | +                    treeNode.data.marketTotalFee = t;
 | 
	
		
			
				|  |  |                      treeNode.changed = true;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | +                } ;
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            treeNode.data.calcTemplate = {"calcItems": []};
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        // 叶子清单公式计算
 | 
	
		
			
				|  |  | -        else if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
 | 
	
		
			
				|  |  | -            delete treeNode.data.gljList;
 | 
	
		
			
				|  |  | +        let template = me.compiledTemplates[treeNode.data.programID];
 | 
	
		
			
				|  |  | +        treeNode.data.calcTemplate = template;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (treeNode.data.programID) {
 | 
	
		
			
				|  |  | -                treeNode.data.programID = null;
 | 
	
		
			
				|  |  | -                treeNode.changed = true;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            let f = calcTools.getFeeRateByNode(treeNode);
 | 
	
		
			
				|  |  | -            let b = treeNode.data.calcBaseValue ? treeNode.data.calcBaseValue : 0;
 | 
	
		
			
				|  |  | -            let tb = treeNode.data.tenderCalcBaseValue ? treeNode.data.tenderCalcBaseValue : 0;
 | 
	
		
			
				|  |  | -            let q = nQ ? nQ : 1;
 | 
	
		
			
				|  |  | -            let tq = nTQ ? nTQ : 1;
 | 
	
		
			
				|  |  | -            let uf = (b * f * 0.01 / q).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | -            let tuf = (tb * f * 0.01 / tq).toDecimal(decimalObj.bills.unitPrice);
 | 
	
		
			
				|  |  | -            let tf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (b * f / 100) : (uf * q);
 | 
	
		
			
				|  |  | -            tf = tf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -            let ttf = (me.project.property.billsCalcMode === leafBillGetFeeType.rationPrice) ? (tb * f / 100) : (tuf * tq);
 | 
	
		
			
				|  |  | -            ttf = ttf.toDecimal(decimalObj.bills.totalPrice);
 | 
	
		
			
				|  |  | -            deleteUselessFees(treeNode);
 | 
	
		
			
				|  |  | -            calcTools.checkFeeField(treeNode, {'fieldName': 'common', 'unitFee': uf, 'totalFee': tf, 'tenderUnitFee': tuf, 'tenderTotalFee': ttf});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // 总造价清单还要做单项工程、建设项目的四大项金额汇总
 | 
	
		
			
				|  |  | -            if (calcTools.isTotalCostBill(treeNode)){
 | 
	
		
			
				|  |  | -                // 公式叶子清单没有暂估费,但总造价清单除外。
 | 
	
		
			
				|  |  | -                calcTools.estimateFee(treeNode);
 | 
	
		
			
				|  |  | -                calcTools.initSummaryFee(treeNode);
 | 
	
		
			
				|  |  | -                treeNode.data.summaryFees.totalFee = tf;
 | 
	
		
			
				|  |  | -                treeNode.data.summaryFees.estimateFee = calcTools.getFee(treeNode, 'estimate.totalFee');
 | 
	
		
			
				|  |  | -                treeNode.data.summaryFees.safetyFee = calcTools.getFee(calcTools.getNodeByFlag(fixedFlag.SAFETY_CONSTRUCTION), 'common.totalFee');
 | 
	
		
			
				|  |  | -                treeNode.data.summaryFees.chargeFee = calcTools.getFee(calcTools.getNodeByFlag(fixedFlag.CHARGE), 'common.totalFee');
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        if (treeNode && template && template.hasCompiled) {//2018-08-27 空行的时候,取费专业为空,template也为空,加入template非空判断
 | 
	
		
			
				|  |  | +            let $CE = executeObj;
 | 
	
		
			
				|  |  | +            $CE.treeNode = treeNode;
 | 
	
		
			
				|  |  | +            $CE.template = template;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            treeNode.data.calcTemplate = {"calcItems": []};
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        // 定额或叶子清单自己的计算程序计算
 | 
	
		
			
				|  |  | -        else{
 | 
	
		
			
				|  |  | -            let fnArr = [];
 | 
	
		
			
				|  |  | -            calcTools.getGLJList(treeNode, true);
 | 
	
		
			
				|  |  | +            calcTools.initFees(treeNode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
 | 
	
		
			
				|  |  | -                // 量价、工料机类型的定额要求市场合价
 | 
	
		
			
				|  |  | -                if (calcTools.isVP_or_GLJR(treeNode)){
 | 
	
		
			
				|  |  | -                    let muf = treeNode.data.marketUnitFee ? treeNode.data.marketUnitFee : 0;
 | 
	
		
			
				|  |  | -                    let mtf = (muf * nQ).toDecimal(decimalObj.ration.totalPrice);
 | 
	
		
			
				|  |  | -                    if (treeNode.data.marketTotalFee != mtf){
 | 
	
		
			
				|  |  | -                        treeNode.data.marketTotalFee = mtf;
 | 
	
		
			
				|  |  | -                        treeNode.changed = true;
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | +            for (let idx of template.compiledSeq) {
 | 
	
		
			
				|  |  | +                let calcItem = template.calcItems[idx];
 | 
	
		
			
				|  |  | +                $CE.tempCalcItem = calcItem;
 | 
	
		
			
				|  |  | +                let feeRate = 100;  // 100%
 | 
	
		
			
				|  |  | +                if (calcItem.feeRate != undefined)
 | 
	
		
			
				|  |  | +                    feeRate = parseFloat(calcItem.feeRate).toDecimal(decimalObj.feeRate);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                calcItem.unitFee = (eval(calcItem.compiledExpr) * feeRate * 0.01).toDecimal(decimalObj.decimal('unitPrice', treeNode));
 | 
	
		
			
				|  |  | +                calcItem.totalFee = (calcItem.unitFee * nQ).toDecimal(decimalObj.decimal('totalPrice', treeNode));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                let tExpr = analyzer.getCompiledTenderExpr(calcItem.compiledExpr);
 | 
	
		
			
				|  |  | +                calcItem.tenderUnitFee = (eval(tExpr) * feeRate * 0.01).toDecimal(decimalObj.decimal('unitPrice', treeNode));
 | 
	
		
			
				|  |  | +                calcItem.tenderTotalFee = (calcItem.tenderUnitFee * nTQ).toDecimal(decimalObj.decimal('totalPrice', treeNode));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (calcItem.fieldName) {
 | 
	
		
			
				|  |  | +                    fnArr.push(calcItem.fieldName);
 | 
	
		
			
				|  |  | +                    calcTools.checkFeeField(treeNode, calcItem);
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  | -            // 2018-08-27   zhang  插入空定额的时候,取费专业也为空
 | 
	
		
			
				|  |  | -           // if (treeNode.data.programID == undefined) treeNode.data.programID = projectObj.project.projectInfo.property.engineering;
 | 
	
		
			
				|  |  | -            let template = me.compiledTemplates[treeNode.data.programID];
 | 
	
		
			
				|  |  | -            treeNode.data.calcTemplate = template;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (treeNode && template && template.hasCompiled) {//2018-08-27 空行的时候,取费专业为空,template也为空,加入template非空判断
 | 
	
		
			
				|  |  | -                let $CE = executeObj;
 | 
	
		
			
				|  |  | -                $CE.treeNode = treeNode;
 | 
	
		
			
				|  |  | -                $CE.template = template;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                calcTools.initFees(treeNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                for (let idx of template.compiledSeq) {
 | 
	
		
			
				|  |  | -                    let calcItem = template.calcItems[idx];
 | 
	
		
			
				|  |  | -                    $CE.tempCalcItem = calcItem;
 | 
	
		
			
				|  |  | -                    let feeRate = 100;  // 100%
 | 
	
		
			
				|  |  | -                    if (calcItem.feeRate != undefined)
 | 
	
		
			
				|  |  | -                        feeRate = parseFloat(calcItem.feeRate).toDecimal(decimalObj.feeRate);
 | 
	
		
			
				|  |  | -                    // console.log(`[${calcItem.ID}]: ${calcItem.compiledExpr}`);   // for test.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    calcItem.unitFee = (eval(calcItem.compiledExpr) * feeRate * 0.01).toDecimal(decimalObj.decimal('unitPrice', treeNode));
 | 
	
		
			
				|  |  | -                    calcItem.totalFee = (calcItem.unitFee * calcTools.uiNodeQty(treeNode)).toDecimal(decimalObj.decimal('totalPrice', treeNode));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    // if (tenderType == tenderTypes.ttCalc) {
 | 
	
		
			
				|  |  | -                        let tExpr = analyzer.getCompiledTenderExpr(calcItem.compiledExpr);
 | 
	
		
			
				|  |  | -                        calcItem.tenderUnitFee = (eval(tExpr) * feeRate * 0.01).toDecimal(decimalObj.decimal('unitPrice', treeNode));
 | 
	
		
			
				|  |  | -                        calcItem.tenderTotalFee = (calcItem.tenderUnitFee * treeNode.data.tenderQuantity).toDecimal(decimalObj.decimal('totalPrice', treeNode));
 | 
	
		
			
				|  |  | -                    // };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                    if (calcItem.fieldName) {
 | 
	
		
			
				|  |  | -                        fnArr.push(calcItem.fieldName);
 | 
	
		
			
				|  |  | -                        calcTools.checkFeeField(treeNode, calcItem);
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (tenderType == tenderTypes.ttReverseRation || tenderType == tenderTypes.ttReverseGLJ)
 | 
	
		
			
				|  |  | -                    this.calcTenderReverse(treeNode, tenderType);
 | 
	
		
			
				|  |  | +            if (tenderType == tenderTypes.ttReverseRation || tenderType == tenderTypes.ttReverseGLJ)
 | 
	
		
			
				|  |  | +                this.calcTenderReverse(treeNode, tenderType);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                deleteUselessFees(treeNode, fnArr);
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | +            me.deleteUselessFees(treeNode, fnArr);
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if (!calcTools.isTotalCostBill(treeNode))  // 已在上面的分支中计算过
 | 
	
		
			
				|  |  | -            calcTools.estimateFee(treeNode);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if (treeNode.changed && !changedArr.includes(treeNode)) changedArr.push(treeNode);
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      // 存储、刷新零散的多个结点。
 | 
	
		
			
				|  |  |      saveNodes(treeNodes, callback){
 | 
	
		
			
				|  |  |          if (treeNodes.length < 1) {
 | 
	
	
		
			
				|  | @@ -2100,8 +2006,6 @@ class CalcProgram {
 | 
	
		
			
				|  |  |          $.bootstrapLoading.start();
 | 
	
		
			
				|  |  |          let startTime = +new Date();
 | 
	
		
			
				|  |  |          me.project.updateNodes(dataArr, function (data) {
 | 
	
		
			
				|  |  | -            let endShowTime = +new Date();
 | 
	
		
			
				|  |  | -            console.log(`保存所需时间——${endShowTime - startTime}`);
 | 
	
		
			
				|  |  |              me.rationMap = null;
 | 
	
		
			
				|  |  |              me.pgljMap = null;
 | 
	
		
			
				|  |  |              if(callback){
 | 
	
	
		
			
				|  | @@ -2139,10 +2043,11 @@ class CalcProgram {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          return changedNodes;
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    // 计算并保存本节点及所有会被影响到的节点。
 | 
	
		
			
				|  |  | +    // 计算并保存一个树节点。(修改一个树节点,实际上要计算和保存的是一批树结点:层层父结点、被其它结点(的公式)引用的公式结点)
 | 
	
		
			
				|  |  |      calcAndSave(treeNode, callback, tender){
 | 
	
		
			
				|  |  | -        let changedNodes = this.calculate(treeNode, true, true, tender);
 | 
	
		
			
				|  |  | -        this.saveNodes(changedNodes, callback);
 | 
	
		
			
				|  |  | +        this.calcNodesAndSave([treeNode],callback,tender);
 | 
	
		
			
				|  |  | +      /*  let changedNodes = this.calculate(treeNode, true, true, tender); 统一调用相同的方法
 | 
	
		
			
				|  |  | +        this.saveNodes(changedNodes, callback);*/
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* 计算所有树结点(分3种情况),并返回发生变动的零散的多个树结点。参数取值如下:
 | 
	
	
		
			
				|  | @@ -2161,6 +2066,7 @@ class CalcProgram {
 | 
	
		
			
				|  |  |                  if (node.children.length > 0) {
 | 
	
		
			
				|  |  |                      calcNodes(node.children);
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                  if (calcType == calcAllType.catAll || calcType == node.sourceType) {
 | 
	
		
			
				|  |  |                      node.calcType = calcTools.getCalcType(node);
 | 
	
		
			
				|  |  |                      if (node.calcType != treeNodeCalcType.ctCalcBaseValue)
 |