Explorar o código

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

MaiXinRong %!s(int64=5) %!d(string=hai) anos
pai
achega
18ecd5d7ab

+ 0 - 1
app/controller/change_controller.js

@@ -442,7 +442,6 @@ module.exports = app => {
                         }
                     }
                     renderData.auditList4 = auditList4;
-                    console.log(auditList4)
 
                     changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort();
                     renderData.changeList = changeList;

+ 127 - 0
app/controller/wap_controller.js

@@ -10,6 +10,7 @@
 const URL = require('url');
 const maintainConst = require('../const/maintain');
 const auditConst = require('../const/audit');
+const changeConst = require('../const/change');
 
 module.exports = app => {
 
@@ -121,8 +122,13 @@ module.exports = app => {
                 audit.end_gather_tp = ctx.helper.add(audit.end_contract_tp, audit.end_qc_tp);
                 audit.pre_gather_tp = ctx.helper.add(audit.pre_contract_tp, audit.pre_qc_tp);
             }
+            // 获取待审批的变更期
+            const auditChanges = await ctx.service.changeAudit.getAuditChangeByWap(ctx.session.sessionUser.accountId);
             const renderData = {
                 auditStages,
+                auditChanges,
+                changeConst,
+                tpUnit: 2,
             };
             await ctx.render('wap/dashboard.ejs', renderData);
         }
@@ -228,10 +234,22 @@ module.exports = app => {
                     p.end_tp = sum;
                     p.end_ratio = ctx.helper.mul(ctx.helper.div(p.end_tp, tender.sum, 4), 100);
                 }
+
+                // 变更令列表
+                const changes = await ctx.service.change.getListByStatus(tender.id, 0, 0);
+
+                for (const c of changes) {
+                    c.curAuditor = await ctx.service.changeAudit.getLastUser(c.cid, c.times);
+                }
+
                 const renderData = {
                     tender,
                     stages,
+                    changes,
                     auditConst: auditConst.stage,
+                    auditChangeConst: auditConst.flow,
+                    changeConst,
+                    tpUnit: ctx.tender.info.decimal.tp,
                     monthProgress,
                     stagesEcharts: JSON.parse(JSON.stringify(stages)).reverse(),
                 };
@@ -257,6 +275,115 @@ module.exports = app => {
                 ctx.redirect('/wap/list');
             }
         }
+
+        /**
+         * 期审批详细页
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async stage(ctx) {
+            try {
+                const tender = ctx.tender.data;
+                const stages = await ctx.service.stage.getValidStages(ctx.tender.id);
+                const lastStage = stages.length > 0 ? stages[0] : null;
+                if (lastStage) {
+                    await this.ctx.service.stage.checkStageGatherData(lastStage);
+                }
+                const stage = lastStage;
+                const renderData = {
+                    tender,
+                    stage,
+                    auditConst: auditConst.stage,
+                };
+                const times = renderData.stage.status === auditConst.stage.status.checkNo ? renderData.stage.times - 1 : renderData.stage.times;
+                renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stage.user_id);
+                renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stage.id, times);
+                // 获取审批流程中左边列表
+                renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stage.id, times);
+                await ctx.render('wap/shenpi_stage.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/wap/list');
+            }
+        }
+
+        /**
+         * 变更审批详细页
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async change(ctx) {
+            try {
+                const tender = ctx.tender.data;
+                const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid });
+                const times = change.status !== auditConst.flow.status.back ? change.times : change.times - 1;
+                const auditList = await ctx.service.changeAudit.getListOrderByTimes(change.cid, times);
+                const auditGroupList = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times);
+                const renderData = {
+                    tender,
+                    change,
+                    auditList,
+                    auditGroupList,
+                    auditConst: auditConst.flow,
+                    changeConst,
+                    tpUnit: ctx.tender.info.decimal.tp,
+                };
+                await ctx.render('wap/shenpi_change.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/wap/list');
+            }
+        }
+
+        /**
+         * 变更令审批
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async changeApproval(ctx) {
+            try {
+                const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.change_id });
+                if (!changeData) {
+                    throw '变更令数据错误';
+                }
+                const status = parseInt(ctx.request.body.status);
+                let result = false;
+                switch (status) {
+                    case 3:// 审批通过
+                        // 获取前一个人的list,生成bills_list
+                        // 获取已选清单
+                        const changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.request.body.change_id } });
+                        const bills_array = [];
+                        for (const cl of changeList) {
+                            const bill = cl.id + '_' + cl.spamount;
+                            bills_array.push(bill);
+                        }
+                        const postData = ctx.request.body;
+                        postData.bills_list = bills_array.join(',');
+                        result = await ctx.service.change.approvalSuccess(ctx.request.body, changeData);
+                        break;
+                    case 4:// 审批终止
+                        result = await ctx.service.change.approvalStop(ctx.request.body);
+                        break;
+                    case 5:// 审批退回到原报人
+                        result = await ctx.service.change.approvalBack(ctx.request.body, changeData);
+                        break;
+                    case 6:// 审批退回到上一个审批人
+                        result = await ctx.service.change.approvalBackNew(ctx.request.body, changeData);
+                        break;
+                    default:break;
+                }
+                if (!result) {
+                    throw '审批失败';
+                }
+                ctx.redirect(ctx.request.header.referer);
+            } catch (err) {
+                console.log(err);
+                ctx.redirect(ctx.request.header.referer);
+            }
+        }
     }
 
     return WapController;

+ 3 - 5
app/extend/helper.js

@@ -965,14 +965,12 @@ module.exports = {
      * @returns {*}
      */
     async urlToShort(url) {
-        // const apiUrl = 'http://mrw.so/api.htm';
+        // const apiUrl = 'http://zhzdjg.com/api/shorturl';
         // const data = {
-        //     format: 'json',
-        //     url,
-        //     key: '5eccdd0144bb353b1cd45c31@0b0510deaba52dad36dc64dbecec5e54',
+        //     url: encodeURI(url),
         // };
         // const result = await this.sendRequest(apiUrl, data, 'get');
-        // return result && result.err === '' && result.url ? result.url : url;
+        // return result && result.code === 200 && result.url ? result.url : url;
         return url;
     },
 

+ 5 - 0
app/public/css/wap/main.css

@@ -20,4 +20,9 @@
 .in-6{padding-left:105px!important}
 .bg-gray {
     background-color: #bbb !important;
+}
+input.form-control[readonly],textarea.form-control[readonly] {
+	border: none;
+	background: #f1f1f1;
+
 }

+ 2 - 0
app/public/js/change_set.js

