Browse Source

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhongzewei 7 years ago
parent
commit
cf7cc31922

+ 138 - 69
public/calc_util.js

@@ -4,14 +4,6 @@
  * added by CSL, 2017-09-01 增加公式解析对象analyzer,用于解析用户修改公式、自定义表达式。
  */
 
-// 需求说小数位数固定为2位,这里预留缓冲接口,防止以后需求变卦。
-const Digit_Calc_Program = -2;              // 需求指定计算程序用到的小数位数。
-const Digit_Calc_Program_Default = -6;      // 需求末指定时默认用到的小数位数。
-function round(value, useDef = false) {
-    let digit = useDef ? Digit_Calc_Program_Default : Digit_Calc_Program;
-    return scMathUtil.roundTo(value, digit);
-};
-
 let executeObj = {
     treeNode: null,
     template: null,
@@ -52,12 +44,12 @@ let executeObj = {
                                if (base.gljTypes.indexOf(md.glj_type) >= 0) {
                                    price = md["base_price"];
                                    if (!price) price = 0;
-                                   mdSum = mdSum +  round(md["consumption"] * price);
-                                   mdSum = round(mdSum, true);
+                                   mdSum = mdSum + (md["consumption"] * price).toDecimal(me.digit);
+                                   mdSum = (mdSum).toDecimal(me.digitDefault);
                                }
                            };
-                           tmpSum = tmpSum + round(glj["quantity"] * mdSum, true);
-                           tmpSum = round(tmpSum, true);
+                           tmpSum = tmpSum + (glj["quantity"] * mdSum).toDecimal(me.digitDefault);
+                           tmpSum = (tmpSum).toDecimal(me.digitDefault);
                        }
                 };
             }else{
@@ -74,15 +66,20 @@ let executeObj = {
                             price = mprice - aprice;
                         };
                         if (!price) price = 0;
-                        tmpSum = round(tmpSum + round(glj["quantity"] * price, true), true);
+                        tmpSum = tmpSum + (glj["quantity"] * price).toDecimal(me.digitDefault);
+                        tmpSum = (tmpSum).toDecimal(me.digitDefault);
                     };
                 };
             };
 
-            rst = round(tmpSum);
+            rst = (tmpSum).toDecimal(me.digitDefault);
         };
 
         return rst;
+    },
+    HJ: function () {
+        let me = this;
+        return me.treeNode.data.baseTotalPrice;
     }
 };
 
