Browse Source

清单汇总调整

MaiXinRong 10 months ago
parent
commit
eb3b356c2a

+ 12 - 6
app/const/spread.js

@@ -1234,16 +1234,18 @@ const stageGather = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             { title: '本期补差|原单价', colSpan: '2|1', rowSpan: '1|1', field: 'org_price', hAlign: 2, width: 60, type: 'Number' },
             { title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'pc_tp', hAlign: 2, width: 60, type: 'Number' },
             {title: '本期完成计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 60, type: 'Number'},
             {title: '截止本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'end_qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number'},
@@ -1264,11 +1266,13 @@ const stageGather = {
         cols: [
             {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 100, formatter: '@'},
             {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, type: 'Number'},
-            {title: '本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量数量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
-            {title: '截止本期计量数量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期计量数量|合同', colSpan: '5|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'end_qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number', visible: false},
             {title: '单位工程', colSpan: '1', rowSpan: '2', field: 'dwgc', hAlign: 0, width: 80, formatter: '@'},
@@ -1295,11 +1299,13 @@ const stageGather = {
             {title: '细目', colSpan: '1', rowSpan: '2', field: 'jldy', hAlign: 0, width: 80, formatter: '@', visible: false},
             {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 80, formatter: '@'},
             {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, type: 'Number'},
-            {title: '本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量数量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
-            {title: '截止本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期计量数量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'end_qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
         ],
         emptyRows: 0,

+ 21 - 2
app/controller/pay_controller.js

@@ -8,6 +8,8 @@
  * @version
  */
 
+const audit = require('../const/audit');
+
 module.exports = app => {
 
     class PayController extends app.BaseController {
@@ -23,13 +25,30 @@ module.exports = app => {
 
         async index(ctx) {
             try {
-                const pays = await this.ctx.service.pay.getAllDataByCondition({ where: { tid: ctx.tender.id } });
+                const phasePays = await this.ctx.service.phasePay.getAllPhasePay(ctx.tender.id, 'DESC');
+                this.ctx.service.phasePay.calculatePhasePay(phasePays);
+                const renderData = {
+                    phasePays,
+                    auditConst: audit.common,
+                };
+                await this.layout('phase_pay/index.ejs', renderData);
+            } catch (err) {
+                ctx.helper.log(err);
+            }
+        }
+
+        async pay(ctx) {
+            try {
+                const pays = await this.ctx.service.phasePay.getAllPhasePay(ctx.tender.id, 'DESC');
                 const renderData = {
+                    pays,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.pay.list)
                 };
-                await this.layout('pay/index.ejs', renderData);
+                await this.layout('pay/pay.ejs', renderData);
             } catch (err) {
                 ctx.helper.log(err);
+                ctx.postError(err, '读取合同支付数据错误');
+                ctx.redirect(this.request.headers.referer);
             }
         }
 

+ 55 - 0
app/middleware/phase_pay_check.js

@@ -0,0 +1,55 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = options => {
+    /**
+     * 期校验 中间件
+     * 1. 读取期数据
+     * 2. 检验用户是否参与期(不校验具体权限)
+     *
+     * 写入ctx.phasePay数据
+     * 其中:
+     * phasePay.user: 创建人
+     * phasePay.auditors: 审批人列表(退回原报时,加载上一流程)
+     * phasePay.curAuditors: 当前审批人(未上报为空,审批通过 or 退回原报时,为空)
+     *
+     * phasePay.readOnly: 登录人,是否可操作
+     * phasePay.curTimes: 当前登录人,操作、查阅数据times
+     * phasePay.curOrder: 当前登录人,操作、查阅数据order
+     *
+     * 该方法为通用方法,如需phasePay其他数据,请在controller中查询
+     *
+     * @param {function} next - 中间件继续执行的方法
+     * @return {void}
+     */
+    return function* phasePayCheck(next) {
+        try {
+            // 读取标段数据
+            const phaseOrder = parseInt(this.params.order);
+            if (phaseOrder <= 0) throw '您访问的合同支付不存在';
+
+            const phasePay = yield this.service.phasePay.getPhasePayByOrder(this.tender.id, phaseOrder);
+            if (!phasePay) throw '合同支付数据错误';
+
+            // 读取原报、审核人数据
+            yield this.service.phasePay.loadUser(phasePay);
+            this.phasePay = phasePay;
+            yield next;
+        } catch (err) {
+            this.log(err);
+            if (this.helper.isAjax(this.request)) {
+                this.ajaxErrorBody(err, '读取合同支付错误');
+            } else {
+                this.postError(err, '读取合同支付错误');
+                this.redirect(this.request.headers.referer);
+            }
+        }
+    };
+};

+ 28 - 13
app/public/js/stage_gather.js

@@ -68,10 +68,18 @@ $(document).ready(function () {
     // 初始化所属项目节
     const leafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-spread')[0]);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(leafXmjSpreadSetting);
+    leafXmjSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
+        if (!data) return defaultColor;
+        return data.overRange && hintOver ? spreadColor.stage.over : defaultColor;
+    };
     SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);
 
     const gatherLeafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-gather-spread')[0]);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherLeafXmjSpreadSetting);
+    gatherLeafXmjSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
+        if (!data) return defaultColor;
+        return data.overRange && hintOver ? spreadColor.stage.over : defaultColor;
+    };
     const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
     SpreadJsObj.initSheet(gatherLeafXmjSheet, gatherLeafXmjSpreadSetting);
 
@@ -174,24 +182,28 @@ $(document).ready(function () {
             }
         }
     }
+    function checkXmjOverRange(data, checkXmjList) {
+        const xmjGatherOver = function (data, qtyField, per) {
+            if (!data[qtyField]) return true;
+            return data[qtyField] > 0
+                ? data.end_contract_qty > ZhCalc.mul(data[qtyField], per)
+                : data.end_contract_qty < ZhCalc.mul(data[qtyField], per) || data.end_contract_qty > 0;
+        };
+        const nPercent = checkOverInfo.coe;
+        for (const node of data) {
+            if (!node || !node[checkXmjList] || node[checkXmjList].length === 0) continue;
+            for (const xmj of node[checkXmjList]) {
+                const bOverRangeTz = checkOverInfo.checkTz ? xmjGatherOver(xmj, 'final_1_qty', nPercent) : false;
+                const bOverRangeDeal = checkOverInfo.checkDeal ? xmjGatherOver(xmj, 'deal_final_1_qty', nPercent) : false;
+                xmj.overRange = bOverRangeDeal || bOverRangeTz;
+            }
+        }
+    }
     // 切换清单行,读取所属项目节数据
     gclSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
         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());
-    // });
 
     postData(preUrl + '/load', { filter: 'ledger;pos;dealBills;spec;change;stageChange;preStageChange' }, function (result) {
         // 解析清单汇总数据
@@ -205,6 +217,8 @@ $(document).ready(function () {
         gclGatherModel.checkDiffer(gclGatherData);
         gclGatherModel.reGatherLeafXmj();
         checkOverRange(gclGatherData);
+        checkXmjOverRange(gclGatherData, 'leafXmjs');
+        checkXmjOverRange(gclGatherData, 'gatherLeafXmjs');
         // 加载清单数据
         SpreadJsObj.loadSheetData(gclSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gclGatherData);
         loadRelaData(0);
@@ -289,6 +303,7 @@ $(document).ready(function () {
             col.visible = col.type === 'Number' || fields.indexOf(col.field) >= 0;
         }
         gclGatherModel.reGatherLeafXmj(fields);
+        checkXmjOverRange(gclGatherData, 'gatherLeafXmjs');
         SpreadJsObj.refreshColumnVisible(gatherLeafXmjSheet);
         loadGatherLeafXmjData();
     });

+ 4 - 0
app/router.js

@@ -20,6 +20,7 @@ module.exports = app => {
     // 期读取中间件
     const stageCheck = app.middlewares.stageCheck();
     const settleCheck = app.middlewares.settleCheck();
+    const phasePayCheck = app.middlewares.phasePayCheck();
     // 材料调差读取中间件
     const materialCheck = app.middlewares.materialCheck();
     // 第三方接口认证判断中间件
@@ -388,6 +389,9 @@ module.exports = app => {
     app.get('/tender/:id/measure/stage/:order/pay/download/file/:fid', sessionAuth, 'stageController.payDownloadFile');
     app.post('/tender/:id/measure/stage/:order/pay/delete/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.payDeleteFile');
 
+    app.get('/tender/:id/pay', sessionAuth, tenderCheck, uncheckTenderCheck, 'payController.index');
+    app.get('/tender/:id/pay/:order', sessionAuth, tenderCheck, uncheckTenderCheck, phasePayCheck, 'payController.pay');
+
     // 变更概况
     app.get('/tender/:id/measure/stage/:order/change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.change');
     app.post('/tender/:id/measure/stage/:order/change/data', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.getChangeData');

+ 165 - 0
app/service/phase_pay.js

@@ -0,0 +1,165 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const audit = require('../const/audit').common;
+
+module.exports = app => {
+    class PhasePay extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'phase_pay';
+        }
+
+        analysisPhasePay(data) {
+            const datas = data instanceof Array ? data : [data];
+            datas.forEach(x => {
+                x.rela_stage = x.rela_stage ? JSON.parse(x.rela_stage) : [];
+                x.calc_base = x.calc_base ? JSON.parse(x.calc_base) : [];
+            });
+        }
+
+        calculatePhasePay(data) {
+            const helper = this.ctx.helper;
+            const datas = data instanceof Array ? data : [data];
+            const formatNum = this.ctx.tender.info.display.thousandth ? this.ctx.helper.formatNum : function(num) { return num ? num + '' : ''; };
+            datas.forEach(x => {
+                x.end_calc_tp = helper.add(x.calc_tp, x.pre_calc_tp);
+                x.end_pay_tp = helper.add(x.pay_tp, x.pre_pay_tp);
+                x.end_cut_tp = helper.add(x.cut_tp, x.pre_cut_tp);
+                x.end_sf_tp = helper.add(x.sf_tp, x.pre_sf_tp);
+                x.end_yf_tp = helper.add(x.yf_tp, x.pre_yf_tp);
+                if (thousandth)
+                for (const prop in x) {
+                    if (prop.indexOf('_tp') > 0) {
+                        x['display_' + prop] = formatNum(x[prop]);
+                    }
+                }
+            });
+        }
+
+        /**
+         * 获取全部修订
+         * @param tid
+         * @returns {Promise<*>}
+         */
+        async getAllPhasePay (tid, sort = 'ASC') {
+            const result = await this.getAllDataByCondition({
+                where: {tid: tid},
+                orders: [['phase_order', sort]],
+            });
+            this.analysisPhasePay(result);
+            return result;
+        }
+
+        async getPhasePay(id) {
+            const result = await this.getDataById(id);
+            this.analysisPhasePay(result);
+            return result;
+        }
+
+        async getPhasePayByOrder(tid, phaseOrder) {
+            const result = await this.getDataByCondition({ tid, phase_order: phaseOrder });
+            this.analysisPhasePay(result);
+            return result;
+        }
+
+        async loadUser(phasePay) {
+            // todo 加载审批人
+        }
+
+        async getNewOrder(tid) {
+            const sql = 'SELECT Max(`phase_order`) As max_order FROM ' + this.tableName + ' Where `tid` = ?';
+            const sqlParam = [tid];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result.max_order || 0;
+        }
+
+        async _checkRelaStageConflict(relaStage, phasePay) {
+            const pays = this.getAllPhasePay(phasePay.tid);
+            for (const p of pays) {
+                if (p.id === phasePay.id) continue;
+                for (const s of relaStage) {
+                    if (p.rela_stage.find(x => { return x.id === s.id; })) return true;
+                }
+            }
+            return false;
+        }
+
+        async getCalcBase(relaStage) {
+            // todo 获取计算基数
+        }
+
+        async add(tid, relaStage, phaseDate, memo) {
+            if (!tid) throw '数据错误';
+            const user_id = this.ctx.session.sessionUser.accountId;
+
+            const maxOrder = await this.getNewOrder(tid);
+            const data = {
+                id: this.uuid.v4(), tid: tid, create_user_id: user_id, update_user_id: user_id,
+                phase_order: maxOrder + 1, phase_date: phaseDate, memo,
+                audit_times: 1, audit_status: audit.status.uncheck,
+                rela_stage: JSON.stringify(relaStage.map(s => { return {stage_id: s.id, stage_order: s.order}; })),
+            };
+            if (await this._checkRelaStageConflict(relaStage, data)) throw '选择的计量期,已被调用,请刷新页面后选择计量期新增合同支付';
+
+            const calcBase = await this.getCalcBase(relaStage);
+            data.calc_base = JSON.stringify(calcBase);
+            const transaction = await this.db.beginTransaction();
+            try {
+                const result = await transaction.insert(this.tableName, data);
+                if (result.affectedRows !== 1) throw '新增合同支付失败';
+
+                await this.ctx.service.phasePayDetail.initPhaseData(data);
+                await transaction.commit();
+                return data;
+            } catch(err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async refreshCalcBase(id) {
+            const curPay = this.getPhasePay(id);
+            if (!curPay) throw '合同支付不存在, 请刷新页面重试';
+
+            const calcBase = await this.getCalcBase(relaStage);
+            await this.defaultUpdate({
+                id, update_user_id: this.ctx.session.sessionUser.accountId,
+                calc_base: JSON.stringify(calcBase),
+                rela_stage: JSON.stringify(relaStage.map(s => { return {stage_id: s.id, stage_order: s.order}; })),
+                calc_base_time: new Date()
+            });
+        }
+
+        async resetRelaStageId(id, relaStage) {
+            const curPay = this.getPhasePay(id);
+            if (!curPay) throw '合同支付不存在, 请刷新页面重试';
+
+            if (await this._checkRelaStageConflict(relaStage, curPay)) throw '选择的计量期,已被调用,请刷新页面后选择计量期新增合同支付';
+            const calcBase = await this.getCalcBase(relaStage);
+            await this.defaultUpdate({
+                id, update_user_id: this.ctx.session.sessionUser.accountId,
+                calc_base: JSON.stringify(calcBase),
+                rela_stage: JSON.stringify(relaStage.map(s => { return {stage_id: s.id, stage_order: s.order}; })),
+                calc_base_time: new Date()
+            });
+        }
+
+    }
+
+    return PhasePay;
+};

+ 107 - 0
app/view/phase_pay/index.ejs

@@ -0,0 +1,107 @@
+<% include ../tender/tender_sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex">
+            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <h2>
+                合同支付列表
+            </h2>
+            <div class="ml-auto">
+                <a href="#add-qi" data-toggle="modal" data-target="#add-qi" class="btn btn-primary btn-sm">开始新一期</a>
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <div class="sjs-height-0">
+                <table class="table table-bordered table-hover">
+                    <thead>
+                    <tr>
+                        <th class="text-center" width="80px">支付期数</th>
+                        <th class="text-center" width="70px">支付月份</th>
+                        <th class="text-center" width="70px">计量期</th>
+                        <th class="text-center" width="100px">本期付款</th>
+                        <th class="text-center" width="100px">本期扣款</th>
+                        <th class="text-center" width="100px">本期应付</th>
+                        <th class="text-center" width="100px">本期实付</th>
+                        <th class="text-center" width="100px">截止本期应付</th>
+                        <th class="text-center" width="100px">截止本期实付</th>
+                        <th class="text-center" width="200px">审批进度</th>
+                        <th class="text-center" width="90px">操作</th>
+                        <th class="text-center" width="200px">备注</th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <% for (const pay of phasePays) { %>
+                    <tr>
+                        <td>
+                            <a href="<%- '/tender/' + pay.tid + '/pay/' + pay.phase_order %>" target="_blank">第 <%- pay.phase_order %> 期</a>
+                            <% if (pay.audit_status !== auditConst.status.checked && pay.create_user_id === ctx.session.sessionUser.accountId) { %>
+                            <a href="#edit" class="edit-pay" data-id="<%- pay.id %>" data-toggle="modal" data-target="#edit"><i class="fa fa-pencil-square-o "></i></a>
+                            <% } %>
+                        </td>
+                        <td class="text-center"><%- s.phase_date %></td>
+                        <td class="text-center">
+                            <% for (const s of pay.rela_stage) { %>
+                            <a href="<%- '/tender/' + pay.tid + '/measure/stage/' + s.sorder %>" target="_blank">第 <%- s.sorder %> 期</a>
+                            <% } %>
+                        </td>
+                        <td class="text-right"><%- s.display_pay_tp %></td>
+                        <td class="text-right"><%- s.display_cut_tp %></td>
+                        <td class="text-right"><%- s.display_yf_tp %></td>
+                        <td class="text-right"><%- s.display_sf_tp %></td>
+                        <td class="text-right"><%- s.display_end_yf_tp %></td>
+                        <td class="text-right"><%- s.display_end_sf_tp %></td>
+                        <td class="<%- auditConst.auditProgressClass[s.status] %>">
+                            <% if (s.status === auditConst.status.checked && s.final_auditor_str) { %>
+                            <a href="#sp-list" data-toggle="modal" data-target="#sp-list" s-order="<%- s.order %>"><%- s.final_auditor_str %></a>
+                            <% } else { %>
+                            <% if (s.curAuditors.length > 0) { %>
+                            <% if (s.curAuditors[0].audit_type === auditType.key.common) { %>
+                            <a href="#sp-list" data-toggle="modal" data-target="#sp-list" s-order="<%- s.order %>"><%- s.curAuditors[0].name %><%if (s.curAuditors[0].role !== '' && s.curAuditors[0].role !== null) { %>-<%- s.curAuditors[0].role %><% } %></a>
+                            <% } else { %>
+                            <a href="#sp-list" data-toggle="modal" data-target="#sp-list" s-order="<%- s.order %>"><%- ctx.helper.transFormToChinese(s.curAuditors[0].audit_order) + '审' %></a>
+                            <% } %>
+                            <% } %>
+                            <% } %>
+                            <%- auditConst.auditProgress[s.status] %>
+                        </td>
+                        <td class="text-center">
+                            <% if (s.status === auditConst.status.uncheck && s.user_id === ctx.session.sessionUser.accountId) { %>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <% } else if (s.status === auditConst.status.checkNo && s.user_id === ctx.session.sessionUser.accountId) { %>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <% } else if ((s.status === auditConst.status.checking || s.status === auditConst.status.checkNoPre) && s.curAuditors && s.curAuditors.findIndex(x => { return x.aid === ctx.session.sessionUser.accountId; }) >= 0) { %>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <% } else { %>
+                            <span class="<%- auditConst.auditStringClass[s.status] %>"><%- auditConst.auditString[s.status] %></span>
+                            <% } %>
+                        </td>
+                        <td> <%- pay.memo %></td>
+                    </tr>
+                    <% } %>
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    </div>
+</div>
+<script src="/public/js/sub_menu.js"></script>
+<script>
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+        }
+    });
+</script>

+ 3 - 0
config/web.js

@@ -679,6 +679,9 @@ const JsFiles = {
                 mergeFile: 'sr_detail',
             },
         },
+        phasePay: {
+
+        },
         measure: {
             compare: {
                 files: [