|
@@ -1,7 +1,7 @@
|
|
|
/**
|
|
|
* Created by Tony on 2017/6/21.
|
|
|
- * Modified by CSL, 2017-08-01
|
|
|
- * 引入多套计算程序、费率同步、人工系数同步、改进基数计算、费字段映射等。
|
|
|
+ * Modified by CSL, 2017-08-01 引入多套计算程序、费率同步、人工系数同步、改进基数计算、费字段映射等。
|
|
|
+ * added by CSL, 2017-09-01 增加公式解析对象analyzer,用于解析用户修改公式、自定义表达式。
|
|
|
*/
|
|
|
|
|
|
let executeObj = {
|
|
@@ -39,6 +39,129 @@ let executeObj = {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+let analyzer = {
|
|
|
+ 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
|
|
|
+ console.log(str);
|
|
|
+ return str;
|
|
|
+ },
|
|
|
+
|
|
|
+ analyzeCalcBase: function(expr){
|
|
|
+ // 前提:必须无空格、无特殊符号
|
|
|
+ function getCalcBase(expr){
|
|
|
+ let base = '',
|
|
|
+ iPos1 = -1, iPos2 = -1;
|
|
|
+ for (let i = 0; i < expr.length; i++) {
|
|
|
+ if (expr[i] === '['){
|
|
|
+ iPos1 = i;
|
|
|
+ }
|
|
|
+ else if (iPos1 != -1 && expr[i]===']'){
|
|
|
+ iPos2 = i;
|
|
|
+ };
|
|
|
+
|
|
|
+ if (iPos1 != -1 && iPos2 != -1){
|
|
|
+ base = expr.slice(iPos1, iPos2 + 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return base;
|
|
|
+ };
|
|
|
+ function calcBaseToIDExpr(base){
|
|
|
+ // for test.
|
|
|
+ let id = -1;
|
|
|
+ if (base == '[人工费]'){
|
|
|
+ id = 111;
|
|
|
+ }
|
|
|
+ else if (base == '[材料费]'){
|
|
|
+ id = 222;
|
|
|
+ }
|
|
|
+ else if (base == '[机械费]'){
|
|
|
+ id = 333;
|
|
|
+ }
|
|
|
+ else id = 999;
|
|
|
+
|
|
|
+ return "@('" + id + "')";
|
|
|
+ };
|
|
|
+
|
|
|
+ while (expr.indexOf('[') > 0) {
|
|
|
+ let base = getCalcBase(expr);
|
|
|
+ let id = calcBaseToIDExpr(base);
|
|
|
+ let baseValue = base.slice(1, -1); // []会给下面的正则带来干扰,这里去掉
|
|
|
+ var pattBase =new RegExp(baseValue, "g");
|
|
|
+ expr = expr.replace(pattBase, id);
|
|
|
+ expr = expr.replace(/\[@\('/g, "@('"); // [@('
|
|
|
+ expr = expr.replace(/'\)\]/g, "')"); // ')]
|
|
|
+ };
|
|
|
+
|
|
|
+ return expr;
|
|
|
+ },
|
|
|
+
|
|
|
+ analyzeLineRef: function(expr){
|
|
|
+ function isOperator(char){
|
|
|
+ var operator = "+-*/()";
|
|
|
+ return operator.indexOf(char) > -1;
|
|
|
+ };
|
|
|
+ function codeToID(code){
|
|
|
+ return eval(parseFloat(code)+1);
|
|
|
+ };
|
|
|
+ // 前提:必须无空格、无特殊符号、标准大写F
|
|
|
+ function getSection(expr){
|
|
|
+ let section = '',
|
|
|
+ iPos1 = -1, iPos2 = -1;
|
|
|
+ for (let i = 0; i < expr.length; i++) {
|
|
|
+ if (expr[i] === 'F'){
|
|
|
+ iPos1 = i;
|
|
|
+ }
|
|
|
+ else if (iPos1 != -1 && isOperator(expr[i])){
|
|
|
+ iPos2 = i;
|
|
|
+ }
|
|
|
+ else if (iPos1 != -1 && i == expr.length - 1){
|
|
|
+ iPos2 = i + 1;
|
|
|
+
|
|
|
+ };
|
|
|
+ if (iPos1 != -1 && iPos2 != -1){
|
|
|
+ section = expr.slice(iPos1, iPos2);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return section;
|
|
|
+ };
|
|
|
+ function sectionToIDExpr(section){
|
|
|
+ if (section){
|
|
|
+ let code = section.slice(1);
|
|
|
+ if (isNaN(code)){
|
|
|
+ return '错误' // 这里的返回提示不能加上section,因为会无限循环
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return "@('" + codeToID(code) + "')";
|
|
|
+ }
|
|
|
+ else return '';
|
|
|
+ };
|
|
|
+
|
|
|
+ while (expr.indexOf('F') > 0) {
|
|
|
+ let sec = getSection(expr);
|
|
|
+ let id = sectionToIDExpr(sec);
|
|
|
+ var pattSec =new RegExp(sec, "g");
|
|
|
+ expr = expr.replace(pattSec, id);
|
|
|
+ };
|
|
|
+ return expr;
|
|
|
+ },
|
|
|
+
|
|
|
+ analyzeUserExpr: function(expr){
|
|
|
+ // 标准化:处理特殊字符、中文符号、大小写
|
|
|
+ expr = this.standard(expr);
|
|
|
+ // 先换掉计算基数
|
|
|
+ expr = this.analyzeCalcBase(expr);
|
|
|
+ // 再换掉行引用
|
|
|
+ expr = this.analyzeLineRef(expr);
|
|
|
+ return expr;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
class Calculation {
|
|
|
// 先编译公用的基础数据
|
|
|
compilePublics(feeRates, labourCoes, feeTypes, calcBases){
|
|
@@ -234,4 +357,6 @@ class Calculation {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+};
|
|
|
+
|
|
|
+export default analyzer;
|