@@ -238,6 +235,8 @@ class Calculation {
         me.compiledFeeTypeNames = [];
         me.compiledCalcBases = {};
         me.saveForReports = [];
+        me.digit = 2;
+        me.digitDefault = 6;
 
         let private_compile_feeRateFile = function() {
             if (feeRates) {
@@ -338,8 +337,13 @@ class Calculation {
             for (let idx of template.compiledSeq) {
                 let item = template.calcItems[idx];
                 item.dispExprUser = item.dispExpr;    // 用于界面显示。disExpr是公式模板,不允许修改:人工系数占位符被修改后变成数值,第二次无法正确替换。
-                item.compiledExpr = item.expression.split('@(').join('$CE.at(');
-                item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
+                if (item.expression == 'HJ')
+                    item.compiledExpr = '$CE.HJ()'
+                else{
+                    item.compiledExpr = item.expression.split('@(').join('$CE.at(');
+                    item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
+                };
+
                 if (item.labourCoeID){
                     let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe;
                     item.dispExprUser = item.dispExpr.replace(/L/gi, lc.toString());
@@ -383,65 +387,130 @@ class Calculation {
         };
     };
 
-    calculate($treeNode){
-        let me = this;
-        let templateID = $treeNode.data.programID;
-        if (!templateID) templateID = 1;
-        let template = me.compiledTemplates[templateID];
-        $treeNode.data.calcTemplate = template;
-
-        if ($treeNode && template.hasCompiled) {
-            let $CE = executeObj;
-            $CE.treeNode = $treeNode;
-            $CE.template = template;
-            $CE.calcBase = me.compiledCalcBases;
-
-            if (!$treeNode.data.fees) {
-                $treeNode.data.fees = [];
-                $treeNode.data.feesIndex = {};
-                $treeNode.changed = true;
+    initFees(treeNode){
+        if (!treeNode.data.fees) {
+            treeNode.data.fees = [];
+            treeNode.data.feesIndex = {};
+            treeNode.changed = true;
+        };
+    };
+
+    checkFee(treeNode, feeObj){
+        if (feeObj.fieldName == '') return;
+
+        if (!treeNode.data.feesIndex[feeObj.fieldName]){
+            let fee = {
+                'fieldName': feeObj.fieldName,
+                'unitFee': feeObj.unitFee,
+                'totalFee': feeObj.totalFee,
+                'tenderUnitFee': 0,
+                'tenderTotalFee': 0
+            };
+            treeNode.data.fees.push(fee);
+            treeNode.data.feesIndex[feeObj.fieldName] = fee;
+            treeNode.changed = true;
+        }
+        else{
+            if (treeNode.data.feesIndex[feeObj.fieldName].unitFee != feeObj.unitFee){
+                treeNode.data.feesIndex[feeObj.fieldName].unitFee = feeObj.unitFee;
+                treeNode.changed = true;
             };
 
-            for (let idx of template.compiledSeq) {
-                let calcItem = template.calcItems[idx];
-
-                let feeRate = calcItem.feeRate;
-                if (!feeRate) feeRate = 100;    // 100%
-                calcItem.unitFee = round(eval(calcItem.compiledExpr) * feeRate * 0.01);   // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
-
-                let quantity = $treeNode.data.quantity;
-                if (!quantity) quantity = 0;
-                calcItem.totalFee = round(calcItem.unitFee * quantity);
-
-                // 费用同步到定额
-                // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。
-                if (calcItem.fieldName != '') {
-                    if (!$treeNode.data.feesIndex[calcItem.fieldName]){
-                        let fee = {
-                            'fieldName': calcItem.fieldName,
-                            'unitFee': calcItem.unitFee,
-                            'totalFee': calcItem.totalFee,
-                            'tenderUnitFee': 0,
-                            'tenderTotalFee': 0
-                        };
-                        $treeNode.data.fees.push(fee);
-                        $treeNode.data.feesIndex[calcItem.fieldName] = fee;
-                        $treeNode.changed = true;
-                    }
-                    else{
-                        if ($treeNode.data.feesIndex[calcItem.fieldName].unitFee != calcItem.unitFee){
-                            $treeNode.data.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee;
-                            $treeNode.changed = true;
-                        };
+            if (treeNode.data.feesIndex[feeObj.fieldName].totalFee != feeObj.totalFee){
+                treeNode.data.feesIndex[feeObj.fieldName].totalFee = feeObj.totalFee;
+                treeNode.changed = true;
+            };
+        };
+    };
 
-                        if ($treeNode.data.feesIndex[calcItem.fieldName].totalFee != calcItem.totalFee){
-                            $treeNode.data.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee;
-                            $treeNode.changed = true;
-                        };
-                    }
+    calculate(treeNode){
+        let me = this;
+        let project = projectObj.project;
+
+        // 汇总定额或子清单的费用类别
+        if (treeNode.data.gatherType != undefined){
+            if (treeNode.sourceType != project.Bills.getSourceType()) return;
+
+            me.initFees(treeNode);
+
+            let objsArr = (treeNode.data.gatherType === CP_GatherType.rations) ? project.Ration.getRationsByNode(treeNode) : treeNode.children;
+            let rst = [];
+            for (let ft of feeType) {
+                let ftObj = {};
+                ftObj.fieldName = ft.type;
+                ftObj.name = ft.name;
+                let uf = 0, tf = 0, tuf = 0, ttf = 0;
+                for (let item of objsArr) {
+                    let data = (treeNode.data.gatherType === CP_GatherType.rations) ? item : item.data;
+                    if (data.feesIndex && data.feesIndex[ft.type]) {
+                        uf = (uf + parseFloat(data.feesIndex[ft.type].unitFee)).toDecimal(me.digitDefault);
+                        tf = (tf + parseFloat(data.feesIndex[ft.type].totalFee)).toDecimal(me.digitDefault);
+                        tuf = (tuf + parseFloat(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(me.digitDefault);
+                        ttf = (ttf + parseFloat(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(me.digitDefault);
+                    };
                 };
+                ftObj.unitFee = uf.toDecimal(me.digit);
+                ftObj.totalFee = tf.toDecimal(me.digit);
+                ftObj.tenderUnitFee = tuf.toDecimal(me.digit);
+                ftObj.tenderTotalFee = ttf.toDecimal(me.digit);
+
+                me.checkFee(treeNode, ftObj);
+
+                rst.push(ftObj);
             };
+            treeNode.data.calcTemplate = {"calcItems": rst};
         }
+        else{
+            // 叶子清单的缺省计算程序需要提供总金额作为计算基数(不需要工料机),然后每条按比例(费率)计算,不需要工料机明细。
+            if (treeNode.data.baseTotalPrice != undefined){
+                if (treeNode.sourceType != project.Bills.getSourceType()) return;
+
+                delete treeNode.data.gljList;
+
+                if (treeNode.data.programID == undefined){
+                    treeNode.data.programID = defaultBillTemplate.ID;
+                };
+            }
+            else {
+                if (treeNode.sourceType === project.Ration.getSourceType()) {
+                    treeNode.data.gljList = project.ration_glj.getGljArrByRation(treeNode.data.ID);
+                }
+                else if (treeNode.sourceType === project.Bills.getSourceType()) {
+                    let rations = project.Ration.getBillsSortRation(treeNode.source.getID());
+                    treeNode.data.gljList = project.ration_glj.getGatherGljArrByRations(rations);
+                };
+
+                if (treeNode.data.programID == undefined){
+                    treeNode.data.programID = 1;
+                };
+            };
+
+            let template = me.compiledTemplates[treeNode.data.programID];
+            treeNode.data.calcTemplate = template;
+
+            if (treeNode && template.hasCompiled) {
+                let $CE = executeObj;
+                $CE.treeNode = treeNode;
+                $CE.template = template;
+                $CE.calcBase = me.compiledCalcBases;
+
+                me.initFees(treeNode);
+
+                for (let idx of template.compiledSeq) {
+                    let calcItem = template.calcItems[idx];
+
+                    let feeRate = calcItem.feeRate;
+                    if (!feeRate) feeRate = 100;    // 100%
+                    calcItem.unitFee = (eval(calcItem.compiledExpr) * feeRate * 0.01).toDecimal(me.digit);   // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
+
+                    let quantity = treeNode.data.quantity;
+                    if (!quantity) quantity = 0;
+                    calcItem.totalFee = (calcItem.unitFee * quantity).toDecimal(me.digit);
+
+                    me.checkFee(treeNode, calcItem);
+                };
+            }
+        };
     }
 };
 

+ 4 - 2
web/building_saas/css/main.css

@@ -10,6 +10,9 @@ body {
 .btn.disabled, .btn:disabled {
   color:#999
 }
+.btn-link:focus, .btn-link:hover{
+  text-decoration: none
+}
 /*自定义css*/
 .header {
     background: #e1e1e1
@@ -306,6 +309,5 @@ body {
   border-bottom:1px solid #ddd
 }
 .navbar-crumb span{
-  max-width: 200px;
-  display: inline-block;
+  max-width: 200px
 }

+ 112 - 231
web/building_saas/main/js/models/calc_program.js

@@ -5,102 +5,104 @@
  *  用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
  */
 
-let defaultBillTemplate = [
-    {
-        ID: 1,
-        serialNo: '一',
-        code: "A",
-        name: "定额直接费",
-        dispExpr: "A1+A2+A3",
-        statement: "人工费+材料费+机械费",
-        feeRate: null,
-        memo: ''
-    },
-    {
-        ID: 2,
-        serialNo: '1',
-        code: "A1",
-        name: "人工费",
-        dispExpr: "HJ",
-        statement: "合计",
-        feeRate: 50,
-        fieldName: 'labour',
-        memo: ''
-    },
-    {
-        ID: 3,
-        serialNo: '2',
-        code: "A2",
-        name: "材料费",
-        dispExpr: "HJ",
-        statement: "合计",
-        feeRate: 30,
-        fieldName: 'material',
-        memo: ''
-    },
-    {
-        ID: 4,
-        serialNo: '3',
-        code: "A3",
-        name: "机械费",
-        dispExpr: "HJ",
-        statement: "合计",
-        feeRate: 20,
-        fieldName: 'machine',
-        memo: ''
-    },
-    {
-        ID: 5,
-        serialNo: '二',
-        code: "A4",
-        name: "管理费",
-        dispExpr: "A",
-        statement: "定额直接费",
-        feeRate: null,
-        fieldName: 'manage',
-        memo: ''
-    },
-    {
-        ID: 6,
-        serialNo: '三',
-        code: "B",
-        name: "利润",
-        dispExpr: "A",
-        statement: "定额直接费",
-        feeRate: null,
-        fieldName: 'profit',
-        memo: ''
-    },
-    {
-        ID: 7,
-        serialNo: '四',
-        code: "C",
-        name: "风险费用",
-        dispExpr: "",
-        statement: "",
-        feeRate: null,
-        fieldName: 'risk',
-        memo: ''
-    },
-    {
-        ID: 8,
-        serialNo: '',
-        code: "",
-        name: "综合单价",
-        dispExpr: "A+B",
-        statement: "定额直接费+利润",
-        feeRate: null,
-        fieldName: 'common',
-        memo: ''
-    }
-];
+let defaultBillTemplate = {
+    ID: 15,
+    name: "清单缺省",
+    calcItems: [
+        {
+            ID: 1,
+            code: "1",
+            name: "定额直接费",
+            dispExpr: "F2+F3+F4",
+            expression: "@('2')+@('3')+@('4')",
+            statement: "人工费+材料费+机械费",
+            feeRate: null,
+            memo: ''
+        },
+        {
+            ID: 2,
+            code: "1.1",
+            name: "人工费",
+            dispExpr: "HJ",
+            expression: "HJ",
+            statement: "合计",
+            feeRate: 50,
+            fieldName: 'labour',
+            memo: ''
+        },
+        {
+            ID: 3,
+            code: "1.2",
+            name: "材料费",
+            dispExpr: "HJ",
+            expression: "HJ",
+            statement: "合计",
+            feeRate: 30,
+            fieldName: 'material',
+            memo: ''
+        },
+        {
+            ID: 4,
+            code: "1.3",
+            name: "机械费",
+            dispExpr: "HJ",
+            expression: "HJ",
+            statement: "合计",
+            feeRate: 20,
+            fieldName: 'machine',
+            memo: ''
+        },
+        {
+            ID: 5,
+            code: "2",
+            name: "企业管理费",
+            dispExpr: "F1",
+            expression: "@('1')",
+            statement: "定额直接费",
+            feeRate: null,
+            fieldName: 'manage',
+            memo: ''
+        },
+        {
+            ID: 6,
+            code: "3",
+            name: "利润",
+            dispExpr: "F1",
+            expression: "@('1')",
+            statement: "定额直接费",
+            feeRate: null,
+            fieldName: 'profit',
+            memo: ''
+        },
+        {
+            ID: 7,
+            code: "4",
+            name: "风险费用",
+            dispExpr: "F1",
+            expression: "@('1')",
+            statement: "定额直接费",
+            feeRate: null,
+            fieldName: 'risk',
+            memo: ''
+        },
+        {
+            ID: 8,
+            code: "5",
+            name: "综合单价",
+            dispExpr: "F1+F5+F6+F7",
+            expression: "@('1')+@('5')+@('6')+@('7')",
+            statement: "定额直接费+企业管理费+利润+风险费用",
+            feeRate: null,
+            fieldName: 'common',
+            memo: ''
+        }
+    ]
+};
 
 class CalcProgram {
     constructor(project){
         this.project = project;
         this.datas = [];
-        this.digit = 2;
-        this.digitDefault = 6;
         this.calc = new Calculation();
         project.registerModule(ModuleNames.calc_program, this);
     };
@@ -124,6 +126,7 @@ class CalcProgram {
         let calcFeeRates = this.project.FeeRate.datas.rates;
         let calcLabourCoes = this.project.labourCoe.datas.coes;
         let calcTemplates = this.project.calcProgram.datas.templates;
+        calcTemplates.push(defaultBillTemplate);
 
         this.calc.compilePublics(calcFeeRates, calcLabourCoes, feeType, rationCalcBase);
         for (let ct of calcTemplates){
@@ -143,22 +146,18 @@ class CalcProgram {
 
     calculate(treeNode){
         let me = this;
-        if (treeNode.sourceType === this.project.Ration.getSourceType()) {
-            treeNode.data.gljList = this.project.ration_glj.getGljArrByRation(treeNode.data.ID);
-        }
-        else if (treeNode.sourceType === this.project.Bills.getSourceType()) {
-             let rations = this.project.Ration.getBillsSortRation(treeNode.source.getID());
-            treeNode.data.gljList = this.project.ration_glj.getGatherGljArrByRations(rations);
-        };
 
-        this.calc.calculate(treeNode);
+        me.calc.calculate(treeNode);
+
+        // 还原,防止出现混乱影响下次计算
+        delete treeNode.data.baseTotalPrice;
+        delete treeNode.data.gatherType;
 
         // 存储、刷新本结点、所有父结点
         if (treeNode.changed) {
             me.saveAndCalcParents(treeNode);
             delete treeNode.changed;
         };
-
     };
 
     saveAndCalcParents(treeNode) {
@@ -174,125 +173,6 @@ class CalcProgram {
         projectObj.mainController.refreshTreeNode([treeNode]);
     };
 
-    initFees(treeNode){
-        if (!treeNode.data.fees) {
-            treeNode.data.fees = [];
-            treeNode.data.feesIndex = {};
-            treeNode.changed = true;
-        };
-    };
-
-    checkFee(treeNode, ftObj){
-        if (!treeNode.data.feesIndex[ftObj.fieldName]){
-            let fee = {
-                'fieldName': ftObj.fieldName,
-                'unitFee': ftObj.unitFee,
-                'totalFee': ftObj.totalFee,
-                'tenderUnitFee': 0,
-                'tenderTotalFee': 0
-            };
-            treeNode.data.fees.push(fee);
-            treeNode.data.feesIndex[ftObj.fieldName] = fee;
-            treeNode.changed = true;
-        }
-        else{
-            if (treeNode.data.feesIndex[ftObj.fieldName].unitFee != ftObj.unitFee){
-                treeNode.data.feesIndex[ftObj.fieldName].unitFee = ftObj.unitFee;
-                treeNode.changed = true;
-            };
-
-            if (treeNode.data.feesIndex[ftObj.fieldName].totalFee != ftObj.totalFee){
-                treeNode.data.feesIndex[ftObj.fieldName].totalFee = ftObj.totalFee;
-                treeNode.changed = true;
-            };
-        };
-    };
-
-    gatherFeeTypes(treeNode, gatherType){
-        let me = this;
-        let rst = [];
-
-        if (treeNode.sourceType === this.project.Bills.getSourceType()) {
-            me.initFees(treeNode);
-
-            let objsArr = [];
-            if (gatherType == CP_GatherType.rations){
-                objsArr = this.project.Ration.getRationsByNode(treeNode);
-            }else if (gatherType == CP_GatherType.bills){
-                objsArr = treeNode.children;
-            };
-
-            for (let ft of feeType) {
-                let ftObj = {};
-                ftObj.fieldName = ft.type;
-                ftObj.name = ft.name;
-                let uf = 0, tf = 0, tuf = 0, ttf = 0;
-                for (let item of objsArr) {
-                    let data = {};
-                    if (gatherType == CP_GatherType.rations){
-                        data = item;
-                    }else if (gatherType == CP_GatherType.bills){
-                        data = item.data;
-                    };
-                    if (data.feesIndex && data.feesIndex[ft.type]) {
-                        uf = (uf + parseFloat(data.feesIndex[ft.type].unitFee)).toDecimal(me.digitDefault);
-                        tf = (tf + parseFloat(data.feesIndex[ft.type].totalFee)).toDecimal(me.digitDefault);
-                        tuf = (tuf + parseFloat(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(me.digitDefault);
-                        ttf = (ttf + parseFloat(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(me.digitDefault);
-                    };
-                };
-                ftObj.unitFee = uf.toDecimal(me.digit);
-                ftObj.totalFee = tf.toDecimal(me.digit);
-                ftObj.tenderUnitFee = tuf.toDecimal(me.digit);
-                ftObj.tenderTotalFee = ttf.toDecimal(me.digit);
-
-                me.checkFee(treeNode, ftObj);
-
-                rst.push(ftObj);
-            };
-
-            if (treeNode.changed) {
-                me.saveAndCalcParents(treeNode);
-                delete treeNode.changed;
-            };
-        };
-
-        return rst;
-    };
-
-    calcDefaultBillTemp(treeNode, totalPrice){
-        let me = this;
-        let rst = [];
-        if (treeNode.sourceType != this.project.Bills.getSourceType()){return rst};
-        me.initFees(treeNode);
-        for (let item of defaultBillTemplate) {
-            let num = totalPrice;
-            item.dispExprUser = item.dispExpr;
-            item.displayFieldName = me.calc.compiledFeeTypes[item.fieldName];
-
-            if (item.feeRate)
-                item.unitFee = (totalPrice * item.feeRate * 0.01).toDecimal(me.digit)
-            else
-                item.unitFee = 0;
-
-            let quantity = treeNode.data.quantity;
-            if (!quantity) quantity = 0;
-            item.totalFee = (item.unitFee * quantity).toDecimal(me.digit);
-            item.tenderUnitFee = 0;
-            item.tenderTotalFee = 0;
-
-            me.checkFee(treeNode, item);
-        };
-
-        if (treeNode.changed) {
-            me.saveAndCalcParents(treeNode);
-            delete treeNode.changed;
-        };
-
-        rst = defaultBillTemplate;
-        return rst;
-    };
-
     getCalcDatas(treeNode){
         let me = this;
         let rst = [];
@@ -301,9 +181,8 @@ class CalcProgram {
         let isLeafBill = isBill && treeNode.source.children && treeNode.source.children.length === 0;
         let isBillPriceCalc = me.project.projSetting.billsCalcMode === billsPrice;
 
-        if (isRation) {                 // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。
-            me.calculate(treeNode);
-            rst = treeNode.data.calcTemplate.calcItems;
+        if (isRation) {
+            //
         }
         else if (isLeafBill) {
             let ct = '';
@@ -320,26 +199,28 @@ class CalcProgram {
             };
 
             if (ct == childrenType.ration){
-                if (isBillPriceCalc){   // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算
-                    me.calculate(treeNode);
-                    rst = treeNode.data.calcTemplate.calcItems;
-                }else{                  // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
-                    rst = me.gatherFeeTypes(treeNode, CP_GatherType.rations);
+                if (isBillPriceCalc){                   // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算
+
+                }
+                else{                                   // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
+                    treeNode.data.gatherType = CP_GatherType.rations;
                 };
             }
             else if (ct == childrenType.volumePrice){
                 let totalPrice = 10000;
-                rst = me.calcDefaultBillTemp(treeNode, totalPrice);
+                treeNode.data.baseTotalPrice = totalPrice;
             }
             else if (ct == childrenType.formula){
                 let totalPrice = 20000;
-                rst = me.calcDefaultBillTemp(treeNode, totalPrice);
+                treeNode.data.baseTotalPrice = totalPrice;
             };
         }
-        else if (isBill){    // 父清单:汇总子清单的费用类别
-            rst = me.gatherFeeTypes(treeNode, CP_GatherType.bills);
+        else if (isBill){                                   // 父清单:汇总子清单的费用类别
+            treeNode.data.gatherType = CP_GatherType.bills;
         };
 
+        me.calculate(treeNode);
+        rst = treeNode.data.calcTemplate.calcItems;
         return rst;
     }
 }

+ 1 - 1
web/building_saas/main/js/views/calc_program_manage.js

@@ -52,7 +52,6 @@ let rationPM = {
         };
         me.mainSpread = sheetCommonObj.buildSheet($('#mainSpread')[0], me.mainSetting, me.datas.length);
         me.detailSpread = sheetCommonObj.buildSheet($('#detailSpread')[0], me.detailSetting, me.datas[0].calcItems.length);
-
         var fieldName = new GC.Spread.Sheets.CellTypes.ComboBox();
         fieldName.items(projectObj.project.calcProgram.calc.compiledFeeTypeNames);
         me.detailSpread.getSheet(0).getRange(-1, 4, -1, 1).cellType(fieldName);
@@ -75,6 +74,7 @@ let rationPM = {
         me.detailSpread.suspendPaint();
         var dSheet = me.detailSpread.getSheet(0);
         var dData = me.datas[row].calcItems;
+        dSheet.setRowCount(dData.length, GC.Spread.Sheets.SheetArea.viewport);
         sheetCommonObj.showData(dSheet, me.detailSetting, dData);
         me.detailSpread.resumePaint();
     },

+ 0 - 16
web/building_saas/main/js/views/calc_program_view.js

@@ -229,22 +229,6 @@ let calcProgramObj = {
         var me = this;
         me.treeNode = treeNode;
         me.datas = projectObj.project.calcProgram.getCalcDatas(treeNode);
-
-        function checkSerialNo() {     // 检测序号列。隐藏列的方式焦点难控制,体验不佳,这里动态添加删除。
-            let srlCol = {headerName: "序号", headerWidth: CP_Col_Width.serialNo, dataCode: "serialNo", dataType: "String", hAlign: "center"};
-            if (me.datas.length > 0 && me.datas[0].serialNo){
-                if (me.setting.header[0].dataCode != "serialNo"){
-                    me.setting.header.splice(0, 0, srlCol);
-                };
-            }
-            else {
-                if (me.setting.header[0].dataCode == "serialNo"){
-                    me.setting.header.splice(0, 1);
-                };
-            }
-        };
-
-        checkSerialNo();
         sheetCommonObj.initSheet(me.sheet, me.setting, me.datas.length);
         sheetCommonObj.showData(me.sheet, me.setting, me.datas);
 

+ 2 - 44
web/building_saas/pm/html/project-management.html

@@ -40,53 +40,11 @@
         </div>
     </div>
     <%include ../../../common/html/header.html %>
-    <nav class="navbar navbar-expand-lg justify-content-between navbar-light p-0">
-        <ul class="nav navbar-nav px-1">
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="http://example.com" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">文件</a>
-                <div class="dropdown-menu" aria-labelledby="supportedContentDropdown">
-                    <a class="dropdown-item" href="#">Action</a>
-                    <a class="dropdown-item" href="#">Another action</a>
-                    <a class="dropdown-item" href="#">Something else here</a>
-                </div>
-            </li>
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">编辑</a>
-                <div class="dropdown-menu">
-                    <a class="dropdown-item" href="#">Action</a>
-                    <a class="dropdown-item" href="#">Another action</a>
-                    <a class="dropdown-item" href="#">Something else here</a>
-                </div>
-            </li>
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">工具</a>
-                <div class="dropdown-menu">
-                    <a class="dropdown-item" href="#">定额库编辑器</a>
-                    <a class="dropdown-item" href="/complementaryGlj">工料机库编辑器</a>
-                </div>
-            </li>
-            <li class="nav-item dropdown">
-                <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-question-circle-o"></i> 帮助</a>
-                <div class="dropdown-menu">
-                    <a class="dropdown-item" href="#">帮助</a>
-                    <a class="dropdown-item" href="#">升级说明</a>
-                    <a class="dropdown-item" href="#">重庆市2008定额说明</a>
-                    <a class="dropdown-item" href="#">纵横官网</a>
-                    <a class="dropdown-item" href="#">动画教程</a>
-                    <a class="dropdown-item" href="#">联系客服</a>
-                    <a class="dropdown-item" href="#">关于</a>
-                </div>
-            </li>
-        </ul>
-        <form class="form-inline">
-            <input class="form-control form-control-sm mr-1" type="text" placeholder="告诉我你想做什么">
-        </form>
-    </nav>
 </div>
     <div class="main">
         <div class="poj-manage container-fluid">
             <div class="row">
-                <div class="col-lg-2">
+                <div class="col-auto">
                     <div class="poj-cate">
                         <input type="text" class="my-2 form-control form-control-sm" placeholder="搜索所有工程">
                         <ul class="nav nav-pills flex-column">
@@ -111,7 +69,7 @@
                         </ul>
                     </div>
                 </div>
-                <div class="col-lg-10">
+                <div class="col">
                     <div class="tab-content">
                         <div class="tab-pane active" id="pm_all" role="tabpanel">
                         <div class="toolsbar">

+ 29 - 2
web/common/html/header.html

@@ -1,11 +1,38 @@
-<nav class="navbar navbar-expand-lg navbar-light bg-light p-0 justify-content-between">
+<nav class="navbar navbar-expand-lg p-0 d-flex">
     <span class="header-logo px-2">Smartcost</span>
     <div class="navbar-text navbar-crumb p-0" id="fullpath">
         <% if (action !== 'index' || controller !== 'pm') {%>
         <span class="text-truncate"><a href="/pm">项目管理</a></span>
         <% } %>
     </div>
-    <div class="float-lg-right navbar-text p-0">
+    <ul class="nav navbar-nav px-1">
+        <li class="nav-item">
+            <a class="nav-link" href="#" aria-expanded="false" data-toggle="modal" data-target="#poj-set"><i class="fa fa-cube"></i> 项目属性</a>
+        </li>
+        <li class="nav-item">
+            <a class="nav-link" href="#" aria-expanded="false"><i class="fa fa-sliders"></i> 选项</a>
+        </li>
+        <li class="nav-item dropdown">
+            <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-wrench"></i> 工具</a>
+            <div class="dropdown-menu">
+                <a class="dropdown-item" href="#">定额库编辑器</a>
+                <a class="dropdown-item" href="/complementaryGlj">工料机库编辑器</a>
+            </div>
+        </li>
+        <li class="nav-item dropdown">
+            <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-question-circle-o"></i> 帮助</a>
+            <div class="dropdown-menu">
+                <a class="dropdown-item" href="#">帮助</a>
+                <a class="dropdown-item" href="#">升级说明</a>
+                <a class="dropdown-item" href="#">重庆市2008定额说明</a>
+                <a class="dropdown-item" href="#">纵横官网</a>
+                <a class="dropdown-item" href="#">动画教程</a>
+                <a class="dropdown-item" href="#">联系客服</a>
+                <a class="dropdown-item" href="#">关于</a>
+            </div>
+        </li>
+    </ul>
+    <div class="ml-auto navbar-text p-0">
         <div class="dropdown d-inline-block navbar-nav">
             <button class="btn btn-link btn-sm dropdown-toggle" type="button" data-toggle="dropdown"><%= sessionUser.email %></button>
             <div class="dropdown-menu dropdown-menu-right">