Przeglądaj źródła

Merge branch 'master' of http://192.168.1.12:3000/SmartCost/ConstructionCost

TonyKang 7 lat temu
rodzic
commit
abc4d22147

+ 204 - 197
test/calculation/test_analyzer.js

@@ -2,203 +2,204 @@
  * Created by CSL on 2017-09-01.
  */
 var test = require('tape');
-import analyzer from '../../public/calc_util';
+import analyzer from '../../web/building_saas/main/js/models/calc_program';
 
-test('解析测试', function(t){
-    let calcTemplate = {
-        ID: 1,
-        name: "建筑工程",
-        calcItems: [
-            {
-                ID: "101",
-                code: "1",
-                name: "基价直接工程费",
-                fieldName: "baseDirect",
-                dispExpr: "F2+F5+F6+F10",
-                expression: "@('2') + @('5') + @('6') + @('10')",
-                compiledExpr: "",
-                statement: "基价人工费+基价材料费+基价机械费+未计价材料费"
-            },
-            {
-                ID: "102",
-                code: "1.1",
-                name: "基价人工费",
-                fieldName: "baseLabour",
-                dispExpr: "F3+F4",
-                expression: "@('3') + @('4')",
-                compiledExpr: "",
-                statement: "定额基价人工费+定额人工单价(基价)调整"
-            },
-            {
-                ID: "103",
-                code: "1.1.1",
-                name: "定额基价人工费",
-                fieldName: "rationBaseLabour",
-                dispExpr: "[定额基价人工费]",
-                expression: "base('定额基价人工费').toFixed(2)",
-                compiledExpr: "",
-                statement: "定额基价人工费"
-            },
-            {
-                ID: "104",
-                code: "1.1.2",
-                name: "定额人工单价(基价)调整",
-                fieldName: "rationLabourFixed",
-                dispExpr: "F3*(L-1)",
-                expression: "@('3') * (L-1)",
-                labourCoeID: 22,
-                compiledExpr: "",
-                statement: "定额基价人工费*[定额人工单价(基价)调整系数-1]",
-                memo: "渝建发(2013)51"
-            },
-            {
-                ID: "105",
-                code: "1.2",
-                name: "基价材料费",
-                fieldName: "baseMaterial",
-                dispExpr: "[定额基价材料费]",
-                expression: "base('定额基价材料费')",
-                compiledExpr: "",
-                statement: "定额基价材料费"
-            },
-            {
-                ID: "106",
-                code: "1.3",
-                name: "基价机械费",
-                fieldName: "baseMachine",
-                dispExpr: "F7+F9",
-                expression: "@('7') + @('9')",
-                compiledExpr: "",
-                statement: "定额基价机械费+定额机上人工单价(基价)调整"
-            },
-            {
-                ID: "107",
-                code: "1.3.1",
-                name: "定额基价机械费",
-                fieldName: "rationBaseMachine",
-                dispExpr: "[定额基价机械费]",
-                expression: "base('定额基价机械费')",
-                compiledExpr: "",
-                statement: "定额基价机械费"
-            },
-            {
-                ID: "108",
-                code: "1.3.1.1",
-                name: "其中:定额基价机上人工费",
-                fieldName: "rationBaseMachineLabour",
-                dispExpr: "[定额基价机上人工费]",
-                expression: "base('定额基价机上人工费')",
-                compiledExpr: "",
-                statement: "定额基价机上人工费"
-            },
-            {
-                ID: "109",
-                code: "1.3.2",
-                name: "定额机上人工单价(基价)调整",
-                fieldName: "rationBaseMachineLabourFixed",
-                dispExpr: "F8*(L-1)",
-                expression: "@('8') * (L-1)",
-                labourCoeID: 24,
-                compiledExpr: "",
-                statement: "定额基价机上人工费*[定额机上人工单价(基价)调整系数-1]"
-            },
-            {
-                ID: "110",
-                code: "1.4",
-                name: "未计价材料费",
-                fieldName: "unPriceMaterial",
-                dispExpr: "[主材费]+[设备费]",
-                expression: "base('主材费') + base('设备费')",
-                compiledExpr: "",
-                statement: "主材费+设备费"
-            },
-            {
-                ID: "111",
-                code: "2",
-                name: "企业管理费",
-                fieldName: "manageFee",
-                dispExpr: "F3+F5+F7",
-                feeRateID: 101,
-                expression: "@('3') + @('5') + @('7')",
-                compiledExpr: "",
-                statement: "定额基价人工费",
-                memo: "渝建发[2014]27号"
-            },
-            {
-                ID: "112",
-                code: "3",
-                name: "利润",
-                fieldName: "profit",
-                dispExpr: "F3+F5+F7",
-                feeRateID: 301,
-                expression: "@('3') + @('5') + @('7')",
-                compiledExpr: "",
-                statement: "定额基价人工费"
-            },
-            {
-                ID: "113",
-                code: "4",
-                name: "风险因素",
-                fieldName: "risk",
-                dispExpr: "F3+F5+F7",
-                feeRateID: 701,
-                expression: "@('3') + @('5') + @('7')",
-                compiledExpr: "",
-                statement: "定额基价人工费",
-                memo: "同定额包干费"
-            },
-            {
-                ID: "114",
-                code: "5",
-                name: "人材机价差",
-                fieldName: "lmmDiff",
-                dispExpr: "F15+F16+F17",
-                expression: "@('15') + @('16') + @('17')",
-                compiledExpr: "",
-                statement: "人工费价差+材料费价差+机械费价差"
-            },
-            {
-                ID: "115",
-                code: "5.1",
-                name: "人工费价差",
-                fieldName: "labourDiff",
-                dispExpr: "[人工费价差]",
-                expression: "base('市场价格人工费') - base('定额基价人工费(调整后)')",
-                compiledExpr: "",
-                statement: "市场价格人工费-调整后的定额人工费(基价)"
-            },
-            {
-                ID: "116",
-                code: "5.2",
-                name: "材料费价差",
-                fieldName: "materialDiff",
-                dispExpr: "[材料费价差]",
-                expression: "base('市场价格材料费') - base('定额基价材料费(调整后)')",
-                compiledExpr: "",
-                statement: "市场价格材料费-定额基价材料费"
-            },
-            {
-                ID: "117",
-                code: "5.3",
-                name: "机械费价差",
-                fieldName: "machineDiff",
-                dispExpr: "[机械费价差]",
-                expression: "base('市场价格机械费') - base('定额基价机械费(调整后)')",
-                compiledExpr: "",
-                statement: "市场价格机械费-调整后的定额基价机械费(基价)"
-            },
-            {
-                ID: "118",
-                code: "6",
-                name: "综合单价",
-                fieldName: "common",
-                dispExpr: "F1+F11+F12+F13+F14",
-                expression: "@('1') + @('11') + @('12') + @('13') + @('14')",
-                compiledExpr: "",
-                statement: "基价直接工程费+企业管理费+利润+风险因素+人材机价差"
-            }
-        ]
-    };
+let calcTemplate = {
+    ID: 1,
+    name: "建筑工程",
+    calcItems: [
+        {
+            ID: "101",
+            code: "1",
+            name: "基价直接工程费",
+            fieldName: "baseDirect",
+            dispExpr: "F2+F5+F6+F10",
+            expression: "@('2') + @('5') + @('6') + @('10')",
+            compiledExpr: "",
+            statement: "基价人工费+基价材料费+基价机械费+未计价材料费"
+        },
+        {
+            ID: "102",
+            code: "1.1",
+            name: "基价人工费",
+            fieldName: "baseLabour",
+            dispExpr: "F3+F4",
+            expression: "@('3') + @('4')",
+            compiledExpr: "",
+            statement: "定额基价人工费+定额人工单价(基价)调整"
+        },
+        {
+            ID: "103",
+            code: "1.1.1",
+            name: "定额基价人工费",
+            fieldName: "rationBaseLabour",
+            dispExpr: "[定额基价人工费]",
+            expression: "base('定额基价人工费').toFixed(2)",
+            compiledExpr: "",
+            statement: "定额基价人工费"
+        },
+        {
+            ID: "104",
+            code: "1.1.2",
+            name: "定额人工单价(基价)调整",
+            fieldName: "rationLabourFixed",
+            dispExpr: "F3*(L-1)",
+            expression: "@('3') * (L-1)",
+            labourCoeID: 22,
+            compiledExpr: "",
+            statement: "定额基价人工费*[定额人工单价(基价)调整系数-1]",
+            memo: "渝建发(2013)51"
+        },
+        {
+            ID: "105",
+            code: "1.2",
+            name: "基价材料费",
+            fieldName: "baseMaterial",
+            dispExpr: "[定额基价材料费]",
+            expression: "base('定额基价材料费')",
+            compiledExpr: "",
+            statement: "定额基价材料费"
+        },
+        {
+            ID: "106",
+            code: "1.3",
+            name: "基价机械费",
+            fieldName: "baseMachine",
+            dispExpr: "F7+F9",
+            expression: "@('7') + @('9')",
+            compiledExpr: "",
+            statement: "定额基价机械费+定额机上人工单价(基价)调整"
+        },
+        {
+            ID: "107",
+            code: "1.3.1",
+            name: "定额基价机械费",
+            fieldName: "rationBaseMachine",
+            dispExpr: "[定额基价机械费]",
+            expression: "base('定额基价机械费')",
+            compiledExpr: "",
+            statement: "定额基价机械费"
+        },
+        {
+            ID: "108",
+            code: "1.3.1.1",
+            name: "其中:定额基价机上人工费",
+            fieldName: "rationBaseMachineLabour",
+            dispExpr: "[定额基价机上人工费]",
+            expression: "base('定额基价机上人工费')",
+            compiledExpr: "",
+            statement: "定额基价机上人工费"
+        },
+        {
+            ID: "109",
+            code: "1.3.2",
+            name: "定额机上人工单价(基价)调整",
+            fieldName: "rationBaseMachineLabourFixed",
+            dispExpr: "F8*(L-1)",
+            expression: "@('8') * (L-1)",
+            labourCoeID: 24,
+            compiledExpr: "",
+            statement: "定额基价机上人工费*[定额机上人工单价(基价)调整系数-1]"
+        },
+        {
+            ID: "110",
+            code: "1.4",
+            name: "未计价材料费",
+            fieldName: "unPriceMaterial",
+            dispExpr: "[主材费]+[设备费]",
+            expression: "base('主材费') + base('设备费')",
+            compiledExpr: "",
+            statement: "主材费+设备费"
+        },
+        {
+            ID: "111",
+            code: "2",
+            name: "企业管理费",
+            fieldName: "manageFee",
+            dispExpr: "F3+F5+F7",
+            feeRateID: 101,
+            expression: "@('3') + @('5') + @('7')",
+            compiledExpr: "",
+            statement: "定额基价人工费",
+            memo: "渝建发[2014]27号"
+        },
+        {
+            ID: "112",
+            code: "3",
+            name: "利润",
+            fieldName: "profit",
+            dispExpr: "F3+F5+F7",
+            feeRateID: 301,
+            expression: "@('3') + @('5') + @('7')",
+            compiledExpr: "",
+            statement: "定额基价人工费"
+        },
+        {
+            ID: "113",
+            code: "4",
+            name: "风险因素",
+            fieldName: "risk",
+            dispExpr: "F3+F5+F7",
+            feeRateID: 701,
+            expression: "@('3') + @('5') + @('7')",
+            compiledExpr: "",
+            statement: "定额基价人工费",
+            memo: "同定额包干费"
+        },
+        {
+            ID: "114",
+            code: "5",
+            name: "人材机价差",
+            fieldName: "lmmDiff",
+            dispExpr: "F15+F16+F17",
+            expression: "@('15') + @('16') + @('17')",
+            compiledExpr: "",
+            statement: "人工费价差+材料费价差+机械费价差"
+        },
+        {
+            ID: "115",
+            code: "5.1",
+            name: "人工费价差",
+            fieldName: "labourDiff",
+            dispExpr: "[人工费价差]",
+            expression: "base('市场价格人工费') - base('定额基价人工费(调整后)')",
+            compiledExpr: "",
+            statement: "市场价格人工费-调整后的定额人工费(基价)"
+        },
+        {
+            ID: "116",
+            code: "5.2",
+            name: "材料费价差",
+            fieldName: "materialDiff",
+            dispExpr: "[材料费价差]",
+            expression: "base('市场价格材料费') - base('定额基价材料费(调整后)')",
+            compiledExpr: "",
+            statement: "市场价格材料费-定额基价材料费"
+        },
+        {
+            ID: "117",
+            code: "5.3",
+            name: "机械费价差",
+            fieldName: "machineDiff",
+            dispExpr: "[机械费价差]",
+            expression: "base('市场价格机械费') - base('定额基价机械费(调整后)')",
+            compiledExpr: "",
+            statement: "市场价格机械费-调整后的定额基价机械费(基价)"
+        },
+        {
+            ID: "118",
+            code: "6",
+            name: "综合单价",
+            fieldName: "common",
+            dispExpr: "F1+F11+F12+F13+F14",
+            expression: "@('1') + @('11') + @('12') + @('13') + @('14')",
+            compiledExpr: "",
+            statement: "基价直接工程费+企业管理费+利润+风险因素+人材机价差"
+        }
+    ]
+};
+
+/*test('解析测试', function(t){
     let calcItem = {dispExpr: "12 +[人工费]*1.2+f13+ (F6+ f10) +F16+[人工费] + f6+[材料费]"};
     let target = "12+base('人工费')*1.2+@('113')+(@('106')+@('110'))+@('116')+base('人工费')+@('106')+base('材料费')";
     let rst = analyzer.analyzeUserExpr(calcTemplate, calcItem);
@@ -207,4 +208,10 @@ test('解析测试', function(t){
     console.log(calcItem.expression);
     t.equal(calcItem.expression, target);
     t.end();
-});
+});*/
+
+let expr = "F2+F5+F6+F10";
+let arr = analyzer.getFArr(expr);
+console.log(JSON.stringify(arr));
+let id = analyzer.getFID('F10', calcTemplate);
+console.log(JSON.stringify(id));

+ 10 - 8
web/building_saas/js/global.js

@@ -1,16 +1,18 @@
 /*全局自适应高度*/
 function autoFlashHeight(){
-    var headerHeight = $(".header").height();
-    var toolsbarHeight = $(".toolsbar").height();
-    var ftoolsbarHeight = $(".toolsbar-f").height();
+    let headerHeight = $(".header").height();
+    let toolsbarHeight = $(".toolsbar").height();
+    let ftoolsbarHeight = $(".toolsbar-f").height();
    // var feeRateToolsbarHeight = $(".toolsbar_feeRate").height();
-    var bottomContentHeight = $(".bottom-content").height();
-    var toolsBarHeightQ = $(".tools-bar-height-q").height();
-    var toolsBarHeightD = $(".tools-bar-height-d").height();
+    let mainBottomContentHeight = $("#main .bottom-content").height();
+    let gljBottomContentHeight = $("#project-glj-main .bottom-content").height();
+    let toolsBarHeightQ = $(".tools-bar-height-q").height();
+    let toolsBarHeightD = $(".tools-bar-height-d").height();
     $(".main-data-side-q").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightQ-302);
     $(".main-data-side-d").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightD-302);
-    $(".main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
-    $("#project_glj_sheet").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
+    //$("#main .main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
+    $("#billsSpread").height($(window).height()-headerHeight-toolsbarHeight-mainBottomContentHeight-1);
+    $("#project_glj_sheet").height($(window).height()-headerHeight-toolsbarHeight-gljBottomContentHeight-25);
     $(".main-data-full").height($(window).height()-headerHeight-toolsbarHeight-1);
     $(".main-data-full-fl").height($(window).height()-headerHeight-toolsbarHeight-37);
     $(".main-data-full-feeRate").height($(window).height()-headerHeight-78);

+ 1 - 1
web/building_saas/main/html/main.html

@@ -1175,7 +1175,7 @@
         <!-- endinject -->
 
         <script type="text/javascript">
-            //autoFlashHeight();
+           // autoFlashHeight();
         </script>
 
         <SCRIPT type="text/javascript">

+ 17 - 7
web/building_saas/main/js/main.js

@@ -21,7 +21,12 @@ $(function () {
         $(e.relatedTarget.hash).removeClass('active');
         $("#subItems").addClass('active');
         $(gljOprObj.activeTab).addClass('active');
-        // do something
+        autoFlashHeight();
+        projectObj.refreshMainSpread();
+        /*loadSize("main", function() {
+            projectObj.refreshMainSpread();
+            refreshSubSpread();
+        });*/
     });
 
     slideResize($("#main"), function() {
@@ -115,16 +120,21 @@ function loadSize(tag, callback) {
     if (tag === '') {
         return;
     }
+    let o_topHeight = $("#"+ tag +" .main-data-top").height();
+    let o_bottomHeight = $("#"+ tag +" .main-data-bottom").height();
     let topHeight = getLocalCache('topHeight:' + tag);
     let bottomHeight = getLocalCache('bottomHeight:' + tag);
     if (topHeight === null || bottomHeight === null) {
-        return;
+        $("#"+ tag +" .main-data-top").height(o_topHeight);
+        $("#"+ tag +" .main-data-bottom").height(o_bottomHeight);
+    }else {
+        const navHeight = $("#"+ tag +" .bottom-content").children('ul.nav').height() + 4;
+        topHeight = parseFloat(topHeight);
+        bottomHeight = parseFloat(bottomHeight);
+        $("#"+ tag +" .main-data-top").height(topHeight);
+        $("#"+ tag +" .main-data-bottom").height(bottomHeight - navHeight);
     }
-    const navHeight = $("#"+ tag +" .bottom-content").children('ul.nav').height() + 4;
-    topHeight = parseFloat(topHeight);
-    bottomHeight = parseFloat(bottomHeight);
-    $("#"+ tag +" .main-data-top").height(topHeight);
-    $("#"+ tag +" .main-data-bottom").height(bottomHeight - navHeight);
+
     // $("#"+ tag +" .bottom-content").height(bottomHeight);
     callback();
 }

+ 107 - 45
web/building_saas/main/js/models/calc_program.js

@@ -13,7 +13,6 @@ let defaultBillTemplate = {
             code: "1",
             name: "定额直接费",
             dispExpr: "F2+F3+F4",
-            expression: "@('2')+@('3')+@('4')",
             statement: "人工费+材料费+机械费",
             feeRate: null,
             memo: ''
@@ -23,7 +22,6 @@ let defaultBillTemplate = {
             code: "1.1",
             name: "人工费",
             dispExpr: "HJ",
-            expression: "HJ",
             statement: "合计",
             feeRate: 50,
             fieldName: 'labour',
@@ -34,7 +32,6 @@ let defaultBillTemplate = {
             code: "1.2",
             name: "材料费",
             dispExpr: "HJ",
-            expression: "HJ",
             statement: "合计",
             feeRate: 30,
             fieldName: 'material',
@@ -45,7 +42,6 @@ let defaultBillTemplate = {
             code: "1.3",
             name: "机械费",
             dispExpr: "HJ",
-            expression: "HJ",
             statement: "合计",
             feeRate: 20,
             fieldName: 'machine',
@@ -56,7 +52,6 @@ let defaultBillTemplate = {
             code: "2",
             name: "企业管理费",
             dispExpr: "F1",
-            expression: "@('1')",
             statement: "定额直接费",
             feeRate: null,
             fieldName: 'manage',
@@ -67,7 +62,6 @@ let defaultBillTemplate = {
             code: "3",
             name: "利润",
             dispExpr: "F1",
-            expression: "@('1')",
             statement: "定额直接费",
             feeRate: null,
             fieldName: 'profit',
@@ -78,7 +72,6 @@ let defaultBillTemplate = {
             code: "4",
             name: "风险费用",
             dispExpr: "F1",
-            expression: "@('1')",
             statement: "定额直接费",
             feeRate: null,
             fieldName: 'risk',
@@ -89,7 +82,6 @@ let defaultBillTemplate = {
             code: "5",
             name: "综合单价",
             dispExpr: "F1+F5+F6+F7",
-            expression: "@('1')+@('5')+@('6')+@('7')",
             statement: "定额直接费+企业管理费+利润+风险费用",
             feeRate: null,
             fieldName: 'common',
@@ -702,14 +694,13 @@ const rationCalcBases = {
 };
 
 let analyzer = {
-    calcTemplate: null,
-
     standard: function(expr){
         let str = expr;
         str = str.replace(/\s/g, "");               // 去空格、去中文空格
         str = str.replace(/(/g, "(");              // 中文括号"("换成英文括号"("
         str = str.replace(/)/g, ")");              // 中文括号")"换成英文括号")"
         str = str.replace(/f/g, "F");               // f换成F
+        str = str.replace(/l/g, "L");               // l换成L
         return str;
     },
     getFArr: function (expr) {
@@ -722,40 +713,44 @@ let analyzer = {
         let arr = expr.match(patt);
         return arr ? arr : [];
     },
-    getFID: function (FName) {          // F3、F22
-        let me = this;
+    getBaseArr: function (expr) {
+        let pattBase = new RegExp(/\[[\u4E00-\u9FA5]+\]/gi);
+        let arrBase = expr.match(pattBase);
+        return arrBase ? arrBase : [];
+    },
+
+    getFID: function (FName, calcTemplate) {          // F3、F22 → 4、99
         let idx = FName.slice(1) - 1;
-        let id = me.calcTemplate.calcItems[idx] ? me.calcTemplate.calcItems[idx].ID : null;
+        let id = calcTemplate.calcItems[idx] ? calcTemplate.calcItems[idx].ID : null;
         return id;
     },
-    getFItem: function (FName){
-        let me = this;
+    getFItem: function (FName, calcTemplate){      // F3 → calcItems[2] → {Object}
         let idx = FName.slice(1) - 1;
-        return me.calcTemplate.calcItems[idx];
+        return calcTemplate.calcItems[idx];
     },
-    isCycleCalc: function (expr) {     // @5+@6  这里已经是ID引用
-        let me = this;
+    isCycleCalc: function (expression, calcTemplate) {     // 这里判断expression,是ID引用: @5+@6
+        let me = analyzer;
         
-        function isCycle(nodeExpr) {
+        function isCycle(nodeExpr, template) {
             let atIDArr = me.getAtIDArr(nodeExpr);
             for (let atID of atIDArr){
                 let ID = atID.slice(1);
-                let item = me.calcTemplate.compiledCalcItems[ID];
+                let item = template.compiledCalcItems[ID];
                 if (item.expression.includes(atID)) {
                     return true;
                 }
                 else {
-                    isCycle(item.expression);
+                    isCycle(item.expression, template);
                 }
             };
             return false;
         };
 
-        return isCycle(expr);
+        return isCycle(expression, calcTemplate);
     },
-    isLegal: function (expr) {   // 调用前必须先标准化
-        let me = this;
-
+    isLegal: function (dispExpr, calcTemplate) {  // 检测包括:无效字符、基数是否中括号、基数是否定义、行引用、循环计算
+        let me = analyzer;
+        let expr = me.standard(dispExpr);
         let invalidChars = /[^0-9\u4e00-\u9fa5\+\-\*\/\(\)\.\[\]F%]/g;
         if (invalidChars.test(expr)){
             alert('表达式中含有无效的字符!');
@@ -787,38 +782,72 @@ let analyzer = {
             }
         };
 
-        // 行引用检测、行引用转ID引用
         let arrF = me.getFArr(expr);
         for (let F of arrF){
             let num = F.slice(1);
-            if (num > me.calcTemplate.calcItems.length){
+            if (num > calcTemplate.calcItems.length){
                 alert('表达式中 “F'+ num +'” 行号引用错误!');
                 return false;
             };
-            let id = me.getFID(F);
-            let fn = new RegExp(F, "g");
-            expr = expr.replace(fn, `@('${id}')`);
         };
 
-        // 循环计算
-        if (me.isCycleCalc(expr)){
+        let expression = me.getExpression(expr, calcTemplate);
+        if (me.isCycleCalc(expression, calcTemplate)){
             alert('表达式中有循环计算!');
             return false;
         }
 
         return true;
     },
-    analyzeUserExpr: function(calcTemplate, calcItem){
-        let me = this;
-        me.calcTemplate = calcTemplate;
+    analyzeUserExpr: function(calcItem, calcTemplate){
+        let me = analyzer;
         let expr = calcItem.dispExpr;
         expr = me.standard(expr);
         calcItem.dispExpr = expr;
-        if (me.isLegal(expr)){
+
+        if (me.isLegal(expr, calcTemplate)){
             calcItem.expression = expr;
             return true;
         }else
             return false;
+    },
+
+    getExpression: function (dispExpr, calcTemplate) {
+        function refLineToID(expr, template) {
+            let rst = expr;
+            let fArr = me.getFArr(rst);
+            let IDArr = [];
+            for (let F of fArr){
+                let ID = me.getFID(F, template);
+                IDArr.push(ID);
+            };
+            for (let i = 0; i < fArr.length; i++) {
+                let patt = new RegExp(fArr[i]);
+                let val = `@${IDArr[i]}`;
+                rst = rst.replace(patt, val);
+            };
+            return rst;
+        };
+
+        let me = analyzer;
+        let expr = me.standard(dispExpr);
+        return refLineToID(expr, calcTemplate);
+    },
+    getCompiledExpr: function (expression) {
+        let me = analyzer;
+        let rst = expression;
+        let atIDArr = me.getAtIDArr(rst);
+        let IDArr = atIDArr.map(function (atID) {
+            return atID.slice(1);
+        });
+        for (var i = 0; i < atIDArr.length; i++) {
+            let patt = new RegExp(atIDArr[i]);
+            let val = `$CE.at(${IDArr[i]})`;
+            rst = rst.replace(patt, val);
+        };
+        rst = rst.replace(/\[/g, "$CE.base('");
+        rst = rst.replace(/\]/g, "')");
+        return rst;
     }
 };
 
@@ -950,7 +979,7 @@ class CalcProgram {
         template.hasCompiled = false;
         template.errs = [];
 
-        let private_extract_ID = function(str, idx){
+        /*let private_extract_ID = function(str, idx){
             let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0;
             for (let i = idx; i < str.length; i++) {
                 if (str[i] === '(') {
@@ -973,8 +1002,8 @@ class CalcProgram {
                 }
             }
             return rst;
-        };
-        let private_parse_ref = function(item, itemIdx){
+        };*/
+        /*let private_parse_ref = function(item, itemIdx){
             let idx = item.expression.indexOf('@(', 0);
             while (idx >= 0) {
                 let ID = private_extract_ID(item.expression, idx);
@@ -996,6 +1025,37 @@ class CalcProgram {
             if (template.compiledSeq.indexOf(itemIdx) < 0) {
                 template.compiledSeq.push(itemIdx);
             }
+        };*/
+        let private_extract_ID = function(str, idx){
+            let subStr = str.slice(idx);
+            let patt = new RegExp(/@\d+/);
+            let atID = subStr.match(patt);
+            let ID = atID ? atID[0].slice(1) : null;
+            return ID;
+        };
+        let private_parse_ref = function(item, itemIdx){
+            let idx = item.expression.indexOf('@', 0);
+            while (idx >= 0) {
+                let ID = private_extract_ID(item.expression, idx);
+                let len = ID ? ID.toString().length : 0;
+                if (len) {
+                    let subItem = template.compiledCalcItems[ID];
+                    if (subItem) {
+                        if (subItem.ID !== item.ID) {
+                            private_parse_ref(subItem, template.compiledCalcItems[ID + "_idx"]);
+                        } else {
+                            template.errs.push("循环引用ID: " + ID);
+                        }
+                    } else {
+                        template.errs.push("找不到ID: " + ID);
+                        console.log('找不到ID: ' + ID);
+                    }
+                }
+                idx = item.expression.indexOf('@', idx + len + 1);
+            }
+            if (template.compiledSeq.indexOf(itemIdx) < 0) {
+                template.compiledSeq.push(itemIdx);
+            }
         };
         let private_compile_items = function() {
             for (let idx of template.compiledSeq) {
@@ -1003,10 +1063,8 @@ class CalcProgram {
                 item.dispExprUser = item.dispExpr;    // 用于界面显示。disExpr是公式模板,不允许修改:人工系数占位符被修改后变成数值,第二次无法正确替换。
                 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(');
-                };
+                else
+                    item.compiledExpr = analyzer.getCompiledExpr(item.expression);
 
                 if (item.labourCoeID){
                     let lc = me.compiledLabourCoes[item.labourCoeID].coe;
@@ -1035,6 +1093,7 @@ class CalcProgram {
 
             for (let i = 0; i < template.calcItems.length; i++) {
                 let item = template.calcItems[i];
+                item.expression = analyzer.getExpression(item.dispExpr, template);
                 template.compiledCalcItems[item.ID] = item;
                 template.compiledCalcItems[item.ID + "_idx"] = i;
             }
@@ -1379,7 +1438,8 @@ class CalcProgram {
     /* 计算所有树结点(分3种情况),并返回发生变动的零散的多个树结点。参数取值如下:
         calcAllType.catAll       计算所有树结点 (不指定参数时的默认值)
         calcAllType.catBills     计算所有清单 (改变项目属性中清单取费算法时会用到)
-        calcAllType.catRations   计算所有定额、工料机形式的定额、量价,因为它们都走自己的计算程序 (改变人工系数、费率值、工料机单价时会用到)
+        calcAllType.catRations   计算所有定额、工料机形式的定额、量价,因为它们都走自己的计算程序 (改变人工系数、费率值、工料机单价时会用到)  不要用
+        缺陷:calcAllType.catRations 参数情况不会计算父结点。(calcAllType.catBills 可以,因为清单的父结点也是清单会计算)
     */
     calcAllNodes(calcType = calcAllType.catAll){
         let me = this;
@@ -1514,4 +1574,6 @@ class CalcProgram {
         baseNodes.push(calcTools.getNodeByFlag(fixedFlag.CHARGE));
         return me.getTotalFee(baseNodes, excludeNodes);
     };
-};
+};
+
+// export default analyzer;

+ 3 - 3
web/building_saas/main/js/models/fee_rate.js

@@ -192,7 +192,7 @@ var FeeRate = {
                     calcProgramObj.showData(node);
                 }
             }
-            project.calcProgram.calcAllNodesAndSave(calcAllType.catBills);
+            project.calcProgram.calcAllNodesAndSave(calcAllType.catAll);
             project.markUpdateProject({projectID:project.ID(),feeRateID:this.getActivateFeeRateFileID()},"feeRate");
             socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
         };
@@ -205,7 +205,7 @@ var FeeRate = {
                     calcProgramObj.showData(node);
                 }
             }
-            project.calcProgram.calcAllNodesAndSave(calcAllType.catBills);
+            project.calcProgram.calcAllNodesAndSave(calcAllType.catAll);
             if(socketObject.roomInfo){
                 //判断费率文件ID是否改变了
                 if(socketObject.roomInfo.feeRate == this.getActivateFeeRateFileID()){//如果没变,则是重选了标准
@@ -426,7 +426,7 @@ var FeeRate = {
               //更新缓存
               let rate = me.getFeeRateByID(rateID);
               for(let dkey in doc){
-                  rate[dkey] = doc;
+                  rate[dkey] = doc[dkey];
               }
             if(callback){
                 callback();

+ 15 - 6
web/building_saas/main/js/models/installation_fee.js

@@ -179,7 +179,7 @@ var installation_fee = {
             };
             return updateData;
         };
-        installation_fee.prototype.submitInstallationUpdate = function (updateData,rationInstallations,callback) {
+       installation_fee.prototype.submitInstallationUpdate = function (updateData,rationInstallations,callback) {
             if(updateData){
                 let data = {'projectID':projectInfoObj.projectInfo.ID,'updateData':updateData};
                 if(rationInstallations){//是否附带更新定额安装费
@@ -201,7 +201,7 @@ var installation_fee = {
                 })
             }
         };
-        installation_fee.prototype.calcInstallationFee=function(callback){
+       installation_fee.prototype.calcInstallationFee=function(callback){
             let project = projectObj.project,me = this;
             let engineering = projectInfoObj.projectInfo.property.engineering;
             let installSetting = projectInfoObj.projectInfo.property.installSetting;
@@ -302,12 +302,13 @@ var installation_fee = {
                         glj.quantity = ur.quantity;
                         glj.rationItemQuantity = ur.rationItemQuantity;
                     }
-
+                    let selectedNode = projectObj.project.mainTree.selected;
                     //对树节点的操作并删除、添加清单、删除添加定额、删除对应的定额工料机缓存
                     TREE_SHEET_HELPER.massOperationSheet(projectObj.mainController.sheet, function () {
                         deleteOldNodes(deleteRationNodes,deleteBillsNodes);
                         addNewNodes(updateData);
                     });
+                    setTreeSelection(selectedNode);
                     projectObj.project.projectGLJ.loadData(function () {
                         cbTools.refreshFormulaNodes();
                         if(callback){
@@ -363,11 +364,19 @@ var installation_fee = {
                     Bill.tree.delete(bd.source);
                     Bill.removeByID(bd.getID());
                 }
-                let sels = controller.sheet.getSelections();
-                controller.setTreeSelected(controller.tree.items[sels[0].row]);
             }
 
-            
+            function setTreeSelection(oldSelect) {
+                let controller = projectObj.mainController;
+                let sel = controller.sheet.getSelections()[0];
+                if(controller.tree.getNodeByID(oldSelect.getID())){//如果旧选中节点还存在
+                    controller.sheet.setSelection(oldSelect.serialNo(),sel.col,sel.rowCount,sel.colCount);
+                    controller.setTreeSelected(oldSelect)
+                }else {//选中节点已被删除,自动选中新的节点
+                    controller.setTreeSelected(controller.tree.items[sel.row]);
+                }
+            }
+
             function checkRation(oldRation,newRation) {//检查定额是否需要更新
                 let gljs = project.ration_glj.getGljByRationID(oldRation.ID);
                 let modify = false;

+ 0 - 1
web/building_saas/main/js/models/project.js

@@ -321,7 +321,6 @@ var PROJECT = {
         project.prototype.projectMarkChecking = function () {
             let  changeMark = projectInfoObj.projectInfo.changeMark;
             if(changeMark&&changeMark!=''){
-                $.bootstrapLoading.start();
                 this.Bills.getEngineeringCostNode(projectObj.mainController).changed = true;
                 this.calcProgram.calcAllNodesAndSave();
                 CommonAjax.post("/project/removeProjectMark",{projectID:this.ID()},function (data) {

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

@@ -191,7 +191,7 @@ let calcBaseView = {
 
             let calcItem = calcProgramManage.getSelectionInfo().calcItem;
             if (calcItem.dispExprUser) {
-                me.inputExpr.val(calcItem.dispExprUser);
+                me.inputExpr.val(calcItem.dispExpr);
             }
             let bnArr = Object.keys(rationCalcBases);
             let baseArr = [];

+ 8 - 0
web/building_saas/main/js/views/calc_program_manage.js

@@ -61,6 +61,7 @@ let calcProgramManage = {
         me.mainSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onMainEnterCell);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.CellChanged, me.onDetailCellChanged);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onDetailEditEnded);
+        me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onEnterCell);
         let mSheet = me.mainSpread.getSheet(0);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
 
@@ -114,6 +115,13 @@ let calcProgramManage = {
             });
         }
     },
+    onEnterCell: function (sender, args) {
+/*        let t = calcProgramManage.getSelectionInfo().template;
+        let c = calcProgramManage.getSelectionInfo().calcItem;
+        c.expression = analyzer.getExpression(c.dispExpr, t);
+        let e = c.dispExpr + '  ' + c.expression;
+        projectObj.testDisplay('', e);*/
+    },
     saveCalcItem: function (data,callback) {//data
         let me = this;
         $.ajax({

+ 19 - 17
web/building_saas/main/js/views/fee_rate_view.js

@@ -400,11 +400,13 @@ var feeRateObject={
     },
     showMainFeeRateData:function () {
         let me = this;
+        let selected = me.mainFeeRateSheet.getSelections()[0];
         me.activateFeeRate = projectObj.project.FeeRate.getActivateFeeRate();
         me.mainFeeRateData = projectObj.project.FeeRate.getActivateFeeRate().rates;
         me.mainFeeRateSheet.setRowCount(0);
         me.mainFeeRateSheet.setRowCount(me.mainFeeRateData.length);
         me.showSelectTree(me.mainFeeRateSheet,me.mainFeeRateSetting,me.mainFeeRateData);
+        me.mainFeeRateSheet.setSelection(selected.row,selected.col,selected.rowCount,selected.colCount);
     },
     reFreshRateViews:function() {
         //feeRateObject.createSpreadView();
@@ -471,20 +473,20 @@ var feeRateObject={
         }
     },
     cascadeSetRates:function(selectedItem,sourceRow,mapID,selectMap){
-        var items=[];
+        let items=[];
         items.push({rateIndex:sourceRow,rate:selectedItem});
         _.forEach(this.mainFeeRateData,function (recode,Index) {
             if(Index!=sourceRow&&recode.subFeeRate){
-                var valueMaps = recode.subFeeRate.valueMaps;
-                var valueMap = _.find(valueMaps,{ID:mapID});
+                let valueMaps = recode.subFeeRate.valueMaps;
+                let valueMap = _.find(valueMaps,{ID:mapID});
                 if(valueMap){//选项完全一样的情况
                     if(valueMap.value==recode.rate){
                         return;
                     }else {
                         recode.rate = valueMap.value;
                         _.forEach(selectMap,function (value,key) {
-                            var tempRecode =  recode.subFeeRate.recodes[key];
-                            var optionList = tempRecode.optionList;
+                            let tempRecode =  recode.subFeeRate.recodes[key];
+                            let optionList = tempRecode.optionList;
                             _.forEach(optionList,function (o) {
                                 if(o.value==value){
                                     o.selected = true;
@@ -492,17 +494,17 @@ var feeRateObject={
                                     o.selected = false;
                                 }
                             })
-                        })
+                        });
                         items.push({rateIndex:Index,rate:recode});
                     }
                 }else {//某条选项一样的情况
-                    var needUpdate = false;
-                    var selectList = mapID.split('-');
-                    var newList=[];
+                    let needUpdate = false;
+                    let selectList = mapID.split('-');
+                    let newList=[];
                     _.forEach(recode.subFeeRate.recodes,function (r) {
-                        var oList = r.optionList;
-                        var oldSelectIndex=0;
-                        var hasChange=false;
+                        let oList = r.optionList;
+                        let oldSelectIndex=0;
+                        let hasChange=false;
                         _.forEach(oList,function (o,key) {
                             if(o.selected){
                                 oldSelectIndex = key;
@@ -515,14 +517,14 @@ var feeRateObject={
                             }else {
                                 o.selected=false;
                             }
-                        })
+                        });
                         if(!hasChange){
                             oList[oldSelectIndex].selected=true;
                             newList.push(oList[oldSelectIndex].value)
                         }
-                    })
+                    });
                     if(needUpdate){
-                      var newValue =   _.find(valueMaps,{ID:newList.join("-")})//取出费率值并更新
+                      let newValue =   _.find(valueMaps,{ID:newList.join("-")})//取出费率值并更新
                         if(newValue){
                           if(recode.rate != newValue.value){
                               recode.rate = newValue.value
@@ -532,7 +534,7 @@ var feeRateObject={
                     }
                 }
             }
-        })
+        });
         projectObj.project.FeeRate.batchUpdateFeeRate(items,feeRateObject.activateFeeRate);
     },
     loadPageContent:function(){
@@ -607,7 +609,7 @@ var feeRateObject={
                     feeRateObject.submitSaveAs(newName);
                 }
             }
-            projectObj.project.FeeRate.checkFeeRateName(newName,callback)
+            projectObj.project.FeeRate.checkFeeRateName(newName,callback);
         }else {
             feeRateObject.submitSaveAs(newName);
         }

+ 1 - 20
web/building_saas/main/js/views/glj_view.js

@@ -138,8 +138,6 @@ var gljOprObj = {
     },
     gljTreeSetting: {
         view: {
-            //addHoverDom: gljTypeTreeOprObj.addHoverDom,
-            //removeHoverDom: gljTypeTreeOprObj.removeHoverDom,
             expandSpeed: "",
             selectedMulti: false
         },
@@ -1103,23 +1101,6 @@ var gljOprObj = {
         installationFeeObj.rationInstallData = [];
         //this.detailData=[];
     },
-    /*   lockRationGLJCell:function(){
-     sheetCommonObj.lockCells(this.sheet,this.setting);
-     },
-     lockRationCoeCell:function () {
-     sheetCommonObj.lockCells(this.coeSheet,this.coeSetting);
-     /!*    if(this.coeSheetData){
-     for(var i =0;i<this.coeSheetData.length;i++){
-     if(this.coeSheetData[i].coeID==-1){
-     this.coeSheet.getCell(i, 1, GC.Spread.Sheets.SheetArea.viewport).locked(false);
-     }
-     }
-     }*!/
-
-     },
-     lockRationGLJCell:function(){
-     sheetCommonObj.lockCells(this.sheet,this.setting);
-     },*/
     updateRationGLJ: function (args) {
         var me = this;
         var updateField = me.setting.header[args.col].dataCode;
@@ -1649,7 +1630,7 @@ var gljOprObj = {
                 cellRect: cellRect,
                 sheetArea: context.sheetArea
             };
-        }
+        };
         TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
             var recode = data[hitinfo.row];
             if (recode && recode.hasOwnProperty('subList')) {

+ 5 - 6
web/building_saas/main/js/views/installation_fee_view.js

@@ -19,7 +19,7 @@ let installationFeeObj={
             {headerName: "记取位置", headerWidth: 200, dataCode: "position", hAlign: "left", dataType: "String",cellType:'selectButton',getText:'forPosition'}
         ],
         view: {
-            lockColumns: [0,1,3,4,5,6,7,8,9]
+            lockColumns: [0,1,3,4,5,6,7,8,9,10]
         },
         getText:{
             forPosition:function (item,val) {//记取位置转换
@@ -383,7 +383,7 @@ let installationFeeObj={
         sheetCommonObj.showData(this.modifyFeeRuleSheet, this.modifyFeeRuleSetting, this.modifyFeeRuleData);
         this.modifyFeeRuleSheet.setRowCount(this.modifyFeeRuleData.length);
         let positionCol = _.findIndex(this.modifyFeeRuleSetting.header,{ 'dataCode': "position"});
-        this.modifyFeeRuleSheet.getRange(-1,positionCol, -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(ration_install.feeType=='子目费用'||ration_install.unifiedSetting==1);//设置选取位置列只读
+        this.modifyFeeRuleSheet.getRange(-1,positionCol, -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(ration_install.feeType=='子目费用');//设置选取位置列只读
     },
     showRationInstallationData:function (node) {
         var installationList = [];
@@ -1110,7 +1110,6 @@ let installationFeeObj={
                 }
               me.refreshFeeDetailRow(info.row);
             }
-            //me.showFeeDetailData(feeDetail.libID,feeDetail.feeItemId);
         });
     },
     onDetailRangeChanged:function (e,info) {
@@ -1212,8 +1211,8 @@ let installationFeeObj={
                                          return
                                     }
                                     if (autoCreate == false){//不自动生成的时候才做检查
-                                        if(feeRule.billID&&feeRule.billID!=""){//先检查清单ID
-                                            let node = projectObj.project.mainTree.getNodeByID(item.billID);
+                                        if(feeRule.billID && feeRule.billID != ""){//先检查清单ID
+                                            let node = projectObj.project.mainTree.getNodeByID(feeRule.billID);
                                             if(!node){
                                                 let c = confirm("所选清单没有找到,需要自动生成吗?");
                                                 if(c){
@@ -1222,7 +1221,7 @@ let installationFeeObj={
                                                     return;
                                                 }
                                             }
-                                        }else if(feeRule.position && feeRule.position!=""){//再检查code
+                                        }else if(feeRule.position && feeRule.position != ""){//再检查code
                                             let bill = projectObj.project.Bills.getBillByCode(feeRule.position);
                                             if(!bill){
                                                 let c = confirm("所选清单没有找到,需要自动生成吗?");

+ 2 - 0
web/building_saas/main/js/views/project_glj_view.js

@@ -470,6 +470,7 @@ $(function () {
         me.showProjectGljData();
         loadSize("project-glj-main", function () {
             me.projectGljSpread.refresh();
+            me.mixRatioSpread?me.mixRatioSpread.refresh():'';
         });
     });
     $('#ration_link').on('shown.bs.tab', function (e) {
@@ -491,6 +492,7 @@ $(function () {
     });
     slideResize($("#project-glj-main"), function () {
         projectGljObject.projectGljSpread.refresh();
+        projectGljObject.mixRatioSpread?projectGljObject.mixRatioSpread.refresh():'';
     });
     $('#pop-used-list').popover({
             placement: "bottom",

+ 8 - 8
web/building_saas/main/js/views/project_view.js

@@ -14,7 +14,9 @@ var projectObj = {
     },
     // CSL, 2018-02-09 用于测试显示。使用示例:projectObj.testDisplay(‘总额’, 100);
     testDisplay: function (caption, value) {
-        let s = `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ ${caption}: ${value} ]`;
+        let c = '';
+        if (caption) c = caption + ': ';
+        let s = `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${c}${value}`;
         $('#testDisplay').html(s);
     },
     treeSelectedChanged: function (node) {
@@ -47,10 +49,9 @@ var projectObj = {
 
         // 基数
         // node.data.isSubcontract = true;
-        node.data.gljList = project.ration_glj.getGljArrByRation(node.data.ID);
-        let bname = '甲供定额基价材料费';
-        projectObj.testDisplay(bname, rationCalcBases[bname](node));
-
+        // node.data.gljList = project.ration_glj.getGljArrByRation(node.data.ID);
+        // let bname = '甲供定额基价材料费';
+        // projectObj.testDisplay(bname, rationCalcBases[bname](node));
     },
     refreshBaseActn: function (tree) {
         let setButtonValid = function (valid, btn) {
@@ -599,9 +600,8 @@ var projectObj = {
                 that.project.projectMarkChecking();//是否需要重新进行造价计算
                 installationFeeObj.engineeringTypeChecking();//检查是否安装工程
                 //初始需要触发一次点击表格事件,sheet.getAutoFitWidth值(获取单元格文本长度)才正确
-                //autoFlashHeight();//设置界面高度
-               // that.mainSpread.refresh();
-                $(window).resize();
+                autoFlashHeight();
+                projectObj.refreshMainSpread();
             }
             else {