浏览代码

1. 默认参数,增加,子项数量1合计,子项数量2合计
2. 指标匹配,支持多编号匹配,例如:'1-4-4-x-x;1-4-5-x'
3. 导入指标模板,允许2中的指标匹配方式

MaiXinRong 5 年之前
父节点
当前提交
898256c9de

+ 5 - 0
README.zh-CN.md

@@ -35,5 +35,10 @@ $ npm stop
 - 使用 `npm test` 来执行单元测试。
 - 使用 `npm run autod` 来自动检测依赖更新,详细参见 [autod](https://www.npmjs.com/package/autod) 。
 
+### 生成min
+
+- 使用 `uglifyjs inputFiles --compress --mangle -o outputFiles `来生成(文件路径基于运行路径)
+- 示例 `uglifyjs app/public/js/compare.js --compress --mangle -o app/public/js/compare.min.js`
+
 
 [egg]: https://eggjs.org

+ 22 - 4
app/const/template_param.js

@@ -21,20 +21,24 @@ const matchType = {
     properties: 2,
     node_default: 11,
     parent_default: 12,
+    child_gather: 13,
     code: 21,
     non_match: -1,
 }
 const matchTypeStr = [];
 matchTypeStr[matchType.fixed_id] = '全局匹配参数';
-matchTypeStr[matchType.node_default] = '节点默认参数';
 matchTypeStr[matchType.properties] = '属性匹配参数';
+matchTypeStr[matchType.node_default] = '节点默认参数';
+matchTypeStr[matchType.parent_default] = '父项默认参数';
+matchTypeStr[matchType.child_gather] = '子项合计参数';
 matchTypeStr[matchType.code] = '编号匹配参数';
 matchTypeStr[matchType.non_match] = '非匹配参数';
+
 const validMatchType = [matchType.properties, matchType.code, matchType.non_match];
 const validProperties = {
     loadLength: 'loadLength',
     loadWidth: 'loadWidth'
-}
+};
 
 // 参数取值
 const matchNum = {
@@ -140,6 +144,20 @@ const defaultNodeParams = [
         name: '父项数量2',
         match_type: matchType.parent_default,
         match_num: matchNum.dgn_quantity2,
+    }, {
+        template_id: 1,
+        param_id: 2,
+        code: 'b',
+        name: '子项数量1合计',
+        match_type: matchType.child_gather,
+        match_num: matchNum.dgn_quantity1,
+    }, {
+        template_id: 1,
+        param_id: 3,
+        code: 'c',
+        name: '子项数量2合计',
+        match_type: matchType.child_gather,
+        match_num: matchNum.dgn_quantity2,
     },
 ];
 
@@ -153,5 +171,5 @@ module.exports = {
     matchNumStr,
     globalParamNodeId,
     defaultGlobalParams,
-    defaultNodeParams
-}
+    defaultNodeParams,
+};

+ 106 - 12
app/extend/helper.js

@@ -11,6 +11,9 @@
 const fs = require('fs');
 const streamToArray = require('stream-to-array');
 const mathjs = require('mathjs');