@@ -646,8 +646,10 @@ function tableDataRemake(changeListData) {
                 let pushbwmx = '0;0';
                 if (listinfo.leafXmjs !== undefined) {
                     const leafInfo = listinfo.leafXmjs.find(function (item) {
+                        console.log(item)
                         return (item.bwmx === undefined || item.bwmx === clinfo[2]) && (item.quantity !== null ? item.quantity === parseFloat(clinfo[5]) : 0 === parseFloat(clinfo[5]));
                     });
+                    console.log(listinfo.leafXmjs, clinfo);
                     pushbwmx = leafInfo.code + '_' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : '') + ';' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                 } else {
                     pushbwmx = '0;' + (listinfo.quantity !== null ? listinfo.quantity : 0);

+ 3 - 0
app/router.js

@@ -324,4 +324,7 @@ module.exports = app => {
     app.get('/wap/dashboard', sessionAuth, 'wapController.dashboard');
     app.get('/wap/list', sessionAuth, 'wapController.list');
     app.get('/wap/tender/:id', sessionAuth, tenderCheck, 'wapController.tender');
+    app.get('/wap/tender/:id/stage/:order', sessionAuth, tenderCheck, 'wapController.stage');
+    app.get('/wap/tender/:id/change/:cid/info', sessionAuth, tenderCheck, 'wapController.change');
+    app.post('/wap/change/approval', sessionAuth, 'wapController.changeApproval');
 };

+ 15 - 10
app/service/change.js

@@ -220,7 +220,7 @@ module.exports = app => {
          * @param {int} status - 状态
          * @return {object} list - 列表
          */
-        async getListByStatus(tenderId, status = 0) {
+        async getListByStatus(tenderId, status = 0, hadlimit = 1) {
             let sql = '';
             let sqlParam = '';
             switch (status) {
@@ -257,11 +257,12 @@ module.exports = app => {
                 default:
                     break;
             }
-
-            const limit = this.app.config.pageSize;
-            const offset = limit * (this.ctx.page - 1);
-            const limitString = offset >= 0 ? offset + ',' + limit : limit;
-            sql += ' LIMIT ' + limitString;
+            if (hadlimit) {
+                const limit = this.app.config.pageSize;
+                const offset = limit * (this.ctx.page - 1);
+                const limitString = offset >= 0 ? offset + ',' + limit : limit;
+                sql += ' LIMIT ' + limitString;
+            }
             const list = await this.db.query(sql, sqlParam);
             return list;
         }
@@ -373,7 +374,8 @@ module.exports = app => {
                                 const smsType = JSON.parse(smsUser.sms_type);
                                 if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                                     const sms = new SMS(this.ctx);
-                                    const content = '【纵横计量支付】' + changeInfo.code + '变更需要您审批。';
+                                    const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + changeInfo.tid + '/change/' + changeInfo.cid + '/info#shenpi');
+                                    const content = '【纵横计量支付】' + changeInfo.code + '变更需要您审批。' + result;
                                     sms.send(smsUser.auth_mobile, content);
                                 }
                             }
@@ -549,7 +551,8 @@ module.exports = app => {
                         if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                             const sms = new SMS(this.ctx);
                             const code = await sms.contentChange(changeData.code);
-                            const content = '【纵横计量支付】' + code + '变更需要您审批。';
+                            const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + changeData.tid + '/change/' + changeData.cid + '/info#shenpi');
+                            const content = '【纵横计量支付】' + code + '变更需要您审批。' + result;
                             sms.send(smsUser.auth_mobile, content);
                         }
                     }
@@ -814,7 +817,8 @@ module.exports = app => {
                     if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const sms = new SMS(this.ctx);
                         const code = await sms.contentChange(changeData.code);
-                        const content = '【纵横计量支付】' + code + '变更需要您审批。';
+                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + changeData.tid + '/change/' + changeData.cid + '/info#shenpi');
+                        const content = '【纵横计量支付】' + code + '变更需要您审批。' + result;
                         sms.send(smsUser.auth_mobile, content);
                     }
                 }
@@ -1040,7 +1044,8 @@ module.exports = app => {
                     if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const sms = new SMS(this.ctx);
                         const code = await sms.contentChange(changeInfo.code);
-                        const content = '【纵横计量支付】' + code + '变更需要您审批。';
+                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + changeInfo.tid + '/change/' + changeInfo.cid + '/info#shenpi');
+                        const content = '【纵横计量支付】' + code + '变更需要您审批。' + result;
                         sms.send(smsUser.auth_mobile, content);
                     }
                 }

+ 25 - 0
app/service/change_audit.js

@@ -317,6 +317,31 @@ module.exports = app => {
             const sqlParam = [tenderId];
             return this.db.query(sql, sqlParam);
         }
+
+        /**
+         * 取待审批变更列表(wap用)
+         *
+         * @param auditorId
+         * @returns {Promise<*>}
+         */
+        async getAuditChangeByWap(uid) {
+            const sql = 'SELECT ca.`uid`, ca.`times`, ca.`usite`, ca.`usort`, ca.`tid`, ca.`cid`, ca.`sin_time`, ca.`name` As `caname`, ' +
+                '    c.`code` As `ccode`, c.`name` As `cname`, c.`status` As `cstatus`, c.`quality`, c.`total_price`,' +
+                '    t.`name`, t.`type`, t.`user_id`, ' +
+                '    ti.`deal_info`, ti.`decimal` ' +
+                '  FROM ?? AS ca, ?? AS c, ?? As t, ?? AS ti ' +
+                '  WHERE ca.`uid` = ? and ca.`status` = ? and c.`status` != ? and c.`status` != ?' +
+                '    and ca.`cid` = c.`cid` and ca.`tid` = t.`id` and ti.`tid` = t.`id`';
+            const sqlParam = [this.tableName, this.ctx.service.change.tableName, this.ctx.service.tender.tableName, this.ctx.service.tenderInfo.tableName, uid, audit.flow.auditStatus.checking, audit.flow.status.uncheck, audit.flow.status.back];
+            const changes = await this.db.query(sql, sqlParam);
+            for (const c of changes) {
+                const preSql = 'SELECT pa.`id`, pa.`account`, pa.`account_group`, pa.`name`, pa.`company`, pa.`role`, pa.`telephone` FROM ?? As ca, ?? As pa ' +
+                    '  WHERE ca.cid = ? and ca.times = ? and ca.usort = ? and ca.uid = pa.id';
+                const preSqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, c.cid, c.times, c.usort - 1];
+                c.pre = await this.db.queryOne(preSql, preSqlParam);
+            }
+            return await this.db.query(sql, sqlParam);
+        }
     }
 
     return ChangeAudit;

+ 6 - 6
app/service/stage_audit.js

@@ -246,7 +246,7 @@ module.exports = app => {
                         const tenderName = await sms.contentChange(tenderInfo.name);
                         const projectName = await sms.contentChange(this.ctx.tender.info.deal_info.buildName);
                         const ptmsg = projectName !== '' ? '项目「' + projectName + '」标段「' + tenderName + '」' : tenderName;
-                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '#shenpi');
+                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '/stage/' + stageInfo.order);
                         const content = '【纵横计量支付】' + ptmsg + '第' + stageInfo.order + '期,需要您审批。' + result;
                         sms.send(smsUser.auth_mobile, content);
                     }
@@ -305,7 +305,7 @@ module.exports = app => {
                             const sms = new SMS(this.ctx);
                             const tenderName = await sms.contentChange(tenderInfo.name);
                             const projectName = await sms.contentChange(this.ctx.tender.info.deal_info.buildName);
-                            const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '#shenpi');
+                            const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '/stage/' + stageInfo.order);
                             // const result = '';
                             const ptmsg = projectName !== '' ? '项目「' + projectName + '」标段「' + tenderName + '」' : tenderName;
                             const content = '【纵横计量支付】' + ptmsg + '第' + stageInfo.order + '期,需要您审批。' + result;
