ソースを参照

计算基数行引用

zhongzewei 7 年 前
コミット
a2754907ae

+ 155 - 29
web/building_saas/main/js/models/calc_base.js

@@ -30,6 +30,38 @@ let cbTools = {
             }
         }
     },
+    //通过行获取根节点清单
+    getBillByRow: function (items, row) {
+        if(cbTools.isDef(items[row]) &&
+            cbTools.isUnDef(items[row]['parent'])&&
+            cbTools.isDef(items[row]['sourceType']) &&
+            items[row]['sourceType'] === calcBase.project.Bills.getSourceType()){
+            return items[row];
+        }
+        return null;
+    },
+    //获取该节点所有父节点
+    getParents: function (node) {
+        let rst = [];
+        rParent(node);
+        return rst;
+        function rParent(node){
+            if(cbTools.isDef(node.parent)){
+                rst.push(node.parent);
+                rParent(node.parent);
+            }
+        }
+    },
+    //获取所有节点的ID
+    getNodeIDs: function (nodes) {
+        let rst = [];
+        for(let i = 0, len = nodes.length; i < len; i++){
+            if(this.isDef(nodes[i]['data']['ID'])){
+                rst.push(nodes[i]['data']['ID']);
+            }
+        }
+        return rst;
+    },
     //需要用到计算基数的时候,先找出所有的固定清单,避免每个基数都要去遍历寻找清单
     setFixedBills: function (project, billsObj, fixedFlag) {
         let bills = project.Bills.datas;
@@ -150,11 +182,19 @@ let cbTools = {
             return tempBases;
         }
         else {
+            //获取基数和行引用
             getBase(node);
             let bases = Array.from(new Set(tempBases));
+            //根据基数和行引用获取清单ID
             for(let i = 0, len = bases.length; i < len; i++){
-                if(cbTools.isDef(calcBase.baseFigures[bases[i]])){
-                    block.push(calcBase.baseFigures[bases[i]]['fixedBill']['bill']['ID']);
+                if(bases[i]['type'] === 'base' && cbTools.isDef(calcBase.baseFigures[bases[i]['value']])){
+                    block.push(calcBase.baseFigures[bases[i]['value']]['fixedBill']['bill']['ID']);
+                }
+                else if(bases[i]['type'] === 'row'){
+                    let node = cbTools.getBillByRow(calcBase.project.mainTree.items, bases[i]['value'] - 1);
+                    if(cbTools.isDef(node)){
+                        block.push(node.data.ID);
+                    }
                 }
             }
             return Array.from(new Set(block));
@@ -162,8 +202,8 @@ let cbTools = {
         function getBase(node){
             if(node && node.children.length === 0){
                 if(cbTools.isDef(node.data.calcBase) && node.data.calcBase !== ''){
-                    let figures = cbParser.getFigure(node.data.calcBase);
-                    tempBases = tempBases.concat(figures);
+                    let figureF = cbParser.getFigureF(cbParser.getFigure(node.data.calcBase), cbParser.getRArr(cbParser.getFArr(node.data.calcBase)));
+                    tempBases = tempBases.concat(figureF);
                 }
             }
             else if(node && node.children.length > 0) {
@@ -398,7 +438,7 @@ let cbAnalyzer = {
     },
     //输入合法性
     inputLegal: function (exp) {
-        let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,}]/g;
+        let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,},F]/g;
         return !ilegalRex.test(exp);
     },
     //基数合法性、存在性
@@ -422,29 +462,61 @@ let cbAnalyzer = {
         }
         return true;
     },
+    //行引用合法性、存在性
+    fLegal: function (items, exp) {
+        console.log(items);
+        console.log(exp);
+        //提取行引用
+        let fArr = cbParser.getFArr(exp);
+        //提取行数
+        let rArr = cbParser.getRArr(fArr);
+        //判断合法性和存在性
+        for(let i = 0, len = rArr.length; i < len; i++){
+            let idx = rArr[i] - 1;
+            if(cbTools.isUnDef(cbTools.getBillByRow(items, idx))){
+                calcBase.errMsg = '行引用不合法';
+                return false;
+            }
+        }
+        return true;
+    },
     //循环计算
     cycleCalc: function (node, baseFigures, exp) {
         let stack = [];
         if(node.sourceType !== calcBase.project.Bills.getSourceType()){
             return false;
         }
-        let sbillID = cbTools.getBaseBill(node).data.ID;
-        let expFigures = cbParser.getFigure(exp);
-        for(let i = 0, len = expFigures.length; i < len; i++){
-            let figure = expFigures[i];
-            if(cbTools.isDef(baseFigures[figure])){
-                let bill = baseFigures[figure]['fixedBill']['bill'];
-                if(checkStack(getRefStack([bill.ID]), sbillID)){
-                    console.log('循环计算');
-                    calcBase.errMsg = '表达式出现循环计算';
-                    return true;
-                }
+        //用于判断的起始清单ID
+        let sIDs = cbTools.getNodeIDs(Array.from(new Set([cbTools.getBaseBill(node)].concat(cbTools.getParents(node)))));
+        console.log(cbParser.getFArr(exp));
+        console.log(cbParser.getRArr(cbParser.getFArr(exp)));
+        let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getRArr(cbParser.getFArr(exp)));
+        console.log(figureF);
+        for(let i = 0, len = figureF.length; i < len; i++){
+            let figure = figureF[i];
+            let bill = null;
+            if(figure.type === 'base' && cbTools.isDef(baseFigures[figure.value])){
+                bill = baseFigures[figure.value]['fixedBill']['bill'];
+            }
+            else if(figure.type === 'row'){
+                let tempBill = cbTools.getBillByRow(calcBase.project.mainTree.items, figure.value - 1);
+                bill = cbTools.isDef(tempBill) ? tempBill.data : null;
+            }
+            if(cbTools.isDef(bill) && checkStack(getRefStack([bill.ID]), sIDs)){
+                console.log('循环计算');
+                calcBase.errMsg = '表达式出现循环计算';
+                return true;
             }
         }
         return false;
-        function checkStack(stack, startBillID){
+        function checkStack(stack, sIDs){
             //引用栈发现了初始引用
-            return stack.indexOf(startBillID) !== -1;
+            for(let i = 0, len = sIDs.length; i < len; i++){
+                if(stack.indexOf(sIDs[i]) !== -1){
+                    return true;
+                }
+            }
+            return false;
         }
         function getRefStack(billIDs){
             stack = Array.from(new Set(stack.concat(billIDs)));
@@ -458,25 +530,27 @@ let cbAnalyzer = {
             return stack;
         }
     },
-    //四则运算合法性,前端控制不允许重复出现运算符,这里主要判断()的使用问题,这里再判断一次
+    //四则运算合法性,前端控制不允许重复出现运算符,这里主要判断()的使用问题,这里再判断一次,控制行引用只能F
     arithmeticLegal: function (exp) {
         let ilegalRex = /[\+,\-,\*,\/]{2}/g;
         let rex2 = /[{]{2}/g;
         let rex3 = /[}]{2}/g;
-        return !ilegalRex.test(exp) && !rex2.test(exp) && !rex3.test(exp);
+        let rex4 = /[F]{2}/g
+        return !ilegalRex.test(exp) && !rex2.test(exp) && !rex3.test(exp) && !rex4.test(exp);
     },
     //
     legalExp: function (node) {
         let exp = this.standar(node.data.userCalcBase);
         if(this.inputLegal(exp)){
             if(this.baseLegal(cbTools.getFigure(node), exp)){
-                if(!this.cycleCalc(node, cbTools.getFigure(node), exp)){
-                    if(this.arithmeticLegal(exp)){
-                        return exp;
+                if(this.fLegal(calcBase.project.mainTree.items, exp)){
+                    if(!this.cycleCalc(node, cbTools.getFigure(node), exp)){
+                        if(this.arithmeticLegal(exp)){
+                            return exp;
+                        }
                     }
                 }
             }
-            return null;
         }
         return null;
     }
@@ -484,6 +558,22 @@ let cbAnalyzer = {
 
 //输入式转换器
 let cbParser = {
+    //获取行引用 eg: F10
+    getFArr: function (exp) {
+        let fRex = /F\d+/g;
+        let fArr = exp.match(fRex);
+        return cbTools.isDef(fArr) ? fArr : [];
+    },
+    //获取行 eg: F10  10
+    getRArr: function (fArr) {
+        let rRex = /\d+/g;
+        let tempArr = [];
+        for(let i = 0, len = fArr.length; i < len; i++){
+            tempArr = tempArr.concat(fArr[i].match(rRex));
+        }
+        let rArr = Array.from(new Set(tempArr));
+        return rArr;
+    },
     //获取表达式中的中文式,没有{}需求时
     getCN: function(expr){
         let rst = [];
@@ -508,12 +598,30 @@ let cbParser = {
         }
         return rst;
     },
+    //获取表达式中的基数和行
+    getFigureF: function (figures, rArr) {
+        let rst = [];
+        for(let i = 0, len = figures.length; i < len; i++){
+            let obj = Object.create(null);
+            obj.type = 'base';
+            obj.value = figures[i];
+            rst.push(obj);
+        }
+        for(let i = 0, len = rArr.length; i < len; i++){
+            let obj = Object.create(null);
+            obj.type = 'row';
+            obj.value = rArr[i];
+            rst.push(obj);
+        }
+        return rst;
+    },
 
     //将表达式转换为可编译的表达式
     toCompileExpr: function(v){
         if(v === ''){
             return '$CBC.base(\'NONE\')';
         }
+        //基数
         let strs = this.getFigure(v);
         let exps = [];
         for(let i = 0, len = strs.length; i < len; i++){
@@ -524,9 +632,20 @@ let cbParser = {
         //去{}
         v = v.replace(/[{, }]/g, '');
         for(let i = 0, len = exps.length;i < len; i++){
-            exps[i].compileExp = '$CBC.base(\'' + exps[i].orgExp;
-            exps[i].compileExp = exps[i].compileExp + '\')';
-            v = v.replace(new RegExp(exps[i].orgExp,"g"), exps[i].compileExp);
+            exps[i].compileExp = '$CBC.base(\'' + exps[i].orgExp + '\')';
+            v = v.replace(new RegExp(exps[i].orgExp, 'g'), exps[i].compileExp);
+        }
+        //行引用
+        let fArr = this.getFArr(v);
+        let fExps = [];
+        for(let i = 0, len = fArr.length; i < len; i++){
+            let fExp = Object.create(null);
+            fExp.orgExp = fArr[i];
+            fExps.push(fExp);
+        }
+        for(let i = 0, len = fExps.length; i < len; i++){
+            fExps[i].compileExp = '$CBC.f(\'' + fExps[i].orgExp + '\')';
+            v = v.replace(new RegExp(fExps[i].orgExp, 'g'), fExps[i].compileExp);
         }
         return v;
     }
@@ -540,6 +659,14 @@ let cbCalctor = {
         }
         return baseFigureTemplate[calcBase.baseFigures[figure]['base']]();
     },
+    //行引用
+    f: function (fExp) {
+        let r = cbParser.getRArr([fExp]);
+        return cbTools.isDef(calcBase.project.mainTree.items[r[0] - 1]['data']['feesIndex']) &&
+            cbTools.isDef(calcBase.project.mainTree.items[r[0] - 1]['data']['feesIndex']['common'])&&
+            cbTools.isDef(calcBase.project.mainTree.items[r[0] - 1]['data']['feesIndex']['common']['totalFee']) ?
+            calcBase.project.mainTree.items[r[0] - 1]['data']['feesIndex']['common']['totalFee'] : 0;
+    },
     //计算
     exec: function () {
 
@@ -576,7 +703,7 @@ let calcBase = {
     getBaseBill: function (node) {
         return cbTools.getBaseBill(node);
     },
-    calculate: function (node, reCalc) {
+    calculate: function (node, reCalc = null) {
         let me = calcBase,
             $CBA = cbAnalyzer,
             $CBP = cbParser,
@@ -595,7 +722,6 @@ let calcBase = {
             }
             //输入式转换表达式
             let compileExp = $CBP.toCompileExpr(exp);
-
             //计算
             let calcBaseValue = eval(compileExp);
             if(!cbTools.isNum(calcBaseValue)){

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

@@ -150,7 +150,8 @@ let calcBaseView = {
         let rex = /[\+,\-,\*,\/]{2}/g;
         let rex2 = /[{]{2}/g;
         let rex3 = /[}]{2}/g;
-        return !rex.test(v) && !rex2.test(v) && !rex3.test(v);
+        let rex4 = /[F]{2}/g;
+        return !rex.test(v) && !rex2.test(v) && !rex3.test(v) && !rex4.test(v);
     },
 
     //运算符点击显示到运算窗口