+const Decimal = require('decimal.js');
+Decimal.set({precision: 50, defaults: true});
+const bc = require('../lib/base_calc.js');
 
 module.exports = {
     /**
@@ -148,17 +151,20 @@ module.exports = {
      * @return {Boolean}
      */
     validMatchCode(code) {
-        const parts = code.split('-');
-        const reg1 = /(^[a-z]+$)/i;
-        const reg2 = /(^[0-9]+$)/;
-        for (const i in parts) {
-            if (i == 0) {
-                if (!reg2.test(parts[i])) {
-                    return false;
-                }
-            } else {
-                if (!(reg1.test(parts[i]) || reg2.test(parts[i]))) {
-                    return false;
+        const codes = code.split(';');
+        for (const c of codes) {
+            const parts = c.split('-');
+            const reg1 = /(^[a-z]+$)/i;
+            const reg2 = /(^[0-9]+$)/;
+            for (const i in parts) {
+                if (i == 0) {
+                    if (!reg2.test(parts[i])) {
+                        return false;
+                    }
+                } else {
+                    if (!(reg1.test(parts[i]) || reg2.test(parts[i]))) {
+                        return false;
+                    }
                 }
             }
         }
@@ -183,6 +189,17 @@ module.exports = {
         return undefined;
     },
 
+    filterObj(arr, field, value) {
+        if (arr.length === 0) { return undefined; }
+        const newArr = [];
+        for (const a of arr) {
+            if (a[field] && a[field] === value) {
+                newArr.push(a);
+            }
+        }
+        return newArr;
+    },
+
     /**
      * 读取json文件并解析
      *
@@ -407,5 +424,82 @@ module.exports = {
         } catch (err) {
             return null;
         }
-    }
+    },
+
+    // 加减乘除方法,为方便调用,兼容num为空的情况
+    // 加减法使用base_calc,乘除法使用Decimal(原因详见demo/calc_test)
+    /**
+     * 加法 num1 + num2
+     * @param num1
+     * @param num2
+     * @returns {number}
+     */
+    add(num1, num2) {
+        return bc.add(num1 ? num1 : 0, num2 ? num2: 0);
+    },
+    /**
+     * 减法 num1 - num2
+     * @param num1
+     * @param num2
+     * @returns {number}
+     */
+    sub(num1, num2) {
+        return bc.sub(num1 ? num1 : 0, num2 ? num2 : 0);
+    },
+    /**
+     * 乘法 num1 * num2
+     * @param num1
+     * @param num2
+     * @returns {*}
+     */
+    mul(num1, num2, digit = 6) {
+        return Decimal.mul(num1 ? num1 : 0, num2 ? num2 : 0).toDecimalPlaces(digit).toNumber();
+    },
+    /**
+     * 除法 num1 / num2
+     * @param num1 - 被除数
+     * @param num2 - 除数
+     * @returns {*}
+     */
+    div(num1, num2, digit = 6) {
+        if (num2 && !this.checkZero(num2)) {
+            return Decimal.div(num1 ? num1: 0, num2).toDecimalPlaces(digit).toNumber();
+        } else {
+            return null;
+        }
+    },
+    /**
+     * 四舍五入(统一,方便以后万一需要置换)
+     * @param {Number} value - 舍入的数字
+     * @param {Number} decimal - 要保留的小数位数
+     * @returns {*}
+     */
+    round(value, decimal) {
+        //return value ? bc.round(value, decimal) : null;
+        return value ? new Decimal(value).toDecimalPlaces(decimal).toNumber() : null;
+    },
+    /**
+     * 汇总
+     * @param array
+     * @returns {number}
+     */
+    sum(array) {
+        let result = 0;
+        for (const a of array) {
+            result = this.add(result, a);
+        }
+        return result;
+    },
+    /**
+     * 汇总
+     * @param array
+     * @returns {number}
+     */
+    sumField(array, field) {
+        let result = 0;
+        for (const a of array) {
+            result = this.add(result, a[field]);
+        }
+        return result;
+    },
 };

+ 60 - 0
app/lib/base_calc.js

@@ -0,0 +1,60 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+const mulPrecision = 12, divPrecision = 12;
+
+function digitLength (num) {
+    // 兼容科学计数
+    var eSplit = num.toString().split(/[eE]/);
+    var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
+    return len > 0 ? len : 0;
+}
+
+function powLength (num) {
+    var rs = num.toString();
+    if (rs.indexOf('+') > 0) {
+        return rs.match(/0*$/g).length();
+    } else {
+        const eSplit = rs.split(/[eE]/);
+        const len = Number(eSplit[1]) - this.digitLength(eSplit[0]);
+        return len > 0 ? len : 0;
+    }
+}
+
+function round (num, digit) {
+    return Math.round(num * Math.pow(10, digit)) / Math.pow(10, digit);
+}
+
+function add(num1, num2) {
+    var d1 = this.digitLength(num1), d2 = this.digitLength(num2);
+    return this.round(num1 + num2, Math.max(d1, d2));
+}
+
+function sub(num1, num2) {
+    var d1 = this.digitLength(num1), d2 = this.digitLength(num2);
+    return this.round(num1 - num2, Math.max(d1, d2));
+}
+
+function mul(num1, num2) {
+    return this.round(num1 * num2, mulPrecision);
+}
+
+function div(num1, num2) {
+    return this.round(num1 / num2, divPrecision);
+}
+
+module.exports = {
+    digitLength: digitLength,
+    powLength: powLength,
+    round: round,
+    add: add,
+    sub: sub,
+    mul: mul,
+    div: div,
+};

+ 9 - 0
app/public/js/compare.js

@@ -191,6 +191,15 @@ $(document).ready(function () {
                 self.sheet.autoFitRow(row);
             }
             let iRow = 2;
+            data.sort(function (a, b) {
+                if (a.code > b.code) {
+                    return 1;
+                } else if (a.code < b.code) {
+                    return -1;
+                } else {
+                    return 0;
+                }
+            });
             SpreadJsObj.massOperationSheet(this.sheet, function () {
                 self.sheet.setRowCount(2);
                 for (const sd of self.showData) {

文件差异内容过多而无法显示
+ 1 - 0
app/public/js/compare.min.js


+ 1 - 0
app/public/js/cookies.min.js

@@ -0,0 +1 @@
+let Cookies={get:function(e){if(document.cookie.length<=0)return"";let o=document.cookie.indexOf(e+"=");if(o<0)return"";o=o+e.length+1;let t=document.cookie.indexOf(";",o);return t=-1===t?document.cookie.length:t,decodeURI(document.cookie.substring(o,t))}};

文件差异内容过多而无法显示
+ 1 - 0
app/public/js/lib_detail.min.js


文件差异内容过多而无法显示
+ 1 - 0
app/public/js/template.min.js


+ 28 - 3
app/service/match.js

@@ -50,7 +50,7 @@ module.exports = app => {
          * @returns {boolean}
          * @private
          */
-        _matchCode(code, rule) {
+        _matchCodeByRule(code, rule) {
             const codeParts = code.split('-');
             const ruleParts = rule.split('-');
             const numReg = /(^[0-9]+$)/, charReg = /(^[a-z]+$)/i;
@@ -67,6 +67,16 @@ module.exports = app => {
             return true;
         }
 
+        _matchCodeByRules(code, rules) {
+            const ruleArr = rules.split(';');
+            for (const r of ruleArr) {
+                if (this._matchCodeByRule(code, r)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         /**
          * 过滤符合指标节点node匹配规则的清单
          * 已经匹配过的清单不再匹配
@@ -79,7 +89,7 @@ module.exports = app => {
             return this.bills.filter(function (b) {
                 if (!b.match_node) {
                     if (node.match_type === nodeConst.matchType.code) {
-                        return self._matchCode(b.code, node.match_key);
+                        return self._matchCodeByRules(b.code, node.match_key);
                     } else {
                         return node.match_key === b.name;
                     }
@@ -111,6 +121,20 @@ module.exports = app => {
             }
         }
 
+        _getChildrenBillsValue(param, bills) {
+            if (bills) {
+                const children = this.ctx.helper.filterObj(this.bills, 'n_pid', bills.n_id);
+                switch(param.match_num) {
+                    case paramConst.matchNum.quantity: return this.ctx.helper.sumField(children, 'quantity');
+                    case paramConst.matchNum.total_price: return this.ctx.helper.sumField(children, 'total_price');
+                    case paramConst.matchNum.dgn_quantity1: return this.ctx.helper.sumField(children, 'dgn_quantity1');
+                    case paramConst.matchNum.dgn_quantity2: return this.ctx.helper.sumField(children, 'dgn_quantity2');
+                }
+            } else {
+                return undefined;
+            }
+        }
+
         /**
          * 获取指标参数取值(固定Id匹配)
          * @param {Object} param - 指标参数
@@ -135,7 +159,7 @@ module.exports = app => {
          */
         _getCodeParamValue(param) {
             for (const b of this.bills) {
-                if (this._matchCode(b.code, param.match_key)) {
+                if (this._matchCodeByRules(b.code, param.match_key)) {
                     return this._getNodeBillsValue(param, b);
                 }
             }
@@ -166,6 +190,7 @@ module.exports = app => {
                     case paramConst.matchType.fixed_id: return this._getFixedIdParamValue(param);
                     case paramConst.matchType.node_default: return this._getNodeBillsValue(param, nodeBills);
                     case paramConst.matchType.parent_default: return this._getNodeBillsValue(param, this._getParentBills(nodeBills));
+                    case paramConst.matchType.child_gather: return this._getChildrenBillsValue(param, nodeBills);
                     case paramConst.matchType.code: return this._getCodeParamValue(param);
                     // to do 匹配属性
                     default: return undefined;

+ 1 - 0
package.json

@@ -5,6 +5,7 @@
   "private": true,
   "dependencies": {
     "await-stream-ready": "^1.0.1",
+    "decimal.js": "^10.2.0",
     "egg": "^2.2.1",
     "egg-mysql": "^3.0.0",
     "egg-redis": "^2.0.0",