@@ -521,7 +521,7 @@ module.exports = app => {
                         const tenderName = await sms.contentChange(tenderInfo.name);
                         const projectName = await sms.contentChange(this.ctx.tender.info.deal_info.buildName);
                         const ptmsg = projectName !== '' ? '项目「' + projectName + '」标段「' + tenderName + '」' : tenderName;
-                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '#shenpi');
+                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '/stage/' + stageInfo.order);
                         // const result = '';
                         const content = '【纵横计量支付】' + ptmsg + '第' + stageInfo.order + '期,需要您审批。' + result;
                         sms.send(smsUser.auth_mobile, content);
@@ -739,7 +739,7 @@ module.exports = app => {
                         const tenderName = await sms.contentChange(tenderInfo.name);
                         const projectName = await sms.contentChange(this.ctx.tender.info.deal_info.buildName);
                         const ptmsg = projectName !== '' ? '项目「' + projectName + '」标段「' + tenderName + '」' : tenderName;
-                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '#shenpi');
+                        const result = await this.ctx.helper.urlToShort('http://' + this.ctx.request.header.host + '/wap/tender/' + this.ctx.tender.id + '/stage/' + stageInfo.order);
                         const content = '【纵横计量支付】' + ptmsg + '第' + stageInfo.order + '期,需要您审批。' + result;
                         sms.send(smsUser.auth_mobile, content);
                     }
@@ -870,14 +870,14 @@ module.exports = app => {
                 case auditConst.status.checking :
                 case auditConst.status.checked :
                 case auditConst.status.checkNoPre :
-                    sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`aid`, la.`order` ' +
+                    sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`order` ' +
                         'FROM ?? AS la, ?? AS pa ' +
                         'WHERE la.`sid` = ? and la.`status` = ? and la.`aid` = pa.`id` order by la.`times` desc, la.`id` desc';
                     sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, status];
                     auditor = await this.db.queryOne(sql, sqlParam);
                     break;
                 case auditConst.status.checkNo :
-                    sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`aid`, la.`order` ' +
+                    sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`sid`, la.`order` ' +
                         'FROM ?? AS la, ?? AS pa ' +
                         'WHERE la.`sid` = ? and la.`status` = ? and la.`times` = ? and la.`aid` = pa.`id` order by la.`times` desc, la.`id` desc';
                     sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, auditConst.status.checkNo, parseInt(times) - 1];

+ 28 - 4
app/view/wap/dashboard.ejs

@@ -36,11 +36,12 @@
         </nav>
         <!--待审批期列表-->
         <div class="py-6">
