Browse Source

根据测试结果,前后端,统一计算、舍入等

MaiXinRong 6 years ago
parent
commit
bc02e37462

+ 7 - 7
app/controller/stage_controller.js

@@ -602,14 +602,14 @@ module.exports = app => {
             function assignStageData(chapter, curStage, preStage) {
                 chapter.contract_tp = curStage.contract_tp;
                 chapter.qc_tp = curStage.qc_tp;
-                chapter.gather_tp = ctx.helper.plus(curStage.contract_tp, curStage.qc_tp);
+                chapter.gather_tp = ctx.helper.add(curStage.contract_tp, curStage.qc_tp);
                 if (preStage) {
                     chapter.pre_contract_tp = preStage.contract_tp;
                     chapter.pre_qc_tp = preStage.qc_tp;
-                    chapter.pre_gather_tp = ctx.helper.plus(preStage.contract_tp, preStage.qc_tp);
-                    chapter.end_contract_tp = ctx.helper.plus(curStage.contract_tp, preStage.contract_tp);
-                    chapter.end_qc_tp = ctx.helper.plus(curStage.qc_tp, preStage.qc_tp);
-                    chapter.end_gather_tp = ctx.helper.plus(chapter.gather_tp, chapter.pre_gather_tp);
+                    chapter.pre_gather_tp = ctx.helper.add(preStage.contract_tp, preStage.qc_tp);
+                    chapter.end_contract_tp = ctx.helper.add(curStage.contract_tp, preStage.contract_tp);
+                    chapter.end_qc_tp = ctx.helper.add(curStage.qc_tp, preStage.qc_tp);
+                    chapter.end_gather_tp = ctx.helper.add(chapter.gather_tp, chapter.pre_gather_tp);
                 } else {
                     chapter.end_contract_tp = curStage.contract_tp;
                     chapter.end_qc_tp = curStage.qc_tp;
@@ -633,7 +633,7 @@ module.exports = app => {
                             const sum = _.find(calcDetail, {cType: 11});
                             const chapters = _.filter(calcDetail, {cType: 1});
                             for (const f of fields) {
-                                cd[f] = ctx.helper.minus(sum[f], this.ctx.helper.sum(_.map(chapters, f)));//_.sumBy(chapters, f));
+                                cd[f] = ctx.helper.sub(sum[f], this.ctx.helper.sum(_.map(chapters, f)));//_.sumBy(chapters, f));
                             }
                             break;
                         case 31:
@@ -643,7 +643,7 @@ module.exports = app => {
                             const sum1 = _.find(calcDetail, {cType: 11});
                             const sum2 = _.find(calcDetail, {cType: 31});
                             for (const f of fields) {
-                                cd[f] = ctx.helper.plus(sum1.value, sum2.value);
+                                cd[f] = ctx.helper.add(sum1.value, sum2.value);
                             }
                             break;
                     }

+ 13 - 76
app/extend/helper.js

@@ -12,9 +12,8 @@ const fs = require('fs');
 const path = require('path');
 const streamToArray = require('stream-to-array');
 const _ = require('lodash');
-const np = require('number-precision');
-np.enableBoundaryChecking(false);
-const math = require('mathjs');
+const bc = require('../lib/base_calc.js');
+const Decimal = require('decimal.js');
 
 module.exports = {
     _: _,
@@ -596,16 +595,16 @@ module.exports = {
         }
     },
 
-    // 以下方法均调用number-precision处理
     // 加减乘除方法,为方便调用,兼容num为空的情况
+    // 加减法使用base_calc,乘除法使用Decimal(原因详见demo/calc_test)
     /**
      * 加法 num1 + num2
      * @param num1
      * @param num2
      * @returns {number}
      */
-    plus(num1, num2) {
-        return np.plus(num1 ? num1 : 0, num2 ? num2: 0);
+    add(num1, num2) {
+        return bc.add(num1 ? num1 : 0, num2 ? num2: 0);
     },
     /**
      * 减法 num1 - num2
@@ -613,8 +612,8 @@ module.exports = {
      * @param num2
      * @returns {number}
      */
-    minus(num1, num2) {
-        return np.minus(num1 ? num1 : 0, num2 ? num2 : 0);
+    sub(num1, num2) {
+        return bc.sub(num1 ? num1 : 0, num2 ? num2 : 0);
     },
     /**
      * 乘法 num1 * num2
@@ -622,8 +621,8 @@ module.exports = {
      * @param num2
      * @returns {*}
      */
-    times(num1, num2) {
-        return np.times(num1 ? num1 : 0, num2 ? num2 : 0);
+    mul(num1, num2, digit = 6) {
+        return Decimal.mul(num1 ? num1 : 0, num2 ? num2 : 0).toDecimalPlaces(digit).toNumber();
     },
     /**
      * 除法 num1 / num2
@@ -631,9 +630,9 @@ module.exports = {
      * @param num2 - 除数
      * @returns {*}
      */
-    divide(num1, num2) {
+    div(num1, num2, digit = 6) {
         if (num2 && !this.checkZero(num2)) {
-            return np.divide(num1 ? num1: 0, num2);
+            return Decimal.div(num1 ? num1: 0, num2).toDecimalPlaces(digit).toNumber();
         } else {
             return null;
         }
@@ -645,7 +644,8 @@ module.exports = {
      * @returns {*}
      */
     round(value, decimal) {
-        return value ? np.round(value, decimal) : null;
+        //return value ? bc.round(value, decimal) : null;
+        return value ? Decimal.round(value, decimal).toNumber() : null;
     },
     /**
      * 汇总
@@ -659,67 +659,4 @@ module.exports = {
         }
         return result;
     },
-
-    // // 以下方法均使用js自有方法,保留10位小数
-    // /**
-    //  * 加法 num1 + num2
-    //  * @param num1
-    //  * @param num2
-    //  * @returns {number}
-    //  */
-    // plus(num1, num2) {
-    //     return _.round((num1 ? num1 : 0) + (num2 ? num2: 0), 10);
-    // },
-    // /**
-    //  * 减法 num1 - num2
-    //  * @param num1
-    //  * @param num2
-    //  * @returns {number}
-    //  */
-    // minus(num1, num2) {
-    //     return _.round((num1 ? num1 : 0) - (num2 ? num2: 0), 10);
-    // },
-    // /**
-    //  * 乘法 num1 * num2
-    //  * @param num1
-    //  * @param num2
-    //  * @returns {*}
-    //  */
-    // times(num1, num2) {
-    //     return _.round((num1 ? num1 : 0) * (num2 ? num2: 0), 10);
-    // },
-    // /**
-    //  * 除法 num1 / num2
-    //  * @param num1 - 被除数
-    //  * @param num2 - 除数
-    //  * @returns {*}
-    //  */
-    // divide(num1, num2) {
-    //     if (num2 && !this.checkZero(num2)) {
-    //         return _.round((num1 ? num1 : 0) / (num2 ? num2: 0), 10);
-    //     } else {
-    //         return null;
-    //     }
-    // },
-    // /**
-    //  * 四舍五入(统一,方便以后万一需要置换)
-    //  * @param {Number} value - 舍入的数字
-    //  * @param {Number} decimal - 要保留的小数位数
-    //  * @returns {*}
-    //  */
-    // round(value, decimal) {
-    //     return value ? _.round(value, decimal) : null;
-    // },
-    // /**
-    //  * 汇总
-    //  * @param array
-    //  * @returns {number}
-    //  */
-    // sum(array) {
-    //     let result = 0;
-    //     for (const a of array) {
-    //         result = this.plus(result, a);
-    //     }
-    //     return result;
-    // }
 };

+ 6 - 6
app/lib/analysis_excel.js

@@ -204,14 +204,14 @@ class ImportBaseTree {
             if (!node.pos || node.pos.length === 0) { continue; }
             node.sgfh_qty = this.ctx.helper.sum(_.map(node.pos, 'sgfh_qty'));
             if (node.sgfh_qty && node.unit_price) {
-                node.sgfh_tp = this.ctx.helper.round(this.ctx.helper.times(node.sgfh_qty, node.unit_price),
+                node.sgfh_tp = this.ctx.helper.round(this.ctx.helper.mul(node.sgfh_qty, node.unit_price),
                     this.ctx.tender.info.decimal.tp);
             } else {
                 node.sgfh_tp = null;
             }
             node.quantity = this.ctx.helper.sum(_.map(node.pos, 'quantity'));
             if (node.quantity && node.unit_price) {
-                node.total_price = this.ctx.helper.round(this.ctx.helper.times(node.quantity, node.unit_price),
+                node.total_price = this.ctx.helper.round(this.ctx.helper.mul(node.quantity, node.unit_price),
                     this.ctx.tender.info.decimal.tp);
             } else {
                 node.total_price = null;
@@ -266,13 +266,13 @@ class AnalysisExcelTree {
         node.drawing_code = row[this.colsDef.drawing_code];
         node.memo = row[this.colsDef.memo];
         if (node.sgfh_qty && node.unit_price) {
-            node.sgfh_tp = this.ctx.helper.round(this.ctx.helper.times(node.sgfh_qty, node.unit_price), this.ctx.tender.info.decimal.tp);
+            node.sgfh_tp = this.ctx.helper.round(this.ctx.helper.mul(node.sgfh_qty, node.unit_price), this.ctx.tender.info.decimal.tp);
         } else {
             node.sgfh_tp = null;
         }
         node.quantity = node.sgfh_qty;
         if (node.quantity && node.unit_price) {
-            node.total_price = this.ctx.helper.round(this.ctx.helper.times(node.quantity, node.unit_price), this.ctx.tender.info.decimal.tp);
+            node.total_price = this.ctx.helper.round(this.ctx.helper.mul(node.quantity, node.unit_price), this.ctx.tender.info.decimal.tp);
         } else {
             node.total_price = null;
         }
@@ -295,13 +295,13 @@ class AnalysisExcelTree {
         node.drawing_code = row[this.colsDef.drawing_code];
         node.memo = row[this.colsDef.memo];
         if (node.sgfh_qty && node.unit_price) {
-            node.sgfh_tp = this.ctx.helper.round(this.ctx.helper.times(node.sgfh_qty, node.unit_price), this.ctx.tender.info.decimal.tp);
+            node.sgfh_tp = this.ctx.helper.round(this.ctx.helper.mul(node.sgfh_qty, node.unit_price), this.ctx.tender.info.decimal.tp);
         } else {
             node.sgfh_tp = null;
         }
         node.quantity = node.sgfh_qty;
         if (node.quantity && node.unit_price) {
-            node.total_price = this.ctx.helper.round(this.ctx.helper.times(node.quantity, node.unit_price), this.ctx.tender.info.decimal.tp);
+            node.total_price = this.ctx.helper.round(this.ctx.helper.mul(node.quantity, node.unit_price), this.ctx.tender.info.decimal.tp);
         } else {
             node.total_price = null;
         }

+ 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 - 9
app/lib/pay_calc.js

@@ -91,13 +91,13 @@ class PayCalculate {
         const cur = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
         const add = {};
         if (pre) {
-            add.contract_tp = this.ctx.helper.plus(pre.contract_tp, cur.contract_tp);
-            add.qc_tp = this.ctx.helper.plus(pre.qc_tp, cur.qc_tp);
+            add.contract_tp = this.ctx.helper.add(pre.contract_tp, cur.contract_tp);
+            add.qc_tp = this.ctx.helper.add(pre.qc_tp, cur.qc_tp);
         } else {
             add.contract_tp = cur.contract_tp;
             add.qc_tp = cur.qc_tp;
         }
-        add.gather_tp = this.ctx.helper.plus(add.contract_tp, add.qc_tp);
+        add.gather_tp = this.ctx.helper.add(add.contract_tp, add.qc_tp);
         return add;
     }
 
@@ -139,9 +139,9 @@ class PayCalculate {
                     if (!p.pause && (!p.sprice || addRela.gather_tp > p.sprice)) {
                         if (p.rprice) {
                             if (this.checkDeadline(p)) {
-                                p.tp = this.ctx.helper.minus(p.rprice, p.pre_total_price);
+                                p.tp = this.ctx.helper.sub(p.rprice, p.pre_total_price);
                             } else {
-                                p.tp = Math.min(this.ctx.helper.minus(p.rprice, p.pre_total_price), value);
+                                p.tp = Math.min(this.ctx.helper.sub(p.rprice, p.pre_total_price), value);
                             }
                         } else {
                             p.tp = value;
@@ -153,15 +153,15 @@ class PayCalculate {
                 // 累加 至 应付
                 if (p.is_yf) {
                     if (p.minus) {
-                        yfPay.tp = this.ctx.helper.minus(yfPay.tp, p.tp);
+                        yfPay.tp = this.ctx.helper.sub(yfPay.tp, p.tp);
                     } else {
-                        yfPay.tp = this.ctx.helper.plus(yfPay.tp, p.tp);
+                        yfPay.tp = this.ctx.helper.add(yfPay.tp, p.tp);
                     }
                 }
             }
-            p.end_tp = this.ctx.helper.round(this.ctx.helper.plus(p.tp, p.pre_tp), this.decimal);
+            p.end_tp = this.ctx.helper.round(this.ctx.helper.add(p.tp, p.pre_tp), this.decimal);
         }
-        yfPay.end_tp = this.ctx.helper.plus(yfPay.tp, yfPay.pre_tp);
+        yfPay.end_tp = this.ctx.helper.add(yfPay.tp, yfPay.pre_tp);
     }
 
     async calculateAll(pays) {

File diff suppressed because it is too large
+ 4877 - 0
app/public/js/decimal.js


File diff suppressed because it is too large
+ 3 - 0
app/public/js/decimal.min.js


+ 13 - 12
app/public/js/gcl_gather.js

@@ -1,7 +1,8 @@
 'use strict';
 
 /**
- * 清单汇总(需使用path_tree.js, lodash.js)
+ *
+ * 清单汇总(需使用 decimal.min.js, zh_calc.js, path_tree.js, lodash.js)
  *
  * @author Mai
  * @date
@@ -28,16 +29,16 @@ const gclGatherModel = (function () {
     gsTreeSetting.calcFields = ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     gsTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
-            node.gather_qty = ZhCalc.plus(node.contract_qty, node.qc_qty);
-            node.end_contract_qty = ZhCalc.plus(node.pre_contract_qty, node.contract_qty);
-            node.end_qc_qty = ZhCalc.plus(node.pre_qc_qty, node.qc_qty);
-            node.end_gather_qty = ZhCalc.plus(node.pre_gather_qty, node.gather_qty);
+            node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+            node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
+            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+            node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
         }
-        node.gather_tp = ZhCalc.plus(node.contract_tp, node.qc_tp);
-        node.end_contract_tp = ZhCalc.plus(node.pre_contract_tp, node.contract_tp);
-        node.end_qc_tp = ZhCalc.plus(node.pre_qc_tp, node.qc_tp);
-        node.end_gather_tp = ZhCalc.plus(node.pre_gather_tp, node.gather_tp);
-        node.dgn_price = ZhCalc.round(ZhCalc.divide(node.total_price, node.dgn_qty1), 2);
+        node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+        node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
+        node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+        node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
+        node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
     };
     const gsTree = createNewPathTree('stage', gsTreeSetting);
     // 初始化 部位明细
@@ -46,7 +47,7 @@ const gclGatherModel = (function () {
         updateFields: ['contract_qty', 'qc_qty'],
     };
     posSetting.calcFun = function (pos) {
-        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
+        pos.gather_qty = ZhCalc.add(pos.contract_qty, pos.qc_qty);
     };
     const gsPos = new StagePosData(posSetting);
     let deal = [];
@@ -89,7 +90,7 @@ const gclGatherModel = (function () {
     function gatherfields(obj, src, fields) {
         if (obj && src) {
             for (const f of fields) {
-                obj[f] = ZhCalc.plus(obj[f], src[f]);
+                obj[f] = ZhCalc.add(obj[f], src[f]);
             }
         }
     }

+ 0 - 4
app/public/js/global.js

@@ -302,10 +302,6 @@ function removeLocalCache(key) {
     return storage.removeItem(key);
 }
 
-/**
- * 计算(四则、舍入) 统一,方便以后置换
- * @type {{plus, minus, times, divide, round}}
- */
 const ZhCalc = (function () {
     // 关闭边界检查
     NP.enableBoundaryChecking(false);

+ 1 - 1
app/public/js/ledger.js

@@ -33,7 +33,7 @@ $(document).ready(function() {
         treeSetting.calcFields = ['deal_tp', 'sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price'];
     }
     treeSetting.calcFun = function (node) {
-        node.dgn_price = ZhCalc.round(ZhCalc.divide(node.total_price, node.dgn_qty1), 2);
+        node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
     };
     const ledgerTree = createNewPathTree('ledger', treeSetting);
     ledgerTree.loadDatas(ledger);

+ 11 - 2
app/public/js/number-precision.js

@@ -23,6 +23,12 @@ var NP = (function (exports) {
         var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
         return len > 0 ? len : 0;
     }
+    function powLength(num) {
+        var eSplit = num.toString().split(/[eE]/);
+        var rs = num.toString().reverse();
+        var rs1 = rs.replace('/^0+/g', '');
+        return rs.length - rs1.length;
+    }
     /**
      * 把小数转成整数,支持科学计数法。如果是小数则放大成整数
      * @param {*number} num 输入数
@@ -76,6 +82,7 @@ var NP = (function (exports) {
         }
         var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
         return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
+        //return (num1 + num2) / baseNum;
     }
     /**
      * 精确减法
@@ -88,8 +95,10 @@ var NP = (function (exports) {
         if (others.length > 0) {
             return minus.apply(void 0, [minus(num1, num2), others[0]].concat(others.slice(1)));
         }
-        var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
-        return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
+        var digit1 = digitLength(num1);
+        var digit2 = digitLength(num2);
+        var baseNum = Math.pow(10, Math.max(digit1, digit2));
+        return round((times(num1, baseNum) - times(num2, baseNum)) / baseNum, digit1>=digit2 ? digit1 : digit2);
     }
     /**
      * 精确除法

+ 3 - 1
app/public/js/path_tree.js

@@ -1,4 +1,6 @@
 /**
+ * (需使用 decimal.min.js, zh_calc.js)
+ *
  * 构建pathTree
  * 可动态加载子节点,要求子节点获取接口按/xxx/get-children定义
  * @param {Object} setting - 设置
@@ -1227,7 +1229,7 @@ const treeCalc = {
             const gather = node.children.reduce(function (rst, x) {
                 const result = {};
                 for (const cf of tree.setting.calcFields) {
-                    result[cf] = ZhCalc.plus(rst[cf], x[cf]);
+                    result[cf] = ZhCalc.add(rst[cf], x[cf]);
                 }
                 return result;
             });

+ 18 - 18
app/public/js/stage.js

@@ -105,18 +105,18 @@ $(document).ready(() => {
         'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     stageTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
-            node.pre_gather_qty = ZhCalc.plus(node.pre_contract_qty, node.pre_qc_qty);
-            node.gather_qty = ZhCalc.plus(node.contract_qty, node.qc_qty);
-            node.end_contract_qty = ZhCalc.plus(node.pre_contract_qty, node.contract_qty);
-            node.end_qc_qty = ZhCalc.plus(node.pre_qc_qty, node.qc_qty);
-            node.end_gather_qty = ZhCalc.plus(node.pre_gather_qty, node.gather_qty);
+            node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+            node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+            node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
+            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+            node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
         }
-        node.pre_gather_tp = ZhCalc.plus(node.pre_contract_tp, node.pre_qc_tp);
-        node.gather_tp = ZhCalc.plus(node.contract_tp, node.qc_tp);
-        node.end_contract_tp = ZhCalc.plus(node.pre_contract_tp, node.contract_tp);
-        node.end_qc_tp = ZhCalc.plus(node.pre_qc_tp, node.qc_tp);
-        node.end_gather_tp = ZhCalc.plus(node.pre_gather_tp, node.gather_tp);
-        node.dgn_price = ZhCalc.round(ZhCalc.divide(node.total_price, node.dgn_qty1), tenderInfo.decimal.up);
+        node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+        node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+        node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
+        node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+        node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
+        node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), tenderInfo.decimal.up);
     };
     const stageTree = createNewPathTree('stage', stageTreeSetting);
     // 初始化 部位明细 数据结构
@@ -125,11 +125,11 @@ $(document).ready(() => {
         updateFields: ['contract_qty', 'qc_qty', 'postil'],
     };
     stagePosSetting.calcFun = function (pos) {
-        pos.pre_gather_qty = ZhCalc.plus(pos.pre_contract_qty, pos.pre_qc_qty);
-        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
-        pos.end_contract_qty = ZhCalc.plus(pos.pre_contract_qty, pos.contract_qty);
-        pos.end_qc_qty = ZhCalc.plus(pos.pre_qc_qty, pos.qc_qty);
-        pos.end_gather_qty = ZhCalc.plus(pos.pre_gather_qty, pos.gather_qty);
+        pos.pre_gather_qty = ZhCalc.add(pos.pre_contract_qty, pos.pre_qc_qty);
+        pos.gather_qty = ZhCalc.add(pos.contract_qty, pos.qc_qty);
+        pos.end_contract_qty = ZhCalc.add(pos.pre_contract_qty, pos.contract_qty);
+        pos.end_qc_qty = ZhCalc.add(pos.pre_qc_qty, pos.qc_qty);
+        pos.end_gather_qty = ZhCalc.add(pos.pre_gather_qty, pos.gather_qty);
     };
     const stagePos = new StagePosData(stagePosSetting);
 
@@ -282,11 +282,11 @@ $(document).ready(() => {
         _calculateAmount() {
             for (const c of this.changes) {
                 c.bamount = _.toNumber(c.b_amount);
-                c.vamount = ZhCalc.minus(c.bamount, c.used_amount);
+                c.vamount = ZhCalc.sub(c.bamount, c.used_amount);
                 const uc = _.find(this.useChanges, {cid: c.cid, cbid: c.cbid});
                 if (uc) {
                     c.uamount = uc.qty;
-                    c.vamount = ZhCalc.plus(c.vamount, c.uamount);
+                    c.vamount = ZhCalc.add(c.vamount, c.uamount);
                 }
             }
         }

+ 2 - 2
app/public/js/stage_change.js

@@ -39,7 +39,7 @@ class ChangeAnalysis {
         change.bills = change.detail.addUsedBills;
         for (const b of change.bills) {
             b.qty = _.toNumber(b.samount);
-            b.valid_qty = ZhCalc.minus(b.qty - b.used_qty);
+            b.valid_qty = ZhCalc.sub(b.qty - b.used_qty);
             b.pos = _.filter(change.detail.curUsedBills, {cbid: b.id});
             b.cur_qty = 0;
             for (const p of b.pos) {
@@ -50,7 +50,7 @@ class ChangeAnalysis {
                     p.leaf_xmj_code = leafXmj.code;
                     p.leaf_xmj_name = leafXmj.name;
                 }
-                b.cur_qty = ZhCalc.plus(b.cur_qty, p.qty);
+                b.cur_qty = ZhCalc.add(b.cur_qty, p.qty);
             }
 
         }

+ 5 - 5
app/public/js/stage_compare.js

@@ -33,14 +33,14 @@ $(document).ready(function () {
 
     function calculateStageLedgerData(datas) {
         for (const d of datas) {
-            d.gather_qty = ZhCalc.plus(d.contract_qty, d.qc_qty);
-            d.gather_tp = ZhCalc.plus(d.contract_tp, d.qc_tp);
+            d.gather_qty = ZhCalc.add(d.contract_qty, d.qc_qty);
+            d.gather_tp = ZhCalc.add(d.contract_tp, d.qc_tp);
         }
     }
     function calculateStagePosData(datas) {
         for (const d of datas) {
-            d.gather_qty = ZhCalc.plus(d.contract_qty, d.qc_qty);
-            d.gather_tp = ZhCalc.plus(d.contract_tp, d.qc_tp);
+            d.gather_qty = ZhCalc.add(d.contract_qty, d.qc_qty);
+            d.gather_tp = ZhCalc.add(d.contract_tp, d.qc_tp);
         }
     }
 
@@ -86,7 +86,7 @@ $(document).ready(function () {
         updateFields: ['contract_qty', 'qc_qty'],
     };
     scPosSetting.calcFun = function (pos) {
-        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
+        pos.gather_qty = ZhCalc.add(pos.contract_qty, pos.qc_qty);
     };
     const scPos = new MasterPosData(scPosSetting);
     scPos.loadDatas(pos);

+ 18 - 18
app/public/js/stage_im.js

@@ -25,17 +25,17 @@ const stageIm = (function () {
     gsTreeSetting.calcFields = ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     gsTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
-            node.pre_gather_qty = ZhCalc.plus(node.pre_contract_qty, node.pre_qc_qty);
-            node.gather_qty = ZhCalc.plus(node.contract_qty, node.qc_qty);
-            node.end_contract_qty = ZhCalc.plus(node.pre_contract_qty, node.contract_qty);
-            node.end_qc_qty = ZhCalc.plus(node.pre_qc_qty, node.qc_qty);
-            node.end_gather_qty = ZhCalc.plus(node.pre_gather_qty, node.gather_qty);
+            node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+            node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+            node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
+            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+            node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
         }
-        node.pre_gather_tp = ZhCalc.plus(node.pre_contract_tp, node.pre_qc_tp);
-        node.gather_tp = ZhCalc.plus(node.contract_tp, node.qc_tp);
-        node.end_contract_tp = ZhCalc.plus(node.pre_contract_tp, node.contract_tp);
-        node.end_qc_tp = ZhCalc.plus(node.pre_qc_tp, node.qc_tp);
-        node.end_gather_tp = ZhCalc.plus(node.pre_gather_tp, node.gather_tp);
+        node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+        node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+        node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
+        node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+        node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
     };
     const gsTree = createNewPathTree('stage', gsTreeSetting);
     const gsPosSetting = {
@@ -43,11 +43,11 @@ const stageIm = (function () {
         updateFields: ['contract_qty', 'qc_qty', 'postil'],
     };
     gsPosSetting.calcFun = function (pos) {
-        pos.pre_gather_qty = ZhCalc.plus(pos.pre_contract_qty, pos.pre_qc_qty);
-        pos.gather_qty = ZhCalc.plus(pos.contract_qty, pos.qc_qty);
-        pos.end_contract_qty = ZhCalc.plus(pos.pre_contract_qty, pos.contract_qty);
-        pos.end_qc_qty = ZhCalc.plus(pos.pre_qc_qty, pos.qc_qty);
-        pos.end_gather_qty = ZhCalc.plus(pos.pre_gather_qty, pos.gather_qty);
+        pos.pre_gather_qty = ZhCalc.add(pos.pre_contract_qty, pos.pre_qc_qty);
+        pos.gather_qty = ZhCalc.add(pos.contract_qty, pos.qc_qty);
+        pos.end_contract_qty = ZhCalc.add(pos.pre_contract_qty, pos.contract_qty);
+        pos.end_qc_qty = ZhCalc.add(pos.pre_qc_qty, pos.qc_qty);
+        pos.end_gather_qty = ZhCalc.add(pos.pre_gather_qty, pos.gather_qty);
     };
     const gsPos = new StagePosData(gsPosSetting);
 
@@ -178,7 +178,7 @@ const stageIm = (function () {
                 lp = {name: p.name, qty: p.quantity};
                 lx.pos.push(lp);
             }
-            lp.jl = ZhCalc.plus(lp.jl, p.gather_qty);
+            lp.jl = ZhCalc.add(lp.jl, p.gather_qty);
         }
     }
 
@@ -202,7 +202,7 @@ const stageIm = (function () {
             };
             im.leafXmjs.push(lx);
         }
-        lx.jl = ZhCalc.plus(lx.jl, node[jlField]);
+        lx.jl = ZhCalc.add(lx.jl, node[jlField]);
         generatePosData(node, lx);
     }
 
@@ -273,7 +273,7 @@ const stageIm = (function () {
                 ImData.push(im);
             }
             generateLeafXmjData(p, im, 'gather_qty');
-            im.jl = ZhCalc.plus(im.jl, p.gather_qty);
+            im.jl = ZhCalc.add(im.jl, p.gather_qty);
         }
     }
 

+ 110 - 0
app/public/js/zh_calc.js

@@ -0,0 +1,110 @@
+'use strict';
+
+/**
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+;const baseCalc = (function () {
+    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);
+    }
+
+    return { digitLength: digitLength, powLength: powLength, round: round, add: add, sub: sub, mul: mul, div: div }
+})();
+
+/**
+ * 计算(四则、舍入) 统一,方便以后置换
+ * @type {{add, sub, mul, div, round}}
+ */
+const ZhCalc = (function () {
+    /**
+     * 加法 num1 + num2
+     * @param num1
+     * @param num2
+     * @returns {number}
+     */
+    function add(num1, num2) {
+        return baseCalc.add(num1 ? num1 : 0, num2 ? num2: 0);
+    };
+    /**
+     * 减法 num1 - num2
+     * @param num1
+     * @param num2
+     * @returns {number}
+     */
+    function sub(num1, num2) {
+        return baseCalc.sub(num1 ? num1 : 0, num2 ? num2 : 0);
+    };
+    /**
+     * 乘法 num1 * num2
+     * @param num1
+     * @param num2
+     * @returns {*}
+     */
+    function mul(num1, num2, digit = 6) {
+        return Decimal.mul(num1 ? num1 : 0, num2 ? num2 : 0).toDecimalPlaces(digit).toNumber();
+    };
+    /**
+     * 除法 num1 / num2
+     * @param num1 - 被除数
+     * @param num2 - 除数
+     * @returns {*}
+     */
+    function div(num1, num2) {
+        if (num2 && !checkZero(num2)) {
+            return Decimal.div(num1 ? num1: 0, num2).toDecimalPlaces(digit).toNumber();
+        } else {
+            return null;
+        }
+    };
+    /**
+     * 四舍五入
+     * @param {Number} value - 舍入的数字
+     * @param {Number} decimal - 要保留的小数位数
+     * @returns {*}
+     */
+    function round(value, decimal) {
+        return value ? Decimal.round(value, decimal).toNumber() : null;
+    };
+    return {plus, minus, times, divide, round}
+});

+ 10 - 10
app/service/ledger.js

@@ -1674,15 +1674,15 @@ module.exports = app => {
                             if (row.deal_qty === undefined) calcData.deal_qty = updateNode.deal_qty;
                             calcData.quantity = this.ctx.helper.sum([calcData.sgfh_qty, calcData.sjcl_qty, calcData.qtcl_qty]);
                             calcData.sgfh_tp = this.ctx.helper.round(
-                                this.ctx.helper.times(calcData.sgfh_qty, calcData.unit_price), info.decimal.tp);
+                                this.ctx.helper.mul(calcData.sgfh_qty, calcData.unit_price), info.decimal.tp);
                             calcData.sjcl_tp = this.ctx.helper.round(
-                                this.ctx.helper.times(calcData.sjcl_qty, calcData.unit_price), info.decimal.tp);
+                                this.ctx.helper.mul(calcData.sjcl_qty, calcData.unit_price), info.decimal.tp);
                             calcData.qtcl_tp = this.ctx.helper.round(
-                                this.ctx.helper.times(calcData.qtcl_qty, calcData.unit_price), info.decimal.tp);
+                                this.ctx.helper.mul(calcData.qtcl_qty, calcData.unit_price), info.decimal.tp);
                             calcData.total_price = this.ctx.helper.round(
-                                this.ctx.helper.times(calcData.quantity, calcData.unit_price), info.decimal.tp);
+                                this.ctx.helper.mul(calcData.quantity, calcData.unit_price), info.decimal.tp);
                             calcData.deal_tp = this.ctx.helper.round(
-                                this.ctx.helper.times(calcData.deal_qty, calcData.unit_price), info.decimal.tp);
+                                this.ctx.helper.mul(calcData.deal_qty, calcData.unit_price), info.decimal.tp);
                         } else if (row.sgfh_tp !== undefined || row.sjcl_tp !== undefined || row.qtcl_tp !== undefined || row.deal_tp !== undefined) {
                             calcData.sgfh_qty = null;
                             calcData.sjcl_qty = null;
@@ -1758,7 +1758,7 @@ module.exports = app => {
                 };
                 child.full_path = parent.full_path + '.' + child.ledger_id;
                 child.total_price = this.ctx.helper.round(
-                    this.ctx.helper.times(child.unit_price, child.quantity), this.ctx.tender.info.decimal.tp);
+                    this.ctx.helper.mul(child.unit_price, child.quantity), this.ctx.tender.info.decimal.tp);
                 tp = this.ctx.helper.add(tp, child.total_price);
                 result.push(child);
                 newIds.push(child.ledger_id);
@@ -1939,10 +1939,10 @@ module.exports = app => {
             data.sjcl_qty = this.round(data.sjcl_qty, precision.value);
             data.qtcl_qty = this.round(data.qtcl_qty, precision.value);
             data.quantity = this.round(data.quantity, precision.value);
-            data.sgfh_tp = this.round(this.ctx.helper.times(data.sgfh_qty, node.unit_price), info.decimal.tp);
-            data.sjcl_tp = this.round(this.ctx.helper.times(data.sjcl_qty, node.unit_price), info.decimal.tp);
-            data.qtcl_tp = this.round(this.ctx.helper.times(data.qtcl_qty, node.unit_price), info.decimal.tp);
-            data.total_price = this.round(this.ctx.helper.times(data.quantity, node.unit_price), info.decimal.tp);
+            data.sgfh_tp = this.round(this.ctx.helper.mul(data.sgfh_qty, node.unit_price), info.decimal.tp);
+            data.sjcl_tp = this.round(this.ctx.helper.mul(data.sjcl_qty, node.unit_price), info.decimal.tp);
+            data.qtcl_tp = this.round(this.ctx.helper.mul(data.qtcl_qty, node.unit_price), info.decimal.tp);
+            data.total_price = this.round(this.ctx.helper.mul(data.quantity, node.unit_price), info.decimal.tp);
             const result = await transaction.update(this.tableName, data);
         }
 

+ 10 - 10
app/service/stage.js

@@ -80,9 +80,9 @@ module.exports = app => {
                 orders: [['order', 'desc']],
             });
             for (const s of stages) {
-                s.tp = this.ctx.helper.plus(s.contract_tp, s.qc_tp);
-                s.pre_tp = this.ctx.helper.plus(s.pre_contract_tp, s.pre_qc_tp);
-                s.end_tp = this.ctx.helper.plus(s.pre_tp, s.tp);
+                s.tp = this.ctx.helper.add(s.contract_tp, s.qc_tp);
+                s.pre_tp = this.ctx.helper.add(s.pre_contract_tp, s.pre_qc_tp);
+                s.end_tp = this.ctx.helper.add(s.pre_tp, s.tp);
             }
             if (stages.length !== 0) {
                 const lastStage = stages[stages.length - 1];
@@ -99,8 +99,8 @@ module.exports = app => {
                     const tpData = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                     stage.contract_tp = tpData.contract_tp;
                     stage.qc_tp = tpData.qc_tp;
-                    stage.tp = this.ctx.helper.plus(stage.contract_tp, stage.qc_tp);
-                    stage.end_tp = this.ctx.helper.plus(stage.pre_tp, stage.tp);
+                    stage.tp = this.ctx.helper.add(stage.contract_tp, stage.qc_tp);
+                    stage.end_tp = this.ctx.helper.add(stage.pre_tp, stage.tp);
                 }
             }
             return stages;
@@ -135,8 +135,8 @@ module.exports = app => {
                 user_id: this.ctx.session.sessionUser.accountId,
             };
             if (preStage) {
-                newStage.pre_contract_tp = this.ctx.helper.plus(preStage.pre_contract_tp, preStage.contract_tp);
-                newStage.pre_qc_tp = this.ctx.helper.plus(preStage.pre_qc_tp, preStage.qc_tp);
+                newStage.pre_contract_tp = this.ctx.helper.add(preStage.pre_contract_tp, preStage.contract_tp);
+                newStage.pre_qc_tp = this.ctx.helper.add(preStage.pre_qc_tp, preStage.qc_tp);
             }
             const transaction = await this.db.beginTransaction();
             try {
@@ -219,7 +219,7 @@ module.exports = app => {
                         cb.value = param.zanLiePrice;
                         break;
                     case 'htjszl':
-                        cb.value = this.ctx.helper.minus(param.contractPrice, param.zanLiePrice);
+                        cb.value = this.ctx.helper.sub(param.contractPrice, param.zanLiePrice);
                         break;
                     case 'kgyfk':
                         cb.value = param.startAdvance;
@@ -229,11 +229,11 @@ module.exports = app => {
                         break;
                     case 'bqwc':
                         const sum = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
-                        cb.value = this.ctx.helper.plus(sum.contract_tp, sum.qc_tp);
+                        cb.value = this.ctx.helper.add(sum.contract_tp, sum.qc_tp);
                         break;
                     case 'ybbqwc':
                         const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGcl(this.ctx.stage, '^1[0-9]{2}-');
-                        cb.value = this.ctx.helper.plus(sumGcl.contract_tp, sumGcl.qc_tp);
+                        cb.value = this.ctx.helper.add(sumGcl.contract_tp, sumGcl.qc_tp);
                         break;
                     default:
                         cb.value = 0;

+ 8 - 8
app/service/stage_bills.js

@@ -114,12 +114,12 @@ module.exports = app => {
             if (insertData.contract_qty) {
                 d.contract_qty = this.round(insertData.contract_qty, precision.value);
                 d.contract_tp = this.round(
-                    this.ctx.helper.times(d.contract_qty, ledgerData.unit_price), info.decimal.tp);
+                    this.ctx.helper.mul(d.contract_qty, ledgerData.unit_price), info.decimal.tp);
             }
             if (insertData.qc_qty) {
                 d.qc_qty = this.round(insertData.qc_qty, precision.value);
                 d.qc_tp = this.round(
-                    this.ctx.helper.times(d.qc_qty, ledgerData.unit_price), info.decimal.tp);
+                    this.ctx.helper.mul(d.qc_qty, ledgerData.unit_price), info.decimal.tp);
             }
             if (insertData.postil) {
                 d.postil = insertData.postil;
@@ -143,11 +143,11 @@ module.exports = app => {
                     const precision = this.ctx.helper.findPrecision(info.precision, ledgerBills.unit);
                     if (d.contract_qty !== undefined) {
                         d.contract_qty = this.round(d.contract_qty, precision.value);
-                        d.contract_tp = this.round(this.ctx.helper.times(d.contract_qty, ledgerBills.unit_price), info.decimal.tp);
+                        d.contract_tp = this.round(this.ctx.helper.mul(d.contract_qty, ledgerBills.unit_price), info.decimal.tp);
                     }
                     if (d.qc_qty !== undefined) {
                         d.qc_qty = this.round(d.qc_qty, precision.value);
-                        d.qc_tp = this.round(this.ctx.helper.times(d.qc_qty, ledgerBills.unit_price), info.decimal.tp);
+                        d.qc_tp = this.round(this.ctx.helper.mul(d.qc_qty, ledgerBills.unit_price), info.decimal.tp);
                     }
                     if (!stageBills) {
                         d.tid = this.ctx.tender.id;
@@ -184,11 +184,11 @@ module.exports = app => {
             const updateData = {};
             if (data.contract_qty) {
                 updateData.contract_qty = this.round(data.contract_qty, precision.value);
-                updateData.contract_tp = this.round(this.ctx.helper.times(updateData.contract_qty, ledgerBills.unit_price), info.decimal.tp);
+                updateData.contract_tp = this.round(this.ctx.helper.mul(updateData.contract_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (data.qc_qty) {
                 updateData.qc_qty = this.round(data.qc_qty, precision.value);
-                updateData.qc_tp = this.round(this.ctx.helper.times(updateData.qc_qty, ledgerBills.unit_price), info.decimal.tp);
+                updateData.qc_tp = this.round(this.ctx.helper.mul(updateData.qc_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (stageBills) {
                 if ((updateData.contract_qty === undefined || stageBills.contract_qty !== updateData.contract_qty) ||
@@ -226,11 +226,11 @@ module.exports = app => {
             // 计算
             if (posGather.contract_qty !== undefined) {
                 posGather.contract_qty = this.round(posGather.contract_qty, precision.value);
-                posGather.contract_tp = this.round(this.ctx.helper.times(posGather.contract_qty, ledgerBills.unit_price), info.decimal.tp);
+                posGather.contract_tp = this.round(this.ctx.helper.mul(posGather.contract_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (posGather.qc_qty !== undefined) {
                 posGather.qc_qty = this.round(posGather.qc_qty, precision.value);
-                posGather.qc_tp = this.round(this.ctx.helper.times(posGather.qc_qty, ledgerBills.unit_price), info.decimal.tp);
+                posGather.qc_tp = this.round(this.ctx.helper.mul(posGather.qc_qty, ledgerBills.unit_price), info.decimal.tp);
             }
             if (stageBills) {
                 if (stageBills.contract_qty === posGather.contract_qty && stageBills.qc_qty === posGather.qc_qty) {

+ 6 - 6
app/service/stage_change.js

@@ -105,7 +105,7 @@ module.exports = app => {
                 if (!nc || nc.qty !== oc.qty) {
                     const qty = nc ? this.round(nc.qty, precision.value) : null;
                     const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty);
-                    billsQty = this.ctx.helper.plus(billsQty, change.qty);
+                    billsQty = this.ctx.helper.add(billsQty, change.qty);
                     if (oc.stimes === this.ctx.stage.curTimes && oc.sorder === this.ctx.stage.curOrder) {
                         change.id = oc.id;
                         updateChanges.push(change);
@@ -113,14 +113,14 @@ module.exports = app => {
                         newChanges.push(change);
                     }
                 } else {
-                    billsQty = this.ctx.helper.plus(billsQty, oc.qty);
+                    billsQty = this.ctx.helper.add(billsQty, oc.qty);
                 }
             }
             for (const c of changes) {
                 const nc = this._.find(oldChanges, {cid: c.cid, cbid: c.cbid});
                 if (!nc) {
                     const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value));
-                    billsQty = this.ctx.helper.plus(billsQty, change.qty);
+                    billsQty = this.ctx.helper.add(billsQty, change.qty);
                     newChanges.push(change);
                 }
             }
@@ -180,7 +180,7 @@ module.exports = app => {
                 if (!nc || nc.qty !== oc.qty) {
                     const qty = nc ? this.round(nc.qty, precision.value) : null;
                     const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty);
-                    posQty = this.ctx.helper.plus(posQty, change.qty);
+                    posQty = this.ctx.helper.add(posQty, change.qty);
                     if (oc.stimes === this.ctx.stage.curTimes && oc.sorder === this.ctx.stage.curOrder) {
                         change.id = oc.id;
                         updateChanges.push(change);
@@ -188,14 +188,14 @@ module.exports = app => {
                         newChanges.push(change);
                     }
                 } else {
-                    posQty = this.ctx.helper.plus(posQty, oc.qty);
+                    posQty = this.ctx.helper.add(posQty, oc.qty);
                 }
             }
             for (const c of changes) {
                 const nc = this._.find(oldChanges, {cid: c.cid, cbid: c.cbid});
                 if (!nc) {
                     const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value));
-                    posQty = this.ctx.helper.plus(posQty, change.qty);
+                    posQty = this.ctx.helper.add(posQty, change.qty);
                     newChanges.push(change);
                 }
             }

+ 1 - 0
app/view/change/info.ejs

@@ -760,6 +760,7 @@
     const pos = JSON.parse('<%- JSON.stringify(pos) %>');
     const dealBillList = JSON.parse('<%- JSON.stringify(dealBillList) %>');
 </script>
+<script src="/public/js/zh_calc.js"></script>
 <script src="/public/js/path_tree.js"></script>
 <script src="/public/js/gcl_gather.js"></script>
 <script src="/public/js/jquery/jquery.form.min.js"></script>

+ 16 - 0
config/web.js

@@ -98,10 +98,12 @@ const JsFiles = {
                     "/public/js/js-xlsx/xlsx.full.min.js",
                     "/public/js/js-xlsx/xlsx.utils.js",
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/ledger_tree_col.js",
                     "/public/js/ledger.js",
@@ -111,10 +113,12 @@ const JsFiles = {
             audit: {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/ledger_audit.js",
                 ],
@@ -126,10 +130,12 @@ const JsFiles = {
             index: {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/stage.js",
                     "/public/js/stage_audit.js",
@@ -139,11 +145,13 @@ const JsFiles = {
             detail: {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                     "/public/js/html2canvas/html2canvas.min.js",
                     "/public/js/html2canvas/canvas2image.js",
                 ],
                 mergeFiles: [
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/stage_im.js",
                     "/public/js/stage_detail.js",
@@ -165,10 +173,12 @@ const JsFiles = {
             change: {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/stage_change.js",
                 ],
@@ -176,12 +186,16 @@ const JsFiles = {
             },
             gather: {
                 files: [
+                    "/public/js/decimal.min.js",
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/gcl_gather.js",
                     "/public/js/stage_gather.js",
                 ],
@@ -190,10 +204,12 @@ const JsFiles = {
             compare: {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/stage_compare.js",
                 ],

+ 1 - 0
package.json

@@ -5,6 +5,7 @@
   "private": true,
   "dependencies": {
     "bignumber.js": "^8.1.1",
+    "decimal.js": "^10.2.0",
     "egg": "^1.13.0",
     "egg-js-validator": "^1.0.2",
     "egg-mysql": "^3.0.0",

+ 7 - 5
test/app/extend/helper.test.js

@@ -11,6 +11,7 @@ const { app, assert } = require('egg-mock/bootstrap');
 const _ = require('lodash');
 const math = require('mathjs');
 const np = require('number-precision');
+const decimal = require('decimal.js');
 
 describe('test/app/extend/helper.test.js', () => {
 
@@ -126,9 +127,10 @@ describe('test/app/extend/helper.test.js', () => {
 
     it('test arithmetic', function () {
         const ctx = app.mockContext();
-        assert(ctx.helper.plus(0.1, 0.2) === 0.3);
-        assert(ctx.helper.minus(0.3, 0.2) === 0.1);
-        assert(ctx.helper.times(0.07, 10) === 0.7);
-        assert(ctx.helper.divide(0.32, 0.2) === 1.6);
-    })
+        assert(ctx.helper.add(0.1, 0.2) === 0.3);
+        assert(ctx.helper.add(43223423.23423, -423423) === 42800000.23423);
+        assert(ctx.helper.sub(0.3, 0.2) === 0.1);
+        assert(ctx.helper.mul(0.07, 10) === 0.7);
+        assert(ctx.helper.div(0.32, 0.2) === 1.6);
+    });
 });

+ 2 - 2
test/app/service/ledger.test.js

@@ -577,7 +577,7 @@ describe('test/app/service/ledger.test.js', () => {
         // 修改202-2-e(1-1-1下)(id=12)的quantity为2.00000001, unit_price位3.0000005
         const qty = 2.00000001, fQty = ctx.helper.round(qty, ctx.tender.info.precision.other.value);
         const up = 3.0000005, fUp = ctx.helper.round(up, ctx.tender.info.decimal.up);
-        const tp = 6.00000103, fTp = ctx.helper.times(fQty, fUp);
+        const tp = 6.00000103, fTp = ctx.helper.mul(fQty, fUp);
         const node1 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 12);
         assert(node1);
         const resultData = yield ctx.service.ledger.updateCalc(ctx.tender.id, {
@@ -637,7 +637,7 @@ describe('test/app/service/ledger.test.js', () => {
             fUp.push(ctx.helper.round(p, ctx.tender.info.decimal.up));
         }
         for (const i in qty) {
-            fTp.push(ctx.helper.times(fQty[i], fUp[i]));
+            fTp.push(ctx.helper.mul(fQty[i], fUp[i]));
         }
 
         const node1 = yield ctx.service.ledger.getDataByNodeId(ctx.tender.id, 11);