|
@@ -40,6 +40,25 @@ let cbTools = {
|
|
|
}
|
|
|
return null;
|
|
|
},
|
|
|
+ //通过ID获取节点行
|
|
|
+ getRowByID: function (items, ID) {
|
|
|
+ for(let i = 0, len = items.length; i < len; i++){
|
|
|
+ if(items[i]['data']['ID'] == ID){
|
|
|
+ return i + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+ //通过ID获取节点
|
|
|
+ getNodeByID: function (items, ID) {
|
|
|
+ ID = parseInt(ID);
|
|
|
+ for(let i = 0, len = items.length; i < len; i++){
|
|
|
+ if(items[i]['data']['ID'] === ID){
|
|
|
+ return items[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ },
|
|
|
//获取该节点所有父节点
|
|
|
getParents: function (node) {
|
|
|
let rst = [];
|
|
@@ -69,7 +88,7 @@ let cbTools = {
|
|
|
return rst;
|
|
|
}
|
|
|
//获取表达式中的基数和行引用
|
|
|
- let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getRArr(cbParser.getFArr(exp)));
|
|
|
+ let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getXNum(cbParser.getFArr(exp)));
|
|
|
for(let i = 0, len = figureF.length; i < len; i++){
|
|
|
let figure = figureF[i];
|
|
|
if(figure.type === 'base' && cbTools.isDef(calcBase.baseFigures[figure.value])){
|
|
@@ -156,28 +175,22 @@ let cbTools = {
|
|
|
let parent = node.parent;
|
|
|
if(this.isFlag(node.data) && (node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.SUB_ENGINERRING
|
|
|
|| node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CONSTRUCTION_TECH)){
|
|
|
- //node.data.baseFigureClass = null;
|
|
|
return null;
|
|
|
}
|
|
|
else if(this.isFlag(node.data) && node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CONSTRUCTION_ORGANIZATION){
|
|
|
- //node.data.baseFigureClass = 'CONSTRUCTION_ORGANIZATION';
|
|
|
return calcBase.baseFigureClass.CONSTRUCTION_ORGANIZATION;
|
|
|
}
|
|
|
else if(this.isFlag(node.data) && node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.OTHER){
|
|
|
- //node.data.baseFigureClass = 'OTHER';
|
|
|
return calcBase.baseFigureClass.OTHER;
|
|
|
}
|
|
|
else if(this.isFlag(node.data) && node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.CHARGE){
|
|
|
- //node.data.baseFigureClass = 'CHARGE';
|
|
|
return calcBase.baseFigureClass.CHARGE;
|
|
|
}
|
|
|
else if(this.isFlag(node.data) && node.data.flagsIndex.fixed.flag === calcBase.fixedFlag.TAX){
|
|
|
- //node.data.baseFigureClass = 'TAX';
|
|
|
return calcBase.baseFigureClass.TAX;
|
|
|
}
|
|
|
else {
|
|
|
if(!parent){
|
|
|
- //node.data.baseFigureClass = 'OTHERS';
|
|
|
return calcBase.baseFigureClass.OTHERS;
|
|
|
}
|
|
|
else {
|
|
@@ -229,8 +242,8 @@ let cbTools = {
|
|
|
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);
|
|
|
+ else if(bases[i]['type'] === 'id'){
|
|
|
+ let node = cbTools.getNodeByID(calcBase.project.mainTree.items, bases[i]['value']);
|
|
|
if(cbTools.isDef(node)){
|
|
|
block.push(node.data.ID);
|
|
|
}
|
|
@@ -241,7 +254,7 @@ let cbTools = {
|
|
|
function getBase(node){
|
|
|
if(node && node.children.length === 0){
|
|
|
if(cbTools.isDef(node.data.calcBase) && node.data.calcBase !== ''){
|
|
|
- let figureF = cbParser.getFigureF(cbParser.getFigure(node.data.calcBase), cbParser.getRArr(cbParser.getFArr(node.data.calcBase)));
|
|
|
+ let figureF = cbParser.getFigureF(cbParser.getFigure(node.data.calcBase), cbParser.getXNum(cbParser.getFIDArr(node.data.calcBase)));
|
|
|
tempBases = tempBases.concat(figureF);
|
|
|
}
|
|
|
}
|
|
@@ -259,6 +272,48 @@ let cbTools = {
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取全部有公式的树节点清单。 CSL, 2018-01-05
|
|
|
+ getFormulaNodes: function (needOrder = false) {
|
|
|
+ // 给公式结点清单换照引用计算顺序排序。
|
|
|
+ function orderFormulaNodes (nodesArr) {
|
|
|
+ let orderArr = [];
|
|
|
+ function recursionNode(nodes) {
|
|
|
+ for (let node of nodes){
|
|
|
+ if (orderArr.includes(node)) continue; // 已排过序的节点则跳过
|
|
|
+ if (node.data.calcBase){
|
|
|
+ let subNodes = cbTools.getNodesByExp(node.data.calcBase);
|
|
|
+ recursionNode(subNodes);
|
|
|
+ };
|
|
|
+ if (nodesArr.includes(node) && !orderArr.includes(node)) orderArr.push(node);
|
|
|
+ };
|
|
|
+ }
|
|
|
+ recursionNode(nodesArr);
|
|
|
+ return orderArr;
|
|
|
+ };
|
|
|
+
|
|
|
+ let nodes = [];
|
|
|
+ for (let node of projectObj.project.mainTree.items){
|
|
|
+ if (node.sourceType == ModuleNames.bills && node.data.calcBase && node.data.calcBase != '')
|
|
|
+ nodes.push(node);
|
|
|
+ };
|
|
|
+ if (needOrder && nodes.length >= 2) return orderFormulaNodes(nodes)
|
|
|
+ else return nodes;
|
|
|
+ },
|
|
|
+ // 刷新全部行引用的公式清单。 CSL, 2018-01-05
|
|
|
+ refreshFormulaNodes: function () {
|
|
|
+ let nodes = this.getFormulaNodes();
|
|
|
+ if (nodes.length > 0) projectObj.mainController.refreshTreeNode(nodes);
|
|
|
+ },
|
|
|
+ // 判断结点是否被其它结点的表达式引用。
|
|
|
+ isUsedByFormula: function(node){
|
|
|
+ let nodes = this.getFormulaNodes();
|
|
|
+ if (nodes.length == 0) return false;
|
|
|
+ let sID = '@' + node.data.ID;
|
|
|
+ for (let node of nodes){
|
|
|
+ if (node.data.calcBase.hasSubStr(sID)) return true;
|
|
|
+ };
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -477,7 +532,7 @@ let cbAnalyzer = {
|
|
|
},
|
|
|
//输入合法性
|
|
|
inputLegal: function (exp) {
|
|
|
- let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,},F]/g;
|
|
|
+ let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,},F,%]/g;
|
|
|
return !ilegalRex.test(exp);
|
|
|
},
|
|
|
//基数合法性、存在性
|
|
@@ -503,15 +558,22 @@ let cbAnalyzer = {
|
|
|
},
|
|
|
//行引用合法性、存在性
|
|
|
fLegal: function (items, exp) {
|
|
|
+ //提取F标记
|
|
|
+ let fmArr = cbParser.getFMArr(exp);
|
|
|
//提取行引用
|
|
|
let fArr = cbParser.getFArr(exp);
|
|
|
+ if(fmArr.length !== fArr.length){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
//提取行数
|
|
|
- let rArr = cbParser.getRArr(fArr);
|
|
|
+ let rArr = cbParser.getXNum(fArr);
|
|
|
+ if(fArr.length !== rArr.length){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
//判断合法性和存在性
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
@@ -525,16 +587,16 @@ let cbAnalyzer = {
|
|
|
}
|
|
|
//用于判断的起始清单ID
|
|
|
let sIDs = cbTools.getNodeIDs(Array.from(new Set([cbTools.getBaseBill(node)].concat(cbTools.getParents(node)))));
|
|
|
- let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getRArr(cbParser.getFArr(exp)));
|
|
|
+ let figureF = cbParser.getFigureF(cbParser.getFigure(exp), cbParser.getXNum(cbParser.getFIDArr(exp)));
|
|
|
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;
|
|
|
+ else if(figure.type === 'id'){
|
|
|
+ let node = cbTools.getNodeByID(calcBase.project.mainTree.items, figure.value);
|
|
|
+ bill = cbTools.isDef(node) ? node.data : null;
|
|
|
}
|
|
|
if(cbTools.isDef(bill) && checkStack(getRefStack([bill.ID]), sIDs)){
|
|
|
console.log('循环计算');
|
|
@@ -569,20 +631,27 @@ let cbAnalyzer = {
|
|
|
let ilegalRex = /[\+,\-,\*,\/]{2}/g;
|
|
|
let rex2 = /[{]{2}/g;
|
|
|
let rex3 = /[}]{2}/g;
|
|
|
- let rex4 = /[F]{2}/g
|
|
|
- return !ilegalRex.test(exp) && !rex2.test(exp) && !rex3.test(exp) && !rex4.test(exp);
|
|
|
+ let rex4 = /[F]{2}/g;
|
|
|
+ let rex5 = /[.]{2}/g;
|
|
|
+ let rex6 = /[%]{2}/g;
|
|
|
+ return !ilegalRex.test(exp) && !rex2.test(exp) && !rex3.test(exp) && !rex4.test(exp) && !rex5.test(exp) && !rex6.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.fLegal(calcBase.project.mainTree.items, exp)){
|
|
|
- if(!this.cycleCalc(node, cbTools.getFigure(node), exp)){
|
|
|
- if(this.arithmeticLegal(exp)){
|
|
|
+ if(this.arithmeticLegal(exp)){
|
|
|
+ if(this.baseLegal(cbTools.getFigure(node), exp)){
|
|
|
+ if(this.fLegal(calcBase.project.mainTree.items, exp)){
|
|
|
+ //转换成ID引用
|
|
|
+ exp = cbParser.toIDExpr(exp);
|
|
|
+ if(!this.cycleCalc(node, cbTools.getFigure(node), exp)){
|
|
|
return exp;
|
|
|
}
|
|
|
}
|
|
|
+ else {
|
|
|
+ calcBase.errMsg = '行引用不合法';
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -592,22 +661,34 @@ let cbAnalyzer = {
|
|
|
|
|
|
//输入式转换器
|
|
|
let cbParser = {
|
|
|
+ //获取标记F
|
|
|
+ getFMArr: function (exp) {
|
|
|
+ let fmRex = /F/g;
|
|
|
+ let fmArr = exp.match(fmRex);
|
|
|
+ return cbTools.isDef(fmArr) ? fmArr : [];
|
|
|
+ },
|
|
|
//获取行引用 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) {
|
|
|
+ //获取X+num eg: F10 10 @105 105
|
|
|
+ getXNum: function (arr) {
|
|
|
let rRex = /\d+/g;
|
|
|
let tempArr = [];
|
|
|
- for(let i = 0, len = fArr.length; i < len; i++){
|
|
|
- tempArr = tempArr.concat(fArr[i].match(rRex));
|
|
|
+ for(let i = 0, len = arr.length; i < len; i++){
|
|
|
+ tempArr = tempArr.concat(arr[i].match(rRex));
|
|
|
}
|
|
|
let rArr = Array.from(new Set(tempArr));
|
|
|
return rArr;
|
|
|
},
|
|
|
+ //获取ID引用
|
|
|
+ getFIDArr: function (exp) {
|
|
|
+ let fidRex = /@\d+/g;
|
|
|
+ let fidArr = exp.match(fidRex);
|
|
|
+ return cbTools.isDef(fidArr) ? fidArr : [];
|
|
|
+ },
|
|
|
//获取表达式中的中文式,没有{}需求时
|
|
|
getCN: function(expr){
|
|
|
let rst = [];
|
|
@@ -632,8 +713,8 @@ let cbParser = {
|
|
|
}
|
|
|
return rst;
|
|
|
},
|
|
|
- //获取表达式中的基数和行
|
|
|
- getFigureF: function (figures, rArr) {
|
|
|
+ //获取表达式中的基数和ID引用
|
|
|
+ getFigureF: function (figures, fidArr) {
|
|
|
let rst = [];
|
|
|
for(let i = 0, len = figures.length; i < len; i++){
|
|
|
let obj = Object.create(null);
|
|
@@ -641,15 +722,75 @@ let cbParser = {
|
|
|
obj.value = figures[i];
|
|
|
rst.push(obj);
|
|
|
}
|
|
|
- for(let i = 0, len = rArr.length; i < len; i++){
|
|
|
+ for(let i = 0, len = fidArr.length; i < len; i++){
|
|
|
let obj = Object.create(null);
|
|
|
- obj.type = 'row';
|
|
|
- obj.value = rArr[i];
|
|
|
+ obj.type = 'id';
|
|
|
+ obj.value = fidArr[i];
|
|
|
rst.push(obj);
|
|
|
}
|
|
|
return rst;
|
|
|
},
|
|
|
-
|
|
|
+ //表达式中的百分数转换成小数
|
|
|
+ percentToNum: function (exp) {
|
|
|
+ let rex = /\d+(\.\d+)?%/g;
|
|
|
+ let percents = exp.match(rex);
|
|
|
+ let numRex = /\d+(\.\d+)?/g;
|
|
|
+ if(cbTools.isDef(percents)){
|
|
|
+ for(let i = 0, len = percents.length; i < len; i++){
|
|
|
+ let percentNum = percents[i].match(numRex);
|
|
|
+ if(cbTools.isDef(percentNum) && percentNum.length === 1){
|
|
|
+ exp = exp.replace(new RegExp(percents[i], 'g'), percentNum[0]/100);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ },
|
|
|
+ //将行引用转换成ID引用
|
|
|
+ toIDExpr: function (exp) {
|
|
|
+ let exps = [];
|
|
|
+ //获得行引用
|
|
|
+ let fArr = this.getFArr(exp);
|
|
|
+ for(let i = 0, len = fArr.length; i < len; i++){
|
|
|
+ let r = this.getXNum([fArr[i]]);
|
|
|
+ if(r.length === 1){
|
|
|
+ let node = cbTools.getBillByRow(calcBase.project.mainTree.items, r[0] - 1);
|
|
|
+ if(cbTools.isUnDef(node)){
|
|
|
+ //continue;
|
|
|
+ calcBase.errMsg = '行引用错误';
|
|
|
+ throw '行引用错误';
|
|
|
+ }
|
|
|
+ exps.push({orgExp: fArr[i], newExp: '@' + node.data.ID});
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ calcBase.errMsg = '行引用错误';
|
|
|
+ throw '行引用错误';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(let i = 0, len = exps.length; i < len; i++){
|
|
|
+ exp = exp.replace(new RegExp(exps[i].orgExp, 'g'), exps[i].newExp);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ },
|
|
|
+ //将ID引用转换成行引用
|
|
|
+ toFExpr: function (exp) {
|
|
|
+ let exps = [];
|
|
|
+ //获得ID引用
|
|
|
+ let fidArr = this.getFIDArr(exp);
|
|
|
+ for(let i = 0, len = fidArr.length; i < len; i++){
|
|
|
+ let id = this.getXNum([fidArr[i]]);
|
|
|
+ if(id.length === 1){
|
|
|
+ let row = cbTools.getRowByID(calcBase.project.mainTree.items, id[0]);
|
|
|
+ if(cbTools.isUnDef(row)){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ exps.push({orgExp: fidArr[i], newExp: 'F' + row});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(let i = 0, len = exps.length; i < len; i++){
|
|
|
+ exp = exp.replace(new RegExp(exps[i].orgExp, 'g'), exps[i].newExp);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ },
|
|
|
//将表达式转换为可编译的表达式
|
|
|
toCompileExpr: function(v){
|
|
|
if(v === ''){
|
|
@@ -670,15 +811,15 @@ let cbParser = {
|
|
|
v = v.replace(new RegExp(exps[i].orgExp, 'g'), exps[i].compileExp);
|
|
|
}
|
|
|
//行引用
|
|
|
- let fArr = this.getFArr(v);
|
|
|
+ let fidArr = this.getFIDArr(v);
|
|
|
let fExps = [];
|
|
|
- for(let i = 0, len = fArr.length; i < len; i++){
|
|
|
+ for(let i = 0, len = fidArr.length; i < len; i++){
|
|
|
let fExp = Object.create(null);
|
|
|
- fExp.orgExp = fArr[i];
|
|
|
+ fExp.orgExp = fidArr[i];
|
|
|
fExps.push(fExp);
|
|
|
}
|
|
|
for(let i = 0, len = fExps.length; i < len; i++){
|
|
|
- fExps[i].compileExp = '$CBC.f(\'' + fExps[i].orgExp + '\')';
|
|
|
+ fExps[i].compileExp = '$CBC.ref(\'' + fExps[i].orgExp + '\')';
|
|
|
v = v.replace(new RegExp(fExps[i].orgExp, 'g'), fExps[i].compileExp);
|
|
|
}
|
|
|
return v;
|
|
@@ -693,13 +834,18 @@ 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;
|
|
|
+ //ID引用
|
|
|
+ ref: function (fExp) {
|
|
|
+ let ID = cbParser.getXNum([fExp]);
|
|
|
+ if(ID.length === 1){
|
|
|
+ let node = cbTools.getNodeByID(calcBase.project.mainTree.items, parseInt(ID[0]));
|
|
|
+ return cbTools.isDef(node) &&
|
|
|
+ cbTools.isDef(node.data.feesIndex) &&
|
|
|
+ cbTools.isDef(node.data.feesIndex.common) &&
|
|
|
+ cbTools.isDef(node.data.feesIndex.common.totalFee) ?
|
|
|
+ node.data.feesIndex.common.totalFee : 0;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
},
|
|
|
//计算
|
|
|
exec: function () {
|
|
@@ -738,7 +884,7 @@ let calcBase = {
|
|
|
return cbTools.getBaseBill(node);
|
|
|
},
|
|
|
calculate: function (node, reCalc = null) {
|
|
|
- let me = calcBase,
|
|
|
+ let me = calcBase,
|
|
|
$CBA = cbAnalyzer,
|
|
|
$CBP = cbParser,
|
|
|
$CBC = cbCalctor;
|
|
@@ -754,10 +900,14 @@ let calcBase = {
|
|
|
if(!cbTools.isDef(exp)){
|
|
|
throw '表达式不正确';
|
|
|
}
|
|
|
+
|
|
|
//输入式转换表达式
|
|
|
let compileExp = $CBP.toCompileExpr(exp);
|
|
|
//计算
|
|
|
- let calcBaseValue = eval(compileExp);
|
|
|
+ console.log(compileExp);
|
|
|
+ let calcExp = $CBP.percentToNum(compileExp);
|
|
|
+ console.log(calcExp);
|
|
|
+ let calcBaseValue = eval(calcExp);
|
|
|
if(!cbTools.isNum(calcBaseValue)){
|
|
|
throw '表达式不正确';
|
|
|
}
|