-            <% if (auditStages.length !== 0) { %>
+            <% if (auditStages.length !== 0 || auditChanges.length !== 0) { %>
                 <% for (const audit of auditStages) { %>
                 <div class="card mb-3">
-                    <div class="card-header">
-                        <%- JSON.parse(audit.deal_info).buildName %>
+                    <div class="card-header d-flex justify-content-between">
+                        <span><%- JSON.parse(audit.deal_info).buildName %></span>
+                        <span class="badge badge-pill badge-info">计量期</span>
                     </div>
                     <div class="bg-light p-2 px-3"><b><%- audit.name %></b></div>
                     <div class="card-body">
@@ -56,11 +57,34 @@
                             </table>
                         </div>
                         <div class="">
-                            <a href="/wap/tender/<%- audit.tid %>#shenpi" class="btn btn-block btn-success">审批</a>
+                            <a href="/wap/tender/<%- audit.tid %>/stage/<%- audit.order %>" class="btn btn-block btn-success">审批</a>
                         </div>
                     </div>
                 </div>
                 <% } %>
+                <% for (const change of auditChanges) { %>
+                    <div class="card mb-3">
+                        <div class="card-header d-flex justify-content-between">
+                            <span><%- JSON.parse(change.deal_info).buildName %></span>
+                            <span class="badge badge-pill badge-danger">工程变更</span>
+                        </div>
+                        <div class="bg-light p-2 px-3"><b><%- change.name %></b></div>
+                        <div class="card-body">
+                            <div class="d-flex justify-content-between"><span><%- change.ccode %></span></div>
+                            <div class="my-2">
+                                <table class="table table-sm table-bordered">
+                                    <tr><th width="90">工程名称</th><td><%- change.cname %></td></tr>
+                                    <tr><th>变更性质</th><td><% for (const q in changeConst.quality) { %>
+                                                <% const cQuality = changeConst.quality[q] %><% if (cQuality.value === change.quality) { %><%- cQuality.name %><% } %><% } %></td></tr>
+                                    <tr><th>变更金额</th><td class="text-right"><%- ctx.helper.roundNum(change.total_price, JSON.parse(change.decimal).tp) %></td></tr>
+                                </table>
+                            </div>
+                            <div class="">
+                                <a href="/wap/tender/<%- change.tid %>/change/<%- change.cid %>/info#shenpi" class="btn btn-block btn-success">审批</a>
+                            </div>
+                        </div>
+                    </div>
+                <% } %>
             <% } else { %>
                 <h3 class="text-center text-muted">暂无待审批期计量</h3>
             <% } %>

+ 396 - 0
app/view/wap/shenpi_change.ejs

@@ -0,0 +1,396 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>标段概况-计量支付</title>
+    <link rel="stylesheet" href="/public/css/bootstrap/bootstrap.min.css">
+    <link rel="stylesheet" href="/public/css/wap/main.css">
+    <link rel="stylesheet" href="/public/css/toast.css">
+    <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="shortcut icon" href="/public/images/favicon.ico">
+    <style>
+        body {
+            padding: 0;
+        }
+    </style>
+</head>
+<body>
+<div class="container">
+    <!--顶部-->
+    <nav class="fixed-top bg-dark">
+        <div class="my-2 d-flex justify-content-between">
+            <span class="text-white ml-3"><a href="/wap/tender/<%- tender.id %>" class="mr-2 text-white show-loading"><i class="fa fa-chevron-left"></i>工程变更</a></span>
+            <a tabindex="0" href="javascript:void(0)" class="text-white text-truncate text-center"
+               style="width:150px" data-toggle="popover" data-placement="top"
+               data-content="<%- tender.name %>" data-trigger="focus"><%- tender.name %></a>
+            <div class="mr-3">
+                <div class="dropdown">
+                    <button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown">
+                        <%- ctx.session.sessionUser.name.substr(ctx.session.sessionUser.name.length > 2 ? ctx.session.sessionUser.name.length - 2 : 0) %>
+                    </button>
+                    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                        <a class="dropdown-item" href="/wap/logout">退出登录</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </nav>
+    <!--标段概况-->
+    <div class="py-6">
+        <!--标签-->
+        <ul class="nav nav-tabs nav-fill">
+            <li class="nav-item">
+                <a class="nav-link active" data-toggle="tab" href="#info" role="tab">变更信息</a>
+            </li>
+            <li class="nav-item">
+                <a class="nav-link" data-toggle="tab" href="#shenpi" role="tab">审批</a>
+            </li>
+        </ul>
+        <div class="tab-content">
+            <div class="tab-pane active" id="info">
+                <form>
+                    <div class="form-group">
+                        <label>申请编号</label>
+                        <input class="form-control form-control-sm" value="<%- change.code %>" type="text" readonly="">
+                    </div>
+                    <!--终审批复编号-->
+                    <div class="form-group">
+                        <label>变更令号(批复编号)</label>
+                        <input class="form-control form-control-sm" type="text" value="<%- change.p_code %>" readonly="">
+                    </div>
+                    <div class="form-group">
+                        <label>工程名称</label>
+                        <input class="form-control form-control-sm" value="<%- change.name %>" type="text" readonly="">
+                    </div>
+                    <div class="form-group">
+                        <label>桩号</label>
+                        <input class="form-control form-control-sm" value="<%- change.peg %>" type="text" readonly="">
+                    </div>
+                    <div class="form-group">
+                        <label>原设计图名称</label>
+                        <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.org_name %>" readonly>
+                    </div>
+                    <div class="form-group">
+                        <label>原图号</label>
+                        <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.org_code %>" readonly>
+                    </div>
+                    <div class="form-group">
+                        <label>变更设计图名称</label>
+                        <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.new_name %>" readonly>
+                    </div>
+                    <div class="form-group">
+                        <label>变更图号</label>
+                        <input class="form-control form-control-sm" placeholder="" type="text" value="<%- change.new_code %>" readonly>
+                    </div>
+                    <div class="form-group">
+                        <label><b class="text-danger">*&nbsp;</b>工程变更理由及内容</label>
+                        <textarea class="form-control form-control-sm" rows="6" readonly=""><%- change.content %></textarea>
+                    </div>
+                    <div class="form-group">
+                        <label>工程变更合同依据</label>
+                        <textarea class="form-control form-control-sm" rows="6" readonly=""><%- change.basis %></textarea>
+                    </div>
+                    <div class="form-group">
+                        <label>变更工程量数量计算式</label>
+                        <textarea class="form-control form-control-sm" rows="2" readonly=""><%- change.expr %></textarea>
+                    </div>
+                    <div class="form-group">
+                        <label>备注</label>
+                        <textarea class="form-control form-control-sm" rows="3" readonly=""><%- change.memo %></textarea>
+                    </div>
+                    <div class="form-group">
+                        <label>变更类型</label>
+                        <div class="checkbox">
+                            <% const changeType = change.type !== null && change.type !== '' ? change.type.split(',') : '' %>
+                            <% for (const t in changeConst.type) { %>
+                                <% const cType = changeConst.type[t] %>
+                                <label class="checkbox-inline">
+                                    <% if (changeType.indexOf(cType.value.toString()) !== -1) { %>
+                                        <input value="<%- cType.value %>" type="checkbox" disabled checked><%- cType.name %>
+                                    <% } %>
+                                </label>
+                            <% } %>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <label>变更类别 </label>
+                        <input class="form-control form-control-sm" value="<% for (const c in changeConst.class) { %><% const cClass = changeConst.class[c] %><% if (cClass.value === change.class) { %><%- cClass.name %><% } %><% } %>" readonly="">
+                    </div>
+                    <div class="form-group">
+                        <label>变更性质 </label>
+                        <input class="form-control form-control-sm" value="<% for (const q in changeConst.quality) { %><% const cQuality = changeConst.quality[q] %><% if (cQuality.value === change.quality) { %><%- cQuality.name %><% } %><% } %>" readonly="">
+                    </div>
+                    <div class="form-group">
+                        <label>变更提出单位</label>
+                        <input class="form-control form-control-sm" value="<%- change.company %>" readonly="">
+                    </div>
+                    <div class="form-group">
+                        <label>费用承担方</label>
+                        <div class="radio">
+                            <% for (const c in changeConst.charge) { %>
+                                <% const cCharge = changeConst.charge[c] %>
+                                <label class="radio-inline">
+                                    <% if (cCharge.value === change.charge) { %>
+                                        <input value="<%- cCharge.value %>" type="radio" disabled checked> <%- cCharge.name %>
+                                    <% } %>
+                                </label>
+                            <% } %>
+                        </div>
+                    </div>
+                    <!--除上报人,审批人填写-->
+                    <!-- <div class="form-group">
+                      <label>批复文号</label>
+                      <input class="form-control form-control-sm" value="121212" type="text" ="">
+                    </div> -->
+                </form>
+            </div>
+            <div class="tab-pane" id="shenpi">
+                <!--审批流程-->
+                <div class="card mt-3">
+                    <ul class="list-group list-group-flush">
+                        <% let checkingAudit = '' %>
+                        <% for (const [index, audit] of auditList.entries()) { %>
+                        <li class="list-group-item">
+                            <% if (audit.usite === 0) { %>
+                                <span class="<%- auditConst.auditStatusClass[audit.status] %> pull-right">
+                                    <% if (audit.status === auditConst.auditStatus.checking) { %>
+                                        待上报
+                                    <% } else if (audit.status === auditConst.auditStatus.checked) { %>
+                                        <small><%- audit.sin_time.toLocaleDateString() %></small> 上报
+                                    <% } %>
+                                </span>
+                                <h5 class="card-title">
+                                    <i class="fa fa-play-circle fa-rotate-90 <%- auditConst.auditStatusClass[audit.status] %>"></i> <%- audit.name %> <% if (audit.jobs !== '' || audit.jobs !== null) { %><small class="text-muted"><%- audit.jobs %></small><% } %>
+                                </h5>
+                            <% } else { %>
+                                <% if (audit.status === auditConst.auditStatus.checking) { %>
+                                <span class="pull-right">审批中</span>
+                                <h5 class="card-title">
+                                    <i class="fa <% if (index !== auditList.length - 1) { %>fa-chevron-circle-down<% } else { %>fa-stop-circle<% } %>"></i> <%- audit.name %> <% if (audit.jobs !== '' || audit.jobs !== null) { %><small class="text-muted"><%- audit.jobs %></small><% } %>
+                                </h5>
+                                <% if (audit.uid === ctx.session.sessionUser.accountId) { %>
+                                <% checkingAudit = audit; %>
+                                <div class="form-group">
+                                    <div class="text-center">
+                                        <button class="btn btn-success" data-toggle="modal" data-target="#sp-done" >审批通过</button>
+                                        <button class="btn btn-warning" data-toggle="modal" data-target="#sp-back" >审批退回</button>
+                                    </div>
+                                </div>
+                                <% } %>
+                                <% } else if(audit.status === auditConst.auditStatus.uncheck) { %>
+                                <h5 class="card-title"><i class="fa <% if (index !== auditList.length - 1) { %>fa-chevron-circle-down<% } else { %>fa-stop-circle<% } %>"></i> <%- audit.name %> <% if (audit.jobs !== '' || audit.jobs !== null) { %><small class="text-muted"><%- audit.jobs %></small><% } %></h5>
+                                <% } else  { %>
+                                <span class="<%- auditConst.auditStatusClass[audit.status] %> pull-right">
+                                    <small><%- audit.sin_time.toLocaleDateString() %></small> <%- auditConst.auditStatusString[audit.status] %>
+                                    <% if (audit.status === auditConst.auditStatus.backnew) { %>
+                                         <%- auditGroupList[audit.usite-1].name %>
+                                    <% } else if (audit.status === auditConst.auditStatus.back) { %>
+                                         <%- auditGroupList[0].name %>
+                                    <% } %>
+                                </span>
+                                <h5 class="card-title"><i class="fa <% if (index !== auditList.length - 1) { %>fa-chevron-circle-down<% } else { %>fa-stop-circle<% } %> <%- auditConst.auditStatusClass[audit.status] %>"></i> <%- audit.name %> <% if (audit.jobs !== '' || audit.jobs !== null) { %><small class="text-muted"><%- audit.jobs %></small><% } %></h5>
+                                <p class="card-text"><%- audit.sdesc %></p>
+                                <% } %>
+                            <% } %>
+                        </li>
+                        <% } %>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!--底栏菜单-->
+    <nav class="fixed-bottom navbar-dark bg-light border-top">
+        <ul class="nav nav-fill my-2">
+            <li class="nav-item">
+                <a class="nav-link text-muted show-loading" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
+            </li>
+            <li class="nav-item">
+                <a class="nav-link active show-loading" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
+            </li>
+        </ul>
+    </nav>
+</div>
+<% if (checkingAudit) { %>
+<!--审批通过弹窗-->
+<div class="modal" tabindex="-1" role="dialog" id="sp-done">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/wap/change/approval?_csrf=<%= ctx.csrf %>" method="post" id="success-approval">
+            <div class="modal-header">
+                <h5 class="modal-title">审批通过</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>审批意见</label>
+                    <textarea class="form-control" rows="8" name="sdesc">同意</textarea>
+                </div>
+
+                <% if (checkingAudit.usort !== 0 && checkingAudit.uid === auditGroupList[auditGroupList.length-1].uid) { %>
+                    <!--终审填写批复编号-->
+                    <div class="form-group mt-3">
+                        <label>变更令号(批复编号)</label>
+                        <input class="form-control" value="<%= change.code %>" name="p_code" type="text">
+                    </div>
+                <% } else { %>
+                    <input type="hidden" name="audit_next_id" value="<%= auditGroupList[checkingAudit.usite+1].id %>">
+                <% } %>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <input type="hidden" name="status" value="<%- auditConst.auditStatus.checked %>">
+                <input type="hidden" name="w_code" value="<%- change.w_code %>">
+                <input type="hidden" name="change_id" value="<%- change.cid %>">
+                <input type="hidden" name="audit_id" value="<%= checkingAudit.id %>">
+                <button type="submit" class="btn btn-success approval-btn">审批通过</button>
+            </div>
+        </form>
+    </div>
+</div>
+<!--审批退回弹窗-->
+<div class="modal" tabindex="-1" role="dialog" id="sp-back">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/wap/change/approval?_csrf=<%= ctx.csrf %>" method="post" id="fail-approval">
+            <div class="modal-header">
+                <h5 class="modal-title">审批退回</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>审批意见</label>
+                    <textarea class="form-control" rows="8" name="sdesc">不同意</textarea>
+                </div>
+                <div class="alert alert-warning">
+                    <div class="custom-control custom-radio custom-control-inline">
+                        <input type="radio" name="status" id="change-back" value="<%- auditConst.auditStatus.back %>" class="custom-control-input" <% if (checkingAudit.usite === 1) { %>checked<% } %>>
+                        <label class="custom-control-label" for="change-back">退回原报 <%- auditGroupList[0].name %></label>
+                    </div>
+                    <% if (checkingAudit.usite > 1) { %>
+                        <div class="custom-control custom-radio custom-control-inline">
+                            <input class="custom-control-input" type="radio" name="status" id="change-backnew" value="<%- auditConst.auditStatus.backnew %>" checked>
+                            <label class="custom-control-label" for="change-backnew">退回上一审批人 <%- auditGroupList[checkingAudit.usite-1].name %></label>
+                        </div>
+                    <% } %>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <input type="hidden" name="w_code" value="<%- change.w_code %>">
+                <input type="hidden" name="change_id" value="<%- change.cid %>">
+                <input type="hidden" name="audit_id" value="<%= checkingAudit.id %>">
+                <button type="submit" class="btn btn-warning approval-btn">确认退回</button>
+            </div>
+        </form>
+    </div>
+</div>
+<% } %>
+<script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
+<script src="/public/js/popper/popper.min.js"></script>
+<script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/cookies.js"></script>
+<script src="/public/js/wap/global.js"></script>
+<script>
+    $(document).ready(function () {
+        if (window.location.hash && window.location.hash === '#shenpi') {
+            $('#info').removeClass('active');
+            $('.nav-item a[href="#info"]').removeClass('active');
+
+            $('#shenpi').addClass('active');
+            $('.nav-item a[href="#shenpi"]').addClass('active');
+        }
+
+        // 审批提交与判断
+        $('.approval-btn').on('click', function () {
+            // 判断审批状态
+            let returnflag = true;
+            if ($(this).hasClass('btn-success')) {
+                const sdesc = $('#success-approval').find('textarea').val();
+                if (sdesc === '') {
+                    toastr.error('审批意见不能为空!');
+                    returnflag = false;
+                }
+                if ($('input[name="p_code"]').val() === '') {
+                    toastr.error('变更令号(批复编号)不能为空!');
+                    returnflag = false;
+                } else if ($('input[name="p_code"]').val() !== undefined) {
+                    $('input[name="p_code"]').val($.trim($('input[name="p_code"]').val()));
+                    const postData = {
+                        p_code: $('input[name="p_code"]').val(),
+                    };
+                    postDataWithAsync('/tender/<%- tender.id %>/change/<%- change.cid %>/check/codeRepeat',postData, function (result) {
+                    }, function (data) {
+                        returnflag = false;
+                    });
+                }
+                if(returnflag) {
+                    $('input[name="w_code"]').val($.trim($('#w_code').val()));
+
+                    $('#success-approval').find('textarea').val(sdesc.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '));
+                    $('#success-approval').submit();
+                }
+            } else {
+                const sdesc = $('#fail-approval').find('textarea').val();
+                if (sdesc === '') {
+                    toastr.error('审批意见不能为空!');
+                    returnflag = false;
+                }
+                const type = $('#fail-approval').find('input[name="status"]:checked').val();
+                if (type === undefined) {
+                    toastr.error('请选择退回类型!');
+                    returnflag = false;
+                }
+                if(returnflag) {
+                    $('#fail-approval').find('textarea').val(sdesc.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '));
+                    $('input[name="w_code"]').val($.trim($('#w_code').val()));
+                    $('#fail-approval').submit();
+                }
+            }
+        })
+    });
+
+    const postDataWithAsync = function (url, data, successCallback, errorCallBack, showWaiting = true) {
+        if (showWaiting) showWaitingView();
+        $.ajax({
+            type:"POST",
+            url: url,
+            data: {'data': JSON.stringify(data)},
+            dataType: 'json',
+            cache: false,
+            async: false,
+            timeout: 60000,
+            beforeSend: function(xhr) {
+                let csrfToken = Cookies.get('csrfToken');
+                xhr.setRequestHeader('x-csrf-token', csrfToken);
+            },
+            success: function(result){
+                if (result.err === 0) {
+                    if (successCallback) {
+                        successCallback(result.data);
+                    }
+                } else {
+                    toastr.error(result.msg);
+                    if (errorCallBack) {
+                        errorCallBack(result.msg);
+                    }
+                }
+                if (showWaiting) closeWaitingView();
+            },
+            error: function(jqXHR, textStatus, errorThrown){
+                toastr.error('error: ' + textStatus + " " + errorThrown);
+                if (errorCallBack) {
+                    errorCallBack();
+                }
+                if (showWaiting) closeWaitingView();
+            }
+        });
+    };
+</script>
+</body>
+
+</html>

+ 260 - 0
app/view/wap/shenpi_stage.ejs

@@ -0,0 +1,260 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>标段概况-计量支付</title>
+    <link rel="stylesheet" href="/public/css/bootstrap/bootstrap.min.css">
+    <link rel="stylesheet" href="/public/css/wap/main.css">
+    <link rel="stylesheet" href="/public/css/toast.css">
+    <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <script src=/public/js/echarts/echarts.min.js></script>
+    <link rel="shortcut icon" href="/public/images/favicon.ico">
+    <style>
+        body {
+            padding: 0;
+        }
+    </style>
+</head>
+<body>
+<div class="container">
+    <!--顶部-->
+    <nav class="fixed-top bg-dark">
+        <div class="my-2 d-flex justify-content-between">
+            <span class="text-white ml-3"><a href="/wap/tender/<%- tender.id %>" class="mr-2 text-white show-loading"><i class="fa fa-chevron-left"></i>计量期</a></span>
+            <a tabindex="0" href="javascript:void(0)" class="text-white text-truncate text-center"
+               style="width:150px" data-toggle="popover" data-placement="top"
+               data-content="<%- tender.name %>" data-trigger="focus"><%- tender.name %></a>
+            <div class="mr-3">
+                <div class="dropdown">
+                    <button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown">
+                        <%- ctx.session.sessionUser.name.substr(ctx.session.sessionUser.name.length > 2 ? ctx.session.sessionUser.name.length - 2 : 0) %>
+                    </button>
+                    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                        <a class="dropdown-item" href="/wap/logout">退出登录</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </nav>
+    <!--标段概况-->
+    <div class="py-6">
+        <!--最新期-->
+        <% let audit = 0; %>
+        <% if (stage) { %>
+            <dl class="mb-2 mt-3">
+                <dt class="bg-light p-2 d-flex justify-content-between"><span>第<%- stage.order %>期</span>
+                    <span class="<%- auditConst.auditStringClass[stage.status] %>">
+                        <% if (stage.curAuditor && stage.status !== auditConst.status.checked) { %>
+                            <%- stage.curAuditor.name %><%if (stage.curAuditor.role !== '' && stage.curAuditor.role !== null) { %>-<%- stage.curAuditor.role %><% } %>
+                        <% } %>
+                        <%- stage.status === auditConst.status.checked ? '审批完成' : auditConst.auditProgress[stage.status] %>
+                        </span>
+                </dt>
+                <dd>
+                    <table class="table table-hover">
+                        <tbody><tr>
+                            <td>
+                                <p class="mb-0">本期合同计量</p>
+                                <b>¥<%- stage.contract_tp ? stage.contract_tp : 0 %></b>
+                            </td>
+                            <td>
+                                <p class="mb-0">本期数量变更计量</p>
+                                <b>¥<%- stage.qc_tp ? stage.qc_tp : 0 %></b>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td>
+                                <p class="mb-0">本期完成计量</p>
+                                <b>¥<%- stage.tp ? stage.tp : 0 %></b>
+                            </td>
+                            <td>
+                                <p class="mb-0">截止上期完成计量</p>
+                                <b>¥<%- stage.pre_tp ? stage.pre_tp : 0 %></b>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td>
+                                <p class="mb-0">截止本期完成计量</p>
+                                <b>¥<%- stage.end_tp ? stage.end_tp : 0 %></b>
+                            </td>
+                            <td>
+                                <p class="mb-0">本期应付</p>
+                                <b>¥<%- stage.yf_tp ? stage.yf_tp : 0 %></b>
+                            </td>
+                        </tr>
+                        </tbody></table>
+                </dd>
+            </dl>
+            <!--审批流程-->
+            <div class="card mt-3">
+                <ul class="list-group list-group-flush">
+                    <li class="list-group-item">
+                        <% if (stage.status === auditConst.status.uncheck) { %>
+                            <span class="pull-right"> 上报中</span>
+                        <% } else { %>
+                            <span class="text-success pull-right"><small><%- stage.auditors[0].begin_time.toLocaleDateString() %></small> 上报</span>
+                        <% } %>
+                        <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- stage.user.name %><small class="text-muted"><%- stage.user.role %></small></h5>
+                    </li>
+                    <% for (let iA = 0; iA < stage.auditors.length; iA++) { %>
+                        <% const auditors = stage.auditors; %>
+                        <li class="list-group-item">
+                            <% if (auditors[iA].status === auditConst.status.checked) { %>
+                                <span class="text-success pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small> 审批通过</span>
+                                <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-success' : 'fa fa-stop-circle text-success') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
+                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                            <% } else if (auditors[iA].status == auditConst.status.checking) { %>
+                                <span class="pull-right">审批中</span>
+                                <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
+                                <% if (auditors[iA].aid === ctx.session.sessionUser.accountId) { %>
+                                    <% audit = auditors[iA]; %>
+                                    <div class="form-group">
+                                        <div class="text-center">
+                                            <button class="btn btn-success" data-toggle="modal" data-target="#sp-done" >审批通过</button>
+                                            <button class="btn btn-warning" data-toggle="modal" data-target="#sp-back" >审批退回</button>
+                                        </div>
+                                    </div>
+                                <% } %>
+                            <% } else if (auditors[iA].status === auditConst.status.checkNoPre) { %>
+                                <% const auditorIndex = stage.auditors2.findIndex(function (item) { return item.aid === auditors[iA].aid }) %>
+                                <span class="text-warning pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small>审批退回 <%- stage.auditors2[auditorIndex-1].name %></span>
+                                <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-warning' : 'fa fa-stop-circle text-warning') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
+                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                            <% } else if (auditors[iA].status === auditConst.status.checkNo) { %>
+                                <span class="text-warning pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small>审批退回</span>
+                                <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-warning' : 'fa fa-stop-circle text-warning') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
+                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                            <% } else if (auditors[iA].status === auditConst.status.checkAgain) { %>
+                                <span class="text-warning pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small>重新审批</span>
+                                <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-warning' : 'fa fa-stop-circle text-warning') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
+                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                            <% } else { %>
+                                <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
+                            <% } %>
+                        </li>
+                    <% } %>
+                </ul>
+            </div>
+        <% } %>
+    </div>
+    <!--底栏菜单-->
+    <nav class="fixed-bottom navbar-dark bg-light border-top">
+        <ul class="nav nav-fill my-2">
+            <li class="nav-item">
+                <a class="nav-link text-muted show-loading" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
+            </li>
+            <li class="nav-item">
+                <a class="nav-link active show-loading" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
+            </li>
+        </ul>
+    </nav>
+</div>
+<!--审批通过弹窗-->
+<div class="modal" tabindex="-1" role="dialog" id="sp-done">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/tender/<%- tender.id %>/measure/stage/<%- stage.order %>/audit/check" method="post" id="audit-check0">
+            <div class="modal-header">
+                <h5 class="modal-title">审批通过</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>审批意见</label>
+                    <textarea class="form-control" rows="8" name="opinion">同意</textarea>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
+                <input type="hidden" name="checkType" value="<%= auditConst.status.checked %>" />
+                <button type="submit" class="btn btn-success">审批通过</button>
+            </div>
+        </form>
+    </div>
+</div>
+<!--审批退回弹窗-->
+<div class="modal" tabindex="-1" role="dialog" id="sp-back">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" id="audit-check1">
+            <div class="modal-header">
+                <h5 class="modal-title">审批退回</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>审批意见</label>
+                    <textarea class="form-control" rows="8" name="opinion">不同意</textarea>
+                </div>
+                <div class="alert alert-warning">
+                    <div class="custom-control custom-radio custom-control-inline">
+                        <input type="radio" id="customRadioInline1" name="checkType" class="custom-control-input" value="<%- auditConst.status.checkNo %>" <% if (audit.order === 1 || audit.aid === stage.auditors[0].aid) { %>checked<% } %>>
+                        <label class="custom-control-label" for="customRadioInline1">退回原报 <%- stage.user.name %></label>
+                    </div>
+                    <% if (audit.order > 1 && audit.aid !== stage.auditors[0].aid) { %>
+                    <% const auditorIndex = stage.auditors2.findIndex(function (item) { return item.aid === audit.aid }) %>
+                    <div class="custom-control custom-radio custom-control-inline">
+                        <input class="custom-control-input" type="radio" name="checkType" id="customRadioInline2" value="<%- auditConst.status.checkNoPre %>" checked>
+                        <label class="custom-control-label" for="customRadioInline2">退回上一审批人 <%- stage.auditors2[auditorIndex-1].name %></label>
+                    </div>
+                    <% } %>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
+                <button type="submit" class="btn btn-warning">确认退回</button>
+            </div>
+        </form>
+    </div>
+</div>
+<!-- JS. -->
+<script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
+<script src="/public/js/popper/popper.min.js"></script>
+<script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/cookies.js"></script>
+<script src="/public/js/wap/global.js"></script>
+<script>
+    $(document).ready(function () {
+        $('#audit-check0').submit(function (e) {
+            if (auditCheck(0)) {
+                const data = {
+                    opinion: $('[name=opinion]', this).val(),
+                    checkType: parseInt($('[name=checkType]', this).val()),
+                };
+                postData(this.action, data, function () {
+                    window.location.reload();
+                });
+            }
+            return false;
+        });
+        $('#audit-check1').submit(function (e) {
+            if (auditCheck(1)) {
+                const data = {
+                    opinion: $('[name=opinion]', this).val(),
+                    checkType: parseInt($('[name=checkType]:checked', this).val()),
+                };
+                postData(this.action, data, function () {
+                    window.location.reload();
+                });
+            }
+            return false;
+        });
+    })
+
+    // texterea换行
+
+    function auditCheck(i) {
+        const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
+        $('textarea[name="opinion"]').eq(i).val(opinion);
+        return true;
+    }
+</script>
+</body>
+
+</html>

+ 33 - 195
app/view/wap/tender.ejs

@@ -49,7 +49,7 @@
                 <a class="nav-link" data-toggle="tab" href="#jlqi" role="tab">计量期</a>
             </li>
             <li class="nav-item">
-                <a class="nav-link" data-toggle="tab" href="#shenpi" role="tab">期审批</a>
+                <a class="nav-link" data-toggle="tab" href="#biangeng" role="tab">工程变更</a>
             </li>
         </ul>
         <div class="tab-content">
@@ -120,110 +120,59 @@
                                     <b>¥<%- s.yf_tp ? s.yf_tp : 0 %></b>
                                 </td>
                             </tr>
+                            <% if (s.curAuditor && s.status == auditConst.status.checking && s.curAuditor.aid === ctx.session.sessionUser.accountId) { %>
+                            <tr>
+                                <td colspan="2">
+                                    <a class="btn btn-block btn-success" href="/wap/tender/<%- s.tid %>/stage/<%- s.order %>">审批本期</a>
+                                </td>
+                            </tr>
+                            <% } %>
                             </tbody></table>
                     </dd>
                     <% } %>
                 </dl>
             </div>
-            <div class="tab-pane" id="shenpi">
-                <!--最新期-->
-                <% let audit = 0; %>
-                <% if (stages.length > 0 && stage) { %>
+            <div class="tab-pane" id="biangeng">
+                <!--工程变更-->
                 <dl class="mb-2 mt-3">
-                    <dt class="bg-light p-2 d-flex justify-content-between"><span>第<%- stage.order %>期</span>
-                        <span class="<%- auditConst.auditStringClass[stage.status] %>">
-                            <% if (stage.curAuditor && stage.status !== auditConst.status.checked) { %>
-                                <%- stage.curAuditor.name %><%if (stage.curAuditor.role !== '' && stage.curAuditor.role !== null) { %>-<%- stage.curAuditor.role %><% } %>
-                            <% } %>
-                            <%- stage.status === auditConst.status.checked ? '审批完成' : auditConst.auditProgress[stage.status] %>
-                        </span>
-                    </dt>
+                    <% for (const c of changes) { %>
+                    <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/<%- c.cid %>/info"><% if (c.status !== auditChangeConst.status.checked) { %><%- c.code %><% } else { %><%- c.p_code %><% } %></a></span></dt>
                     <dd>
                         <table class="table table-hover">
-                            <tbody><tr>
-                                <td>
-                                    <p class="mb-0">本期合同计量</p>
-                                    <b>¥<%- stage.contract_tp ? stage.contract_tp : 0 %></b>
-                                </td>
-                                <td>
-                                    <p class="mb-0">本期数量变更计量</p>
-                                    <b>¥<%- stage.qc_tp ? stage.qc_tp : 0 %></b>
+                            <tbody>
+                            <tr>
+                                <td colspan="2">
+                                    <p class="mb-0">工程名称</p>
+                                    <%- c.name %>
                                 </td>
                             </tr>
                             <tr>
                                 <td>
-                                    <p class="mb-0">本期完成计量</p>
-                                    <b>¥<%- stage.tp ? stage.tp : 0 %></b>
+                                    <p class="mb-0">变更性质</p>
+                                    <b><% for (const q in changeConst.quality) { %>
+                                            <% const cQuality = changeConst.quality[q] %><% if (cQuality.value === c.quality) { %><%- cQuality.name %><% } %><% } %></b>
                                 </td>
                                 <td>
-                                    <p class="mb-0">截止上期完成计量</p>
-                                    <b>¥<%- stage.pre_tp ? stage.pre_tp : 0 %></b>
+                                    <p class="mb-0">变更金额</p>
+                                    <b><%- ctx.helper.roundNum(c.total_price, tpUnit) %></b>
                                 </td>
                             </tr>
                             <tr>
-                                <td>
-                                    <p class="mb-0">截止本期完成计量</p>
-                                    <b>¥<%- stage.end_tp ? stage.end_tp : 0 %></b>
-                                </td>
-                                <td>
-                                    <p class="mb-0">本期应付</p>
-                                    <b>¥<%- stage.yf_tp ? stage.yf_tp : 0 %></b>
+                                <td colspan="2">
+                                    <% if ((c.status === auditChangeConst.status.checking || c.status === auditChangeConst.status.backnew) && c.curAuditor.uid === ctx.session.sessionUser.accountId) { %>
+                                    <a href="/wap/tender/<%- tender.id %>/change/<%- c.cid %>/info#shenpi" class="btn btn-block btn-success">审批变更</a>
+                                    <% } else if (c.status === auditChangeConst.status.uncheck) { %>
+                                    <span>待上报</span>
+                                    <% } else { %>
+                                    <span class="<%- auditChangeConst.auditStatusClass[c.curAuditor.status] %>"><%- c.curAuditor.name %>-<%- c.curAuditor.jobs %> <%- auditChangeConst.auditStatusString[c.curAuditor.status] %></span>
+                                    <% } %>
                                 </td>
                             </tr>
-                            </tbody></table>
+                            </tbody>
+                        </table>
                     </dd>
+                    <% } %>
                 </dl>
-                <!--审批流程-->
-                <div class="card mt-3">
-                    <ul class="list-group list-group-flush">
-                        <li class="list-group-item">
-                            <% if (stage.status === auditConst.status.uncheck) { %>
-                            <span class="pull-right"> 上报中</span>
-                            <% } else { %>
-                            <span class="text-success pull-right"><small><%- stage.auditors[0].begin_time.toLocaleDateString() %></small> 上报</span>
-                            <% } %>
-                            <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- stage.user.name %><small class="text-muted"><%- stage.user.role %></small></h5>
-                        </li>
-                        <% for (let iA = 0; iA < stage.auditors.length; iA++) { %>
-                            <% const auditors = stage.auditors; %>
-                        <li class="list-group-item">
-                            <% if (auditors[iA].status === auditConst.status.checked) { %>
-                            <span class="text-success pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small> 审批通过</span>
-                            <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-success' : 'fa fa-stop-circle text-success') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                            <p class="card-text"><%- auditors[iA].opinion %></p>
-                            <% } else if (auditors[iA].status == auditConst.status.checking) { %>
-                            <span class="pull-right">审批中</span>
-                            <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                <% if (auditors[iA].aid === ctx.session.sessionUser.accountId) { %>
-                                <% audit = auditors[iA]; %>
-                                <div class="form-group">
-                                    <div class="text-center">
-                                        <button class="btn btn-success" data-toggle="modal" data-target="#sp-done" >审批通过</button>
-                                        <button class="btn btn-warning" data-toggle="modal" data-target="#sp-back" >审批退回</button>
-                                    </div>
-                                </div>
-                                <% } %>
-                            <% } else if (auditors[iA].status === auditConst.status.checkNoPre) { %>
-                            <% const auditorIndex = stage.auditors2.findIndex(function (item) { return item.aid === auditors[iA].aid }) %>
-                            <span class="text-warning pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small>审批退回 <%- stage.auditors2[auditorIndex-1].name %></span>
-                            <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-warning' : 'fa fa-stop-circle text-warning') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                            <p class="card-text"><%- auditors[iA].opinion %></p>
-                            <% } else if (auditors[iA].status === auditConst.status.checkNo) { %>
-                            <span class="text-warning pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small>审批退回</span>
-                            <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-warning' : 'fa fa-stop-circle text-warning') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                            <p class="card-text"><%- auditors[iA].opinion %></p>
-                            <% } else if (auditors[iA].status === auditConst.status.checkAgain) { %>
-                            <span class="text-warning pull-right"><small><%- auditors[iA].end_time.toLocaleDateString() %></small>重新审批</span>
-                            <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-warning' : 'fa fa-stop-circle text-warning') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                            <p class="card-text"><%- auditors[iA].opinion %></p>
-                            <% } else { %>
-                            <h5 class="card-title"><i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                            <% } %>
-                        </li>
-                        <% } %>
-                    </ul>
-                </div>
-                <% } %>
             </div>
         </div>
     </div>
@@ -239,70 +188,6 @@
         </ul>
     </nav>
 </div>
-<% if (audit !== 0) { %>
-<!--审批通过弹窗-->
-<div class="modal" tabindex="-1" role="dialog" id="sp-done">
-    <div class="modal-dialog" role="document">
-        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" id="audit-check0">
-            <div class="modal-header">
-                <h5 class="modal-title">审批通过</h5>
-                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                </button>
-            </div>
-            <div class="modal-body">
-                <div class="form-group">
-                    <label>审批意见</label>
-                    <textarea class="form-control" rows="8" name="opinion">同意</textarea>
-                </div>
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
-                <input type="hidden" name="checkType" value="<%= auditConst.status.checked %>" />
-                <button type="submit" class="btn btn-success">审批通过</button>
-            </div>
-        </form>
-    </div>
-</div>
-<!--审批退回弹窗-->
-<div class="modal" tabindex="-1" role="dialog" id="sp-back">
-    <div class="modal-dialog" role="document">
-        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" id="audit-check1">
-            <div class="modal-header">
-                <h5 class="modal-title">审批通过</h5>
-                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                </button>
-            </div>
-            <div class="modal-body">
-                <div class="form-group">
-                    <label>审批意见</label>
-                    <textarea class="form-control" rows="8" name="opinion">不同意</textarea>
-                </div>
-                <div class="alert alert-warning">
-                    <div class="custom-control custom-radio custom-control-inline">
-                        <input type="radio" id="customRadioInline1" name="checkType" class="custom-control-input" value="<%- auditConst.status.checkNo %>" <% if (audit.order === 1 || audit.aid === stage.auditors[0].aid) { %>checked<% } %>>
-                        <label class="custom-control-label" for="customRadioInline1">退回上报 <%- stage.user.name %></label>
-                    </div>
-                    <% if (audit.order > 1 && audit.aid !== stage.auditors[0].aid) { %>
-                    <% const auditorIndex = stage.auditors2.findIndex(function (item) { return item.aid === audit.aid }) %>
-                    <div class="custom-control custom-radio custom-control-inline">
-                        <input class="custom-control-input" type="radio" name="checkType" id="customRadioInline2" value="<%- auditConst.status.checkNoPre %>" checked>
-                        <label class="custom-control-label" for="customRadioInline2">退回上一审批人 <%- stage.auditors2[auditorIndex-1].name %></label>
-                    </div>
-                    <% } %>
-                </div>
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
-                <button type="submit" class="btn btn-warning">确认退回</button>
-            </div>
-        </form>
-    </div>
-</div>
-<% } %>
 <!-- JS. -->
 <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
 <script src="/public/js/popper/popper.min.js"></script>
@@ -533,53 +418,6 @@
     myChart.setOption(option);
     //3 标段月进度//
 </script>
-<!--sjs-->
-<script>
-    $(document).ready(function () {
-        if (window.location.hash && window.location.hash === '#shenpi') {
-            $('#gaikuang').removeClass('active');
-            $('#jlqi').removeClass('active');
-            $('.nav-item a[href="#gaikuang"]').removeClass('active');
-            $('.nav-item a[href="#jlqi"]').removeClass('active');
-
-            $('#shenpi').addClass('active');
-            $('.nav-item a[href="#shenpi"]').addClass('active');
-        }
-
-        $('#audit-check0').submit(function (e) {
-            if (auditCheck(0)) {
-                const data = {
-                    opinion: $('[name=opinion]', this).val(),
-                    checkType: parseInt($('[name=checkType]', this).val()),
-                };
-                postData(this.action, data, function () {
-                    window.location.reload();
-                });
-            }
-            return false;
-        });
-        $('#audit-check1').submit(function (e) {
-            if (auditCheck(1)) {
-                const data = {
-                    opinion: $('[name=opinion]', this).val(),
-                    checkType: parseInt($('[name=checkType]:checked', this).val()),
-                };
-                postData(this.action, data, function () {
-                    window.location.reload();
-                });
-            }
-            return false;
-        });
-    })
-
-    // texterea换行
-
-    function auditCheck(i) {
-        const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
-        $('textarea[name="opinion"]').eq(i).val(opinion);
-        return true;
-    }
-</script>
 </body>
 
 </html>