瀏覽代碼

1. 超计判断调整
2. 动态投资,配置相关标段相关
3. 所有计算式,替换%调整

MaiXinRong 7 月之前
父節點
當前提交
de11abdd60

+ 20 - 2
app/const/tender_info.js

@@ -8,8 +8,9 @@
  * @version
  */
 
-const parseInfo = ['deal_info', 'construction_unit', 'tech_param', 'decimal', 'precision', 'deal_param', 'display', 'pay_account', 'shenpi', 'bid_info', 'ledger_check', 'fun_rela'];
+const parseInfo = ['deal_info', 'construction_unit', 'tech_param', 'decimal', 'precision', 'deal_param', 'display', 'pay_account', 'shenpi', 'bid_info', 'ledger_check', 'fun_rela', 'over_range_check'];
 const arrayInfo = ['chapter'];
+
 const defaultInfo = {
     // 合同信息
     deal_info: {
@@ -209,14 +210,21 @@ const defaultInfo = {
             show: false,
         },
     },
+    over_range_check: {
+        field: 'tz', // 'deal', 'both',
+        percent: 100,
+        billsWithPos: 'pos', // 'bills', 'both',
+    },
 };
 const gclDefaultInfo = (function () {
     const result = JSON.parse(JSON.stringify(defaultInfo));
     result.display.ledger.deal = true;
+    result.over_range_check = { field: 'deal', percent: 100, billsWithPos: 'bills'};
     return result;
 })(defaultInfo);
 const tzDefaultInfo = (function () {
     const result = JSON.parse(JSON.stringify(defaultInfo));
+    result.over_range_check = { field: 'tz', percent: 100, billsWithPos: 'both'};
     return result;
 })(defaultInfo);
 const paymentDefaultInfo = (function () {
@@ -225,10 +233,19 @@ const paymentDefaultInfo = (function () {
     result.construction_unit = JSON.parse(JSON.stringify(defaultInfo.construction_unit));
     result.tech_param = JSON.parse(JSON.stringify(defaultInfo.tech_param));
     result.pay_account = JSON.parse(JSON.stringify(defaultInfo.pay_account));
-
     return result;
 })(defaultInfo);
 
+const transOverRangeCheck = function(helper, check) {
+    const result = {};
+    result.coe = helper.div(check.percent, 100);
+    result.checkTz = check.field === 'tz' || check.field === 'both';
+    result.checkDeal = check.field === 'deal' || check.field === 'both';
+    result.hasPosCheckBills = check.billsWithPos === 'bills' || check.billsWithPos === 'both';
+    result.hasPosCheckPos = check.billsWithPos === 'pos' || check.billsWithPos === 'both';
+    return result;
+};
+
 module.exports = {
     parseInfo,
     arrayInfo,
@@ -236,4 +253,5 @@ module.exports = {
     gclDefaultInfo,
     tzDefaultInfo,
     paymentDefaultInfo,
+    transOverRangeCheck,
 };

+ 3 - 1
app/controller/stage_controller.js

@@ -465,7 +465,9 @@ module.exports = app => {
                 await this.ctx.service.s2bProj.refreshSessionS2b();
                 checkData.check3fLimit(ctx.tender.data);
 
-                projRela.banOver && ctx.tender.info.ledger_check.over && checkData.checkOverRange(['contract_qty', 'qc_qty']);
+                if (projRela.banOver && ctx.tender.info.ledger_check.over) {
+                    checkData.checkOverRange(ctx.tender.info.checkOverInfo);
+                }
                 checkData.checkBillsTp([
                     { qty: 'contract_qty', tp: 'contract_tp' }, { qty: 'qc_qty', tp: 'qc_tp' },
                 ], this.ctx.tender.info.decimal, x => { return x.is_tp; });

+ 1 - 1
app/controller/tender_controller.js

@@ -682,7 +682,7 @@ module.exports = app => {
         async saveTenderInfo2(ctx) {
             try {
                 const data = JSON.parse(ctx.request.body.data);
-                if (!data || (!data.ledger_check && !data.fun_rela && !data.s_type)) throw '提交数据错误';
+                if (!data || (!data.ledger_check && !data.fun_rela && !data.s_type && !data.over_range_check)) throw '提交数据错误';
                 if (!ctx.session.sessionUser.is_admin) throw '您无权修改该内容';
 
                 const updateData = {};

+ 1 - 1
app/extend/helper.js

@@ -1409,7 +1409,7 @@ module.exports = {
     },
 
     calcExpr(expr) {
-        const validExpr = expr.replace('=', '').replace('%', '/100');
+        const validExpr = expr.replace('=', '').replace(new RegExp('%', 'gm'), '/100');
         return parseFloat(math.eval(validExpr));
     },
 

+ 54 - 22
app/lib/ledger.js

@@ -975,41 +975,73 @@ class checkData {
             }
         }
     }
-    _checkPosOverRange(p) {
+    _checkPosOverRangeTz(p, coe) {
         const end_contract_qty = this.ctx.helper.add(p.pre_contract_qty, p.contract_qty);
-        if (!p.quantity) return !!end_contract_qty;
-        return p.quantity > 0
-            ? end_contract_qty > p.final_1_qty
-            : (p.final_1_qty > 0 ? true : end_contract_qty < p.final_1_qty || end_contract_qty > 0);
+        const base_qty = p.quantity;
+        const compare_qty = this.ctx.helper.mul(p.final_1_qty, coe);
+        if (!base_qty) return !!end_contract_qty;
+        return base_qty > 0
+            ? end_contract_qty > compare_qty
+            : (compare_qty > 0 ? true : end_contract_qty < compare_qty || end_contract_qty > 0);
     }
-    _checkBillsOverRange(bills, posRange, isTz) {
-        if (isTz && posRange.length > 0) {
-            for (const p of posRange) {
-                if (this._checkPosOverRange(p)) return true;
-            }
+    _checkPosOverRange(p, checkInfo) {
+        const checkTz = checkInfo.checkTz ? this._checkPosOverRangeTz(p, checkInfo.coe) : false;
+        const checkDeal = false;
+        return checkTz || checkDeal;
+    }
+    _checkBillsOverRangeTz(bills, coe) {
+        const end_contract_qty = this.ctx.helper.add(bills.contract_qty, bills.pre_contract_qty);
+        const end_contract_tp = this.ctx.helper.add(bills.contract_tp, bills.pre_contract_tp);
+        if (bills.is_tp) {
+            const base_tp = bills.total_price;
+            const compare_tp = this.ctx.helper.mul(base_tp, coe);
+            if (!base_tp) return !!end_contract_tp;
+            return base_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;
+        } else {
+            const base_qty = bills.quantity;
+            const compare_qty = this.ctx.helper.mul(bills.final_1_qty, coe);
+            if (!base_qty) return !!end_contract_qty;
+            return base_qty > 0
+                ? end_contract_qty > compare_qty
+                : (compare_qty > 0 ? true : end_contract_qty < compare_qty || end_contract_qty > 0);
         }
+    }
+    _checkBillsOverRangeDeal(bills, coe) {
         const end_contract_qty = this.ctx.helper.add(bills.contract_qty, bills.pre_contract_qty);
         const end_contract_tp = this.ctx.helper.add(bills.contract_tp, bills.pre_contract_tp);
         if (bills.is_tp) {
-            const compare_tp = isTz ? bills.total_price : bills.deal_tp;
-            if (!compare_tp) return !!end_contract_tp;
-            return compare_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;
+            const base_tp = bills.deal_tp;
+            const compare_tp = this.ctx.helper.mul(base_tp, coe);
+            if (!base_tp) return !!end_contract_tp;
+            return base_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;
         } else {
-            const compare_qty1 = isTz ? bills.quantity : bills.deal_qty;
-            const compare_qty2 = isTz ? bills.final_1_qty : bills.deal_final_1_qty;
-            if (!compare_qty1) return !!end_contract_qty;
-            return compare_qty1 > 0
-                ? end_contract_qty > compare_qty2
-                : (compare_qty2 > 0 ? true : end_contract_qty < compare_qty2 || end_contract_qty > 0);
+            const base_qty = bills.deal_qty;
+            const compare_qty = this.ctx.helper.mul(bills.deal_final_1_qty, coe);
+            if (!base_qty) return !!end_contract_qty;
+            return base_qty > 0
+                ? end_contract_qty > compare_qty
+                : (compare_qty > 0 ? true : end_contract_qty < compare_qty || end_contract_qty > 0);
+        }
+    }
+    _checkBillsOverRange(bills, posRange, checkInfo) {
+        if (checkInfo.hasPosCheckPos && posRange.length > 0) {
+            for (const p of posRange) {
+                if (this._checkPosOverRange(p, checkInfo)) return true;
+            }
+        }
+        if (checkInfo.hasPosCheckBills || posRange.length === 0) {
+            const checkTz = checkInfo.checkTz ? this._checkBillsOverRangeTz(bills, checkInfo.coe) : false;
+            const checkDeal = checkInfo.checkDeal ? this._checkBillsOverRangeDeal(bills, checkInfo.coe) : false;
+            return checkTz || checkDeal;
         }
+        return false;
     }
-    checkOverRange() {
-        const isTz = this.ctx.tender.data.measure_type === this.measureType.tz.value;
+    checkOverRange(checkInfo) {
         for (const b of this.checkBills.nodes) {
             if (b.children && b.children.length > 0) continue;
             const pr = this.checkPos.getLedgerPos(b.id) || [];
 
-            if (this._checkBillsOverRange(b, pr, isTz)) {
+            if (this._checkBillsOverRange(b, pr, checkInfo)) {
                 this.checkResult.error.push({
                     ledger_id: b.ledger_id,
                     b_code: b.b_code,

+ 1 - 1
app/lib/material_calc.js

@@ -48,7 +48,7 @@ class MaterialCalculate {
             const percent = formula.match(this.percentReg);
             if (percent) {
                 for (const p of percent) {
-                    const v = math.eval(p.replace('%', '/100'));
+                    const v = math.eval(p.replace(new RegExp('%', 'gm'), '/100'));
                     formula = formula.replace(p, v);
                 }
             }

+ 2 - 2
app/lib/pay_calc.js

@@ -80,7 +80,7 @@ class PayCalculate {
         const percent = formula.match(this.percentReg);
         if (percent) {
             for (const p of percent) {
-                const v = math.eval(p.replace('%', '/100'));
+                const v = math.eval(p.replace(new RegExp('%', 'gm'), '/100'));
                 formula = formula.replace(p, v);
             }
         }
@@ -105,7 +105,7 @@ class PayCalculate {
         const percent = formula.match(this.percentReg);
         if (percent) {
             for (const p of percent) {
-                const v = math.eval(p.replace('%', '/100'));
+                const v = math.eval(p.replace(new RegExp('%', 'gm'), '/100'));
                 formula = formula.replace(p, v);
             }
         }

+ 2 - 2
app/lib/ybp_tree.js

@@ -216,8 +216,8 @@ class YbpImportTree {
     sortChildren(children, recursive) {
         children.sort((x, y) => {
             return x.kind === YbpNodeKind.bill
-                ? (x.b_code ? x.b_code.localeCompare(y.b_code) : -1)
-                : (x.code ? x.code.localeCompare(y.code) : -1);
+                ? (x.b_code ? (y.b_code ? x.b_code.localeCompare(y.b_code) : 1) : -1)
+                : (x.code ? (y.code ? x.code.localeCompare(y.code) : -1) : 1);
         });
         children.forEach((c, i) => { c.order = i + 1; });
 

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

@@ -936,7 +936,7 @@ $(document).ready(() => {
                     const [valid, msg] = this._checkExprValid(expr);
                     if (!valid) return [valid, msg];
                     data.expr = expr;
-                    data.quantity = ZhCalc.calcExpr.calcExprStrRpn(expr.replace('%', '/100'));
+                    data.quantity = ZhCalc.calcExpr.calcExprStrRpn(expr.replace(new RegExp('%', 'gm'), '/100'));
                     // const ce = new CalcEvalMin();
                     // data.quantity = ce.eval(expr);
                     // console.log(data.quantity);

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

@@ -25,7 +25,7 @@ function getExprInfo (field, converse = false) {
     return converse ?  _.find(exprField, {expr: field}) : _.find(exprField, {qty: field});
 }
 function transExpr(expr) {
-    return $.trim(expr).replace('\t', '').replace('=', '').replace('%', '/100');
+    return $.trim(expr).replace('\t', '').replace('=', '').replace(new RegExp('%', 'gm'), '/100');
 }
 const copyBlockTag = 'zh.calc.copyBlock';
 const dskCompilation = 'zh.calc.dskCompilation';

+ 60 - 28
app/public/js/global.js

@@ -1033,38 +1033,70 @@ $.fn.extend({
 });
 
 const checkUtils = {
-    posOver(data) {
-        if (!data) return false;
-        if (!data.quantity) return !!data.end_contract_qty;
-        return data.quantity > 0
-            ? data.end_contract_qty > data.final_1_qty
-            : (data.final_1_qty > 0 ? true : data.end_contract_qty < data.final_1_qty || data.end_contract_qty > 0);
+    _checkPosOverRangeTz(p, coe) {
+        const end_contract_qty = ZhCalc.add(p.pre_contract_qty, p.contract_qty);
+        const base_qty = p.quantity;
+        const compare_qty = ZhCalc.mul(p.final_1_qty, coe);
+        if (!base_qty) return !!end_contract_qty;
+        return base_qty > 0
+            ? end_contract_qty > compare_qty
+            : (compare_qty > 0 ? true : end_contract_qty < compare_qty || end_contract_qty > 0);
     },
-    billsOver(data, isTz, relaPos) {
-        if (!data) return false;
-        if (isTz) {
-            const posRange = relaPos.ledgerPos[itemsPre + data.id] || [];
-            if (posRange.length > 0) {
-                for (const p of posRange) {
-                    if (checkUtils.posOver(p)) return true;
-                }
-            }
+    _checkBillsOverRangeTz(bills, coe) {
+        const end_contract_qty = ZhCalc.add(bills.contract_qty, bills.pre_contract_qty);
+        const end_contract_tp = ZhCalc.add(bills.contract_tp, bills.pre_contract_tp);
+        if (bills.is_tp) {
+            const base_tp = bills.total_price;
+            const compare_tp = ZhCalc.mul(base_tp, coe);
+            if (!base_tp) return !!end_contract_tp;
+            return base_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;
+        } else {
+            const base_qty = bills.quantity;
+            const compare_qty = ZhCalc.mul(bills.final_1_qty, coe);
+            if (!base_qty) return !!end_contract_qty;
+            return base_qty > 0
+                ? end_contract_qty > compare_qty
+                : (compare_qty > 0 ? true : end_contract_qty < compare_qty || end_contract_qty > 0);
         }
-
-        if (data.is_tp) {
-            const compare_tp = isTz ? data.total_price : data.deal_tp;
-            if (!compare_tp) return !!data.end_contract_tp;
-            return compare_tp > 0
-                ? data.end_contract_tp > compare_tp
-                : data.end_contract_tp < compare_tp || data.end_contract_tp > 0;
+    },
+    _checkBillsOverRangeDeal(bills, coe) {
+        const end_contract_qty = ZhCalc.add(bills.contract_qty, bills.pre_contract_qty);
+        const end_contract_tp = ZhCalc.add(bills.contract_tp, bills.pre_contract_tp);
+        if (bills.is_tp) {
+            const base_tp = bills.deal_tp;
+            const compare_tp = ZhCalc.mul(base_tp, coe);
+            if (!base_tp) return !!end_contract_tp;
+            return base_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;
         } else {
-            const compare_qty1 = isTz ? data.quantity : data.deal_qty;
-            const compare_qty2 = isTz ? data.final_1_qty : data.deal_final_1_qty;
-            if (!compare_qty1) return !!data.end_contract_qty;
-            return compare_qty1 > 0
-                ? data.end_contract_qty > compare_qty2
-                : (compare_qty2 > 0 ? true : data.end_contract_qty < compare_qty2 || data.end_contract_qty > 0);
+            const base_qty = bills.deal_qty;
+            const compare_qty = ZhCalc.mul(bills.deal_final_1_qty, coe);
+            if (!base_qty) return !!end_contract_qty;
+            return base_qty > 0
+                ? end_contract_qty > compare_qty
+                : (compare_qty > 0 ? true : end_contract_qty < compare_qty || end_contract_qty > 0);
+        }
+    },
+    posOver(pos, checkInfo) {
+        if (!pos) return false;
+        const checkTz = checkInfo.checkTz ? this._checkPosOverRangeTz(pos, checkInfo.coe) : false;
+        const checkDeal = false;
+        return checkTz || checkDeal;
+    },
+    billsOver(bills, relaPos, checkInfo) {
+        if (!bills) return false;
+
+        const posRange = relaPos.ledgerPos[itemsPre + bills.id] || [];
+        if (checkInfo.hasPosCheckPos && posRange.length > 0) {
+            for (const p of posRange) {
+                if (this.posOver(p, checkInfo)) return true;
+            }
+        }
+        if (checkInfo.hasPosCheckBills || posRange.length === 0) {
+            const checkTz = checkInfo.checkTz ? this._checkBillsOverRangeTz(bills, checkInfo.coe) : false;
+            const checkDeal = checkInfo.checkDeal ? this._checkBillsOverRangeDeal(bills, checkInfo.coe) : false;
+            return checkTz || checkDeal;
         }
+        return false;
     },
     compareCode(str1, str2, symbol = '-') {
         if (!str1) {

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

@@ -33,7 +33,7 @@ function getExprInfo (field, converse = false) {
     return _.find(exprField, {qty: field});
 }
 function transExpr(expr) {
-    return expr.replace('=', '').replace('%', '/100');
+    return expr.replace('=', '').replace(new RegExp('%', 'gm'), '/100');
 }
 const checkOption = {
     sibling: { enable: 1 },

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

@@ -152,7 +152,7 @@ const ledgerCheckUtil = {
         for (const node of ledgerTree.nodes) {
             if (node.children && node.children.length > 0) continue;
 
-            if (checkUtils.billsOver(node, option.isTz, ledgerPos)) error.push(node);
+            if (checkUtils.billsOver(node, ledgerPos, option.checkInfo)) error.push(node);
         }
         return error;
     },

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

@@ -903,7 +903,7 @@ $(document).ready(() => {
                         const [valid, msg] = this._checkExprValid(expr);
                         if (!valid) return [valid, msg];
                         data.expr = expr;
-                        data.quantity = ZhCalc.calcExpr.calcExprStrRpn(expr.replace('%', '/100'));
+                        data.quantity = ZhCalc.calcExpr.calcExprStrRpn(expr.replace(new RegExp('%', 'gm'), '/100'));
                     }
                 } else {
                     data.quantity = 0;

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

@@ -1801,7 +1801,7 @@ $(document).ready(() => {
                         const [valid, msg] = this._checkExprValid(expr);
                         if (!valid) return [valid, msg];
                         data.expr = expr;
-                        data.quantity = ZhCalc.calcExpr.calcExprStrRpn(expr.replace('%', '/100'));
+                        data.quantity = ZhCalc.calcExpr.calcExprStrRpn(expr.replace(new RegExp('%', 'gm'), '/100'));
                         // const ce = new CalcEvalMin();
                         // data.quantity = ce.eval(expr);
                         // console.log(data.quantity);

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

@@ -25,7 +25,7 @@ function getExprInfo (field, converse = false) {
     return converse ?  _.find(exprField, {expr: field}) : _.find(exprField, {qty: field});
 }
 function transExpr(expr) {
-    return $.trim(expr).replace('\t', '').replace('=', '').replace('%', '/100');
+    return $.trim(expr).replace('\t', '').replace('=', '').replace(new RegExp('%', 'gm'), '/100');
 }
 const copyBlockTag = 'zh.calc.copyBlock';
 const checkOption = {

+ 1 - 1
app/public/js/shares/tree_expr_calc.js

@@ -194,7 +194,7 @@ const TreeExprCalc = (function(){
                 formula = formula.replace(ip, getIdParamValue(ip));
             }
         }
-        if (formula.indexOf('%') >= 0) formula = formula.replace('%', '/100');
+        if (formula.indexOf('%') >= 0) formula = formula.replace(new RegExp('%', 'gm'), '/100');
         return [formula, math.evaluate(formula)];
     };
     const addCache = function(expr) {

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

@@ -13,7 +13,7 @@ function checkTzMeasureType () {
 }
 
 function transExpr(expr) {
-    return $.trim(expr).replace('\t', '').replace('=', '').replace('%', '/100');
+    return $.trim(expr).replace('\t', '').replace('=', '').replace(new RegExp('%', 'gm'), '/100');
 }
 function getExprInfo (field) {
     const exprField = [

+ 5 - 7
app/public/js/stage.js

@@ -13,7 +13,7 @@ function checkTzMeasureType () {
 }
 
 function transExpr(expr) {
-    return $.trim(expr).replace('\t', '').replace('=', '').replace('%', '/100');
+    return $.trim(expr).replace('\t', '').replace('=', '').replace(new RegExp('%', 'gm'), '/100');
 }
 function getExprInfo (field) {
     const exprField = [
@@ -249,7 +249,7 @@ $(document).ready(() => {
                 return node.is_tp;
             }
         },
-        over: { enable: 1, isTz: checkTzMeasureType(), },
+        over: { enable: 1, isTz: checkTzMeasureType(), checkInfo: tenderInfo.checkOverInfo },
         limit3f: { enable: 1, checkType: [], status: thirdParty, },
         minus_cb: { enable: hintMinusCb },
         // change_over: { enable: 1 },
@@ -749,7 +749,7 @@ $(document).ready(() => {
             if (data.settle_status === settleStatus.finish) {
                 return spreadColor.stage.settle;
             }
-            return hintOver && checkUtils.billsOver(data, checkTzMeasureType(), stagePos) ? spreadColor.stage.over : defaultColor;
+            return hintOver && checkUtils.billsOver(data, stagePos, tenderInfo.checkOverInfo) ? spreadColor.stage.over : defaultColor;
         } else {
             return defaultColor;
         }
@@ -841,9 +841,7 @@ $(document).ready(() => {
                 return spreadColor.stage.settle;
             }
         }
-        if (checkTzMeasureType()) {
-            return hintOver && checkUtils.posOver(data)  ? spreadColor.stage.over : defaultColor;
-        }
+        return hintOver && checkUtils.posOver(data, tenderInfo.checkOverInfo)  ? spreadColor.stage.over : defaultColor;
     };
     sjsSettingObj.setGridSelectStyle(posSpreadSetting);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(posSpreadSetting);
@@ -4544,7 +4542,7 @@ $(document).ready(() => {
                         }, {
                             key: 'over', title: '超计', valid: true,
                             check: function (node) {
-                                return checkUtils.billsOver(node, checkTzMeasureType(), stagePos);
+                                return checkUtils.billsOver(node, stagePos, tenderInfo.checkOverInfo);
                             }
                         }, {
                             key: 'empty', title: '漏计', valid: false,

+ 24 - 26
app/public/js/stage_gather.js

@@ -45,13 +45,13 @@ function generateChapterHtml(data) {
 
 $(document).ready(function () {
     const preUrl = window.location.pathname.split('/').slice(0, 6).join('/');
-    let per = _.toNumber(getLocalCache('StageGatherOverPercent'));
-    if (per && !_.isNaN(per)) {
-        $('#over-percent').val(per >= 50 ? (per <= 100 ? per : 100) : 50);
-    }
-
-    let overType = $('#' + getLocalCache('StageGatherOverType'))[0];
-    if (overType) overType.checked = true;
+    // let per = _.toNumber(getLocalCache('StageGatherOverPercent'));
+    // if (per && !_.isNaN(per)) {
+    //     $('#over-percent').val(per >= 50 ? (per <= 100 ? per : 100) : 50);
+    // }
+    //
+    // let overType = $('#' + getLocalCache('StageGatherOverType'))[0];
+    // if (overType) overType.checked = true;
     autoFlashHeight();
     // 初始化工程量清单
     const gclSpread = SpreadJsObj.createNewSpread($('#gcl-spread')[0]);
@@ -165,14 +165,12 @@ $(document).ready(function () {
                     : data.end_contract_tp < ZhCalc.mul(data[tpField], per) || data.end_contract_tp > 0;
             }
         };
-        const bQty = $('#customRadio1')[0].checked, bDealQty = $('#customRadio2')[0].checked;
-        const nPercent = Math.min(Math.max(ZhCalc.div(parseFloat($('#over-percent').val()), 100), 0.5), 1);
+        const nPercent = checkOverInfo.coe;
         for (const node of data) {
             if (node) {
-                if (node.b_code === '103-4')console.log(node);
-                const bOverRangeTz = billsGatherOver(node, 'final_1_qty', 'final_1_tp', nPercent);
-                const bOverRangeDeal = billsGatherOver(node, 'deal_final_1_qty', 'deal_final_1_tp', nPercent);
-                node.overRange = bQty ? bOverRangeTz : (bDealQty ? bOverRangeDeal : bOverRangeTz || bOverRangeDeal);
+                const bOverRangeTz = checkOverInfo.checkTz ? billsGatherOver(node, 'final_1_qty', 'final_1_tp', nPercent) : false;
+                const bOverRangeDeal = checkOverInfo.checkDeal ? billsGatherOver(node, 'deal_final_1_qty', 'deal_final_1_tp', nPercent) : false;
+                node.overRange = bOverRangeTz || bOverRangeDeal;
             }
         }
     }
@@ -181,19 +179,19 @@ $(document).ready(function () {
         const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
         if (iNewRow !== iOldRow) loadRelaData(iNewRow);
     });
-    $('.custom-radio').click(() => {
-        setLocalCache('StageGatherOverType', $('input[name=customRadio]:checked').attr('id'));
-        checkOverRange(gclGatherData);
-        SpreadJsObj.reLoadSheetData(gclSpread.getActiveSheet());
-        // 收起菜单
-        $('.dropdown-menu').click();
-    });
-    $('#over-percent').change(function () {
-        this.value = this.value >= 50 ? (this.value <= 100 ? ZhCalc.round(this.value, 2) : 100) : 50;
-        setLocalCache('StageGatherOverPercent', this.value);
-        checkOverRange(gclGatherData);
-        SpreadJsObj.reLoadSheetData(gclSpread.getActiveSheet());
-    });
+    // $('.custom-radio').click(() => {
+    //     setLocalCache('StageGatherOverType', $('input[name=customRadio]:checked').attr('id'));
+    //     checkOverRange(gclGatherData);
+    //     SpreadJsObj.reLoadSheetData(gclSpread.getActiveSheet());
+    //     // 收起菜单
+    //     $('.dropdown-menu').click();
+    // });
+    // $('#over-percent').change(function () {
+    //     this.value = this.value >= 50 ? (this.value <= 100 ? ZhCalc.round(this.value, 2) : 100) : 50;
+    //     setLocalCache('StageGatherOverPercent', this.value);
+    //     checkOverRange(gclGatherData);
+    //     SpreadJsObj.reLoadSheetData(gclSpread.getActiveSheet());
+    // });
 
     postData(preUrl + '/load', { filter: 'ledger;pos;dealBills;spec;change;stageChange;preStageChange' }, function (result) {
         // 解析清单汇总数据

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

@@ -97,7 +97,7 @@ $(document).ready(() => {
                 const percent = formula.match(this.percentReg);
                 if (percent) {
                     for (const p of percent) {
-                        const v = math.evaluate(p.replace('%', '/100'));
+                        const v = math.evaluate(p.replace(new RegExp('%', 'gm'), '/100'));
                         formula = formula.replace(p, v);
                     }
                 }

+ 1 - 1
app/service/sub_project.js

@@ -358,7 +358,7 @@ module.exports = app => {
                 const removeTenderId = orgRelaTenderId.filter(x => { return relaTenderId.indexOf(x) < 0});
                 const addTenderId = relaTenderId.filter(x => { return orgRelaTenderId.indexOf(x) < 0});
                 if (removeTenderId.length > 0) await conn.update(this.ctx.service.tender.tableName, { id: removeTenderId, spid: '' });
-                if (removeTenderId.length > 0) await conn.update(this.ctx.service.tender.tableName, { id: addTenderId, spid: data.id });
+                if (addTenderId.length > 0) await conn.update(this.ctx.service.tender.tableName, { id: addTenderId, spid: data.id });
                 await conn.commit();
                 return data;
             } catch (error) {

+ 1 - 0
app/service/tender_info.js

@@ -83,6 +83,7 @@ module.exports = app => {
             if (info.decimal) {
                 info.decimal._pay_tp = info.decimal.pay ? info.decimal.payTp : info.decimal.tp;
             }
+            info.checkOverInfo = infoConst.transOverRangeCheck(this.ctx.helper, info.over_range_check);
             return info;
         }
 

+ 1 - 38
app/view/stage/gather.ejs

@@ -5,44 +5,6 @@
             <% include ./stage_sub_mini_menu.ejs %>
             <div>
                 <div class="d-inline-block">
-                    <div class="dropdown">
-                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                            超计显示
-                        </button>
-                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" style="width:290px">
-                            <span class="dropdown-item-text text-danger">截止本期合同计量 大于</span>
-                            <form class="px-4 py-3">
-                                <div class="form-group">
-                                    <div class="custom-control custom-radio">
-                                        <input type="radio" id="customRadio1" name="customRadio" class="custom-control-input" checked="">
-                                        <label class="custom-control-label" for="customRadio1">台账数量</label>
-                                    </div>
-                                </div>
-                                <div class="form-group">
-                                    <div class="custom-control custom-radio">
-                                        <input type="radio" id="customRadio2" name="customRadio" class="custom-control-input">
-                                        <label class="custom-control-label" for="customRadio2">签约清单数量</label>
-                                    </div>
-                                </div>
-                                <div class="form-group mb-0">
-                                    <div class="custom-control custom-radio">
-                                        <input type="radio" id="customRadio3" name="customRadio" class="custom-control-input">
-                                        <label class="custom-control-label" for="customRadio3">台账数量 或 签约清单数量</label>
-                                    </div>
-                                </div>
-                            </form>
-                            <span class="dropdown-item-text text-danger">
-                            <div class="input-group input-group-sm">
-                                <input type="number" step="5" class="form-control form-control-sm m-0" placeholder="100" max="100" min="50" id="over-percent" value="100">
-                                <div class="input-group-append">
-                                    <span class="input-group-text" id="basic-addon2">%</span>
-                                </div>
-                            </div>
-                        </span>
-                        </div>
-                    </div>
-                </div>
-                <div class="d-inline-block">
                     <button href="#zjhj" class="btn btn-sm btn-light text-primary" data-toggle="modal" data-target="#zjhj">章节合计</button>
                 </div>
                 <% if (ctx.app.config.is_debug) { %>
@@ -140,5 +102,6 @@
     const chapter = JSON.parse('<%- JSON.stringify(ctx.tender.info.chapter) %>');
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
     const hintOver = <%- hintOver %>;
+    const checkOverInfo = JSON.parse('<%- JSON.stringify(ctx.tender.info.checkOverInfo) %>');
     const tenderDecimal = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.tender.info.decimal)) %>'));
 </script>

+ 1 - 0
app/view/tender/detail.ejs

@@ -73,6 +73,7 @@
                             <a href="#bd-set-12" data-toggle="modal" data-target="#bd-set-12" class="dropdown-item">功能设置</a>
                             <a href="#bd-set-11" data-toggle="modal" data-target="#bd-set-11" class="dropdown-item">概况设置</a>
                             <a href="#bd-set-13" data-toggle="modal" data-target="#bd-set-13" class="dropdown-item">标段类型</a>
+                            <a href="#bd-set-14" data-toggle="modal" data-target="#bd-set-14" class="dropdown-item">超计判断条件</a>
                         </div>
                     </div>
                 <% } %>

+ 88 - 0
app/view/tender/detail_modal.ejs

@@ -1895,6 +1895,62 @@
         </div>
     </div>
 </div>
+<div class="modal fade" id="bd-set-14" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">超计判断条件</h5>
+            </div>
+            <div class="modal-body">
+                <div class="in-2">
+                    <label for="" class="mr-4">清单对比数据:</label>
+                    <div class="form-check form-check-inline ">
+                        <input class="form-check-input" name="oc-field" type="radio" id="oc-field-deal" value="deal">
+                        <label class="form-check-label" for="oc-field-deal">签约</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                        <input class="form-check-input" name="oc-field" type="radio" id="oc-field-tz" value="tz">
+                        <label class="form-check-label" for="oc-field-tz">台账</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                        <input class="form-check-input" name="oc-field" type="radio" id="oc-field-bothy" value="both">
+                        <label class="form-check-label" for="oc-field-both">签约或台账</label>
+                    </div>
+                </div>
+                <div class="in-2">
+                    <label>含计量单元的清单:</label>
+                    <div class="form-check form-check-inline ">
+                        <input class="form-check-input" name="oc-bp" type="radio" id="oc-bp-bills" value="bills">
+                        <label class="form-check-label" for="oc-bp-bills">清单</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                        <input class="form-check-input" name="oc-bp" type="radio" id="oc-bp-pos" value="pos">
+                        <label class="form-check-label" for="oc-bp-pos">计量单元</label>
+                    </div>
+                    <div class="form-check form-check-inline">
+                        <input class="form-check-input" name="oc-bp" type="radio" id="oc-bp-both" value="both">
+                        <label class="form-check-label" for="oc-bp-both">清单和计量单元</label>
+                    </div>
+                </div>
+                <div class="in-2" style="vertical-align: middle;">
+                    <label class="mr-5">数据比例:</label>
+                    <div class="form-check form-check-inline">
+                        <div class="input-group input-group-sm" style="width:100px">
+                            <input type="number" class="form-control" name="oc-percent" max="100" min="0" step="2" value="100">
+                            <div class="input-group-append">
+                                <span class="input-group-text">%</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-sm btn-primary" onclick="post14();">确认修改</button>
+            </div>
+        </div>
+    </div>
+</div>
 <!--游客账号-->
 <div class="modal fade" id="bd-set-9" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -2119,6 +2175,38 @@
             $('#bd-set-13').modal('hide');
         });
     }
+    const loadOverCheckProperty = function () {
+        //$('[name=oc-field]').removeAttr('checked');
+        $(`#oc-field-${property.over_range_check.field}`)[0].checked = true;
+        //$('[name=oc-bp]').removeAttr('checked');
+        $(`#oc-bp-${property.over_range_check.billsWithPos}`)[0].checked = true;
+        $('[name=oc-percent]').val(property.over_range_check.percent);
+    };
+    $('#bd-set-14').on('show.bs.modal', function () {
+        loadOverCheckProperty();
+    });
+    function post14() {
+        let percent;
+        try {
+            percent = parseInt($('[name=oc-percent]').val());
+            if (percent < 0 || percent > 100) throw '数据比例请输入0-100的整数';
+        } catch (err) {
+            toastr.error('数据比例请输入0-100的整数');
+            return;
+        }
+        const prop = {
+            over_range_check: {
+                field: $('[name=oc-field]:checked').val(),
+                billsWithPos: percent,
+                percent: $('[name=oc-bp]:checked').val(),
+            }
+        }
+        const tenderId = window.location.pathname.split('/')[2];
+        postData('/tender/' + tenderId + '/save2', prop, function (data) {
+            property.over_range_check = data.over_range_check;
+            $('#bd-set-14').modal('hide');
+        });
+    }
     $(function () {
         // 投资进度
         let timer2 = null;

+ 6 - 1
sql/update.sql

@@ -85,7 +85,12 @@ CREATE TABLE `zh_sub_project_file`  (
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
 
+ALTER TABLE `calculation`.`zh_tender_info`
+ADD COLUMN `over_range_check` varchar(255) NOT NULL DEFAULT '' AFTER `s_type`;
 
 ------------------------------------
 -- 表数据
-------------------------------------
+------------------------------------
+
+UPDATE zh_tender_info ti LEFT JOIN zh_tender t ON ti.tid = t.id SET ti.over_range_check = '{"field":"deal","percent":100,"billsWithPos":"bills"}' WHERE t.measure_type = 2;
+UPDATE zh_tender_info ti LEFT JOIN zh_tender t ON ti.tid = t.id SET ti.over_range_check = '{"field":"tz","percent":100,"billsWithPos":"both"}' WHERE t.measure_type = 1;