浏览代码

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

TonyKang 4 年之前
父节点
当前提交
6c866e79b7

+ 9 - 1
app/const/tender_info.js

@@ -8,7 +8,7 @@
  * @version
  */
 
-const parseInfo = ['deal_info', 'construction_unit', 'tech_param', 'decimal', 'precision', 'deal_param', 'display', 'pay_account'];
+const parseInfo = ['deal_info', 'construction_unit', 'tech_param', 'decimal', 'precision', 'deal_param', 'display', 'pay_account', 'shenpi'];
 const arrayInfo = ['chapter'];
 const defaultInfo = {
     // 合同信息
@@ -132,6 +132,14 @@ const defaultInfo = {
             phone: '',
         },
     },
+    shenpi: {
+        advance: 1,
+        ledger: 1,
+        revise: 1,
+        stage: 1,
+        change: 1,
+        material: 1,
+    },
 };
 
 module.exports = {

+ 10 - 8
app/controller/ledger_audit_controller.js

@@ -9,6 +9,7 @@
  */
 const auditConst = require('../const/audit').ledger;
 const spreadConst = require('../const/spread');
+const shenpiConst = require('../const/shenpi');
 const measureType = require('../const/tender').measureType;
 
 module.exports = app => {
@@ -74,7 +75,10 @@ module.exports = app => {
                     throw '审核信息错误';
                 }
 
-                const auditors = await ctx.service.ledgerAudit.getAuditorsWithOwner(ctx.tender.id, ctx.tender.data.ledger_times);
+                renderData.user = await ctx.service.projectAccount.getAccountInfoById(ctx.tender.data.user_id);
+                renderData.auditHistory = [];
+                const times = ctx.tender.data.ledger_status === auditConst.status.checkNo ? ctx.tender.data.ledger_times - 1 : ctx.tender.data.ledger_times;
+                const auditors = await ctx.service.ledgerAudit.getAuditorsWithOwner(ctx.tender.id, times);
                 if (ctx.tender.data.user_id !== ctx.session.sessionUser.accountId) {
                     if (auditors.length > 0) {
                         const auditor = auditors.find(function(a) { return a.audit_id === ctx.session.sessionUser.accountId; });
@@ -83,10 +87,6 @@ module.exports = app => {
                         }
                     }
                 }
-
-                renderData.user = await ctx.service.projectAccount.getAccountInfoById(ctx.tender.data.user_id);
-                renderData.auditHistory = [];
-                const times = ctx.tender.data.ledger_status === auditConst.status.checkNo ? ctx.tender.data.ledger_times - 1 : ctx.tender.data.ledger_times;
                 if (times >= 1) {
                     for (let i = 1; i <= times; i++) {
                         renderData.auditHistory.push(await ctx.service.ledgerAudit.getAuditors(ctx.tender.id, i));
@@ -138,13 +138,14 @@ module.exports = app => {
                 if (exist) {
                     throw '该审核人已存在,请勿重复添加';
                 }
-
-                const result = await ctx.service.ledgerAudit.addAuditor(ctx.tender.id, id, ctx.tender.data.ledger_times);
+                const is_gdzs = ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdzs ? 1 : 0;
+                const result = await ctx.service.ledgerAudit.addAuditor(ctx.tender.id, id, ctx.tender.data.ledger_times, is_gdzs);
                 if (!result) {
                     throw '添加审核人失败';
                 }
 
-                responseData.data = await ctx.service.ledgerAudit.getAuditor(ctx.tender.id, id, ctx.tender.data.ledger_times);
+                // responseData.data = await ctx.service.ledgerAudit.getAuditor(ctx.tender.id, id, ctx.tender.data.ledger_times);
+                responseData.data = await ctx.service.ledgerAudit.getAuditorsWithOwner(ctx.tender.id, ctx.tender.data.ledger_times);
             } catch (err) {
                 responseData.err = 1;
                 responseData.msg = err.toString();
@@ -206,6 +207,7 @@ module.exports = app => {
                 ctx.body = { err: 0, msg: '', data: { url: '/tender/' + ctx.tender.id + '/ledger' } };
             } catch (err) {
                 this.log(err);
+                ctx.session.postError = err.toString();
                 ctx.body = this.ajaxErrorBody(err, '上报失败,请刷新页面重试');
             }
         }

+ 6 - 2
app/controller/ledger_controller.js

@@ -18,6 +18,7 @@ const auditConst = audit.ledger;
 const tenderMenu = require('../../config/menu').tenderMenu;
 const measureType = require('../const/tender').measureType;
 const spreadConst = require('../const/spread');
+const shenpiConst = require('../const/shenpi');
 const externalDataConst = require('../const/external_data.js');
 const fs = require('fs');
 const LzString = require('lz-string');
@@ -131,7 +132,9 @@ module.exports = app => {
                 const times = tender.data.ledger_status === auditConst.status.checkNo ? tender.data.ledger_times - 1 : tender.data.ledger_times;
 
                 const curAuditor = await ctx.service.ledgerAudit.getCurAuditor(tender.id, tender.data.ledger_times);
-                const auditors = await ctx.service.ledgerAudit.getAuditorsWithOwner(tender.id, times);
+                const auditors = tender.data.ledger_status === auditConst.status.checkNo && tender.data.user_id !== ctx.session.sessionUser.accountId ?
+                    await ctx.service.ledgerAudit.getAuditorsWithOwner(tender.id, times) :
+                    await ctx.service.ledgerAudit.getAuditorsWithOwner(tender.id, tender.data.ledger_times);
                 const user = await ctx.service.projectAccount.getAccountInfoById(ctx.tender.data.user_id);
                 const auditHistory = [];
                 if (times >= 1) {
@@ -157,7 +160,8 @@ module.exports = app => {
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.ledger.explode),
                     stdBills,
                     stdChapters,
-                    dealBillsPermission: this._canUpdateDealBills(tender.data, auditors.filter(x => {return x.audit_order > 0}))
+                    dealBillsPermission: this._canUpdateDealBills(tender.data, auditors.filter(x => {return x.audit_order > 0})),
+                    shenpiConst,
                 };
                 if ((tender.data.ledger_status === auditConst.status.uncheck || tender.data.ledger_status === auditConst.status.checkNo) && tender.data.user_id === ctx.session.sessionUser.accountId) {
                     // renderData.accountGroup = accountGroup;

+ 24 - 15
app/controller/material_controller.js

@@ -15,6 +15,7 @@ const tenderConst = require('../const/tender');
 const measureType = tenderConst.measureType;
 const accountGroup = require('../const/account_group').group;
 const materialConst = require('../const/material');
+const shenpiConst = require('../const/shenpi');
 const MaterialCalculator = require('../lib/material_calc');
 const sendToWormhole = require('stream-wormhole');
 const fs = require('fs');
@@ -176,6 +177,7 @@ module.exports = app => {
                 measureType,
                 preUrl: '/tender/' + ctx.tender.id + '/measure/material/' + ctx.params.order,
                 material: ctx.material,
+                shenpiConst,
             };
             if ((ctx.material.status === auditConst.status.uncheck || ctx.material.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === ctx.material.user_id) {
                 // data.accountGroup = accountGroup;
@@ -214,7 +216,9 @@ module.exports = app => {
                 }
             }
             // 获取审批流程中左边列表
-            ctx.material.auditors2 = await ctx.service.materialAudit.getAuditorsWithOwner(ctx.material.id, times);
+            ctx.material.auditors2 = ctx.material.status === auditConst.status.checkNo && ctx.material.user_id !== ctx.session.sessionUser.accountId ?
+                await ctx.service.materialAudit.getAuditorsWithOwner(ctx.material.id, times) :
+                await ctx.service.materialAudit.getAuditorsWithOwner(ctx.material.id, ctx.material.times);
             if (ctx.material.status === auditConst.status.uncheck || ctx.material.status === auditConst.status.checkNo) {
                 ctx.material.auditorList = await ctx.service.materialAudit.getAuditors(ctx.material.id, ctx.material.times);
             }
@@ -739,14 +743,14 @@ module.exports = app => {
                 if (exist) {
                     throw '该审核人已存在,请勿重复添加';
                 }
-
-                const result = await ctx.service.materialAudit.addAuditor(ctx.material.id, id, ctx.material.times);
+                const is_gdzs = ctx.tender.info.shenpi.material === shenpiConst.sp_status.gdzs ? 1 : 0;
+                const result = await ctx.service.materialAudit.addAuditor(ctx.material.id, id, ctx.material.times, is_gdzs);
                 if (!result) {
                     throw '添加审核人失败';
                 }
 
-                const audit = await ctx.service.materialAudit.getAuditor(ctx.material.id, id, ctx.material.times);
-                ctx.body = { err: 0, msg: '', data: audit };
+                const auditors = await ctx.service.materialAudit.getAuditorsWithOwner(ctx.material.id, ctx.material.times);
+                ctx.body = { err: 0, msg: '', data: auditors };
             } catch (err) {
                 this.log(err);
                 ctx.body = { err: 1, msg: err.toString(), data: null };
@@ -839,19 +843,24 @@ module.exports = app => {
             }
         }
 
-        _checkMaterialFileCanModify(ctx) {
+        async _checkMaterialFileCanModify(ctx) {
             // 检查登录用户,是否可操作
             const accountId = ctx.session.sessionUser.accountId;
-            if (!ctx.material.curAuditor) {
-                if (ctx.material.status === auditConst.status.uncheck || ctx.material.status === auditConst.status.checkNo && accountId === ctx.material.user_id) {
-                    return;
-                }
-                throw '该调差期当前您无权操作';
-            } else {
-                if (ctx.material.curAuditor.aid === accountId) return;
+            const auditors = await ctx.service.materialAudit.getAuditorsWithOwner(ctx.material.id, ctx.material.times);
+            // console.log(auditors);
+
+            if (auditors.findIndex(item => item.aid === accountId) === -1) {
                 throw '该调差期当前您无权操作';
             }
-
+            // if (!ctx.material.curAuditor) {
+            //     if (ctx.material.status === auditConst.status.uncheck || ctx.material.status === auditConst.status.checkNo && accountId === ctx.material.user_id) {
+            //         return;
+            //     }
+            //     throw '该调差期当前您无权操作';
+            // } else {
+            //     if (ctx.material.curAuditor.aid === accountId) return;
+            //     throw '该调差期当前您无权操作';
+            // }
         }
         /**
          * 上传附件
@@ -860,7 +869,7 @@ module.exports = app => {
         async upload(ctx) {
             let stream;
             try {
-                this._checkMaterialFileCanModify(ctx);
+                await this._checkMaterialFileCanModify(ctx);
                 const parts = this.ctx.multipart({
                     autoFields: true,
                 });

+ 1 - 1
app/controller/revise_controller.js

@@ -526,7 +526,7 @@ module.exports = app => {
                 const data = JSON.parse(ctx.request.body.data);
                 if (!data || !data.rid || data.rid === '') throw '查询的台账修订有误';
                 const reviseInfo = await ctx.service.ledgerRevise.getRevise(ctx.tender.id, data.rid);
-                reviseInfo.end_time_str = reviseInfo.end_time ? ctx.moment(reviseInfo.end_time).format('YYYY-MM-DD hh:mm:ss') : '';
+                reviseInfo.end_time_str = reviseInfo.end_time ? ctx.moment(reviseInfo.end_time).format('YYYY-MM-DD HH:mm:ss') : '';
                 ctx.body = { err: 0, msg: '', data: reviseInfo };
             } catch (err) {
                 this.log(err);

+ 11 - 6
app/controller/stage_controller.js

@@ -13,6 +13,7 @@ const auditConst = require('../const/audit').stage;
 const changeAudit = require('../const/audit').flow;
 const spreadConst = require('../const/spread');
 const tenderConst = require('../const/tender');
+const shenpiConst = require('../const/shenpi');
 const payConst = require('../const/deal_pay.js');
 const externalDataConst = require('../const/external_data.js');
 const changeConst = require('../const/change');
@@ -58,6 +59,7 @@ module.exports = app => {
                     gxby: ctx.session.sessionProject.gxby_status,
                     dagl: ctx.session.sessionProject.dagl_status,
                 },
+                shenpiConst,
             };
             if ((ctx.stage.status === auditConst.status.uncheck || ctx.stage.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === ctx.stage.user_id) {
                 // data.accountGroup = accountGroup;
@@ -149,7 +151,9 @@ module.exports = app => {
                 }
             }
             // 获取审批流程中左边列表
-            ctx.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByListWithOwner(ctx.stage.id, times);
+            ctx.stage.auditors2 = ctx.stage.status === auditConst.status.checkNo && ctx.stage.user_id !== ctx.session.sessionUser.accountId ?
+                await ctx.service.stageAudit.getAuditGroupByListWithOwner(ctx.stage.id, times) :
+                await ctx.service.stageAudit.getAuditGroupByListWithOwner(ctx.stage.id, ctx.stage.times);
             const { status } = ctx.stage;
             if (status === auditConst.status.uncheck || status === auditConst.status.checkNo) {
                 ctx.stage.auditorList = await ctx.service.stageAudit.getAuditors(ctx.stage.id, ctx.stage.times);
@@ -974,14 +978,14 @@ module.exports = app => {
                 if (exist) {
                     throw '该审核人已存在,请勿重复添加';
                 }
-
-                const result = await ctx.service.stageAudit.addAuditor(ctx.stage.id, id, ctx.stage.times);
+                const is_gdzs = ctx.tender.info.shenpi.stage === shenpiConst.sp_status.gdzs ? 1 : 0;
+                const result = await ctx.service.stageAudit.addAuditor(ctx.stage.id, id, ctx.stage.times, is_gdzs);
                 if (!result) {
                     throw '添加审核人失败';
                 }
 
-                const audit = await ctx.service.stageAudit.getAuditor(ctx.stage.id, id, ctx.stage.times);
-                ctx.body = { err: 0, msg: '', data: audit };
+                const auditors = await ctx.service.stageAudit.getAuditGroupByListWithOwner(ctx.stage.id, ctx.stage.times);
+                ctx.body = { err: 0, msg: '', data: auditors };
             } catch (err) {
                 this.log(err);
                 ctx.body = { err: 1, msg: err.toString(), data: null };
@@ -1032,7 +1036,8 @@ module.exports = app => {
                 ctx.body = { err: 0, msg: '', data: [] };
             } catch (err) {
                 this.log(err);
-                ctx.redirect(ctx.request.header.referer);
+                ctx.session.postError = err.toString();
+                // ctx.redirect(ctx.request.header.referer);
                 ctx.body = this.ajaxErrorBody(err, '上报失败');
             }
         }

+ 19 - 15
app/controller/tender_controller.js

@@ -742,6 +742,9 @@ module.exports = app => {
         }
 
         async shenpiSet(ctx) {
+            if (ctx.session.sessionUser.is_admin === 0) {
+                ctx.request.headers.referer ? ctx.redirect(ctx.request.headers.referer) : ctx.redirect('/list');
+            }
             // 获取所有项目参与者
             const accountList = await ctx.service.projectAccount.getAllDataByCondition({
                 where: { project_id: ctx.session.sessionProject.id, enable: 1 },
@@ -752,7 +755,7 @@ module.exports = app => {
                 return { groupName: item, groupList };
             });
             for (const sp of shenpiConst.sp_lc) {
-                sp.status = ctx.tender.info.shenpi ? JSON.parse(ctx.tender.info.shenpi)[sp.code] : shenpiConst.sp_status.sqspr;
+                sp.status = ctx.tender.info.shenpi ? ctx.tender.info.shenpi[sp.code] : shenpiConst.sp_status.sqspr;
                 if (sp.status === shenpiConst.sp_status.gdspl) {
                     sp.auditList = await ctx.service.shenpiAudit.getAuditList(ctx.tender.id, sp.type, sp.status);
                 } else if (sp.status === shenpiConst.sp_status.gdzs) {
@@ -778,20 +781,21 @@ module.exports = app => {
                 if (ctx.session.sessionUser.is_admin === 0) {
                     throw '你没有权限修改审批流程';
                 }
-                let postData = {};
-                if (!ctx.tender.info.shenpi) {
-                    for (const sp of shenpiConst.sp_lc) {
-                        if (sp.code === data.code) {
-                            postData[sp.code] = data.status;
-                        } else {
-                            postData[sp.code] = shenpiConst.sp_status.sqspr;
-                        }
-                    }
-                } else {
-                    postData = JSON.parse(ctx.tender.info.shenpi);
-                    postData[data.code] = data.status;
-                }
-                await ctx.service.tenderInfo.saveTenderInfo(ctx.tender.id, { shenpi: JSON.stringify(postData) });
+                // let postData = {};
+                // if (!ctx.tender.info.shenpi) {
+                //     for (const sp of shenpiConst.sp_lc) {
+                //         if (sp.code === data.code) {
+                //             postData[sp.code] = data.status;
+                //         } else {
+                //             postData[sp.code] = shenpiConst.sp_status.sqspr;
+                //         }
+                //     }
+                // } else {
+                const postData = ctx.tender.info.shenpi;
+                postData[data.code] = data.status;
+                // }
+                // console.log(postData);
+                await ctx.service.tenderInfo.saveTenderInfo(ctx.tender.id, { shenpi: postData });
                 let auditList = [];
                 if (data.status === shenpiConst.sp_status.gdspl) {
                     auditList = await ctx.service.shenpiAudit.getAuditList(ctx.tender.id, shenpiConst.sp_type[data.code], data.status);

+ 1 - 1
app/extend/helper.js

@@ -1190,7 +1190,7 @@ module.exports = {
                 checkData[f.tp] = b[f.tp] || 0;
                 calcData[f.tp] = this.mul(b.unit_price, b[f.qty], decimal.tp) || 0;
             }
-            if (!_.isMatch(checkData, calcData)) {
+            if (!this._.isMatch(checkData, calcData)) {
                 result.error.push({
                     ledger_id: b.ledger_id,
                     b_code: b.b_code,

+ 6 - 1
app/lib/analysis_excel.js

@@ -281,7 +281,11 @@ class ImportBaseTree {
 
     calculateLeafWithPos () {
         for (const node of this.items) {
-            if (node.children && node.children.length > 0) { continue; }
+            if (node.children && node.children.length > 0) {
+                node.unit_price = null;
+                node.quantity = null;
+                node.total_price = null;
+            }
             if (!node.pos || node.pos.length === 0) { continue; }
             node.quantity = this.ctx.helper.sum(_.map(node.pos, 'quantity'));
             if (node.quantity && node.unit_price) {
@@ -353,6 +357,7 @@ class AnalysisExcelTree {
         node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
         const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
         node.quantity = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.quantity]), precision.value);
+        node.sgfh_qty = node.quantity;
         node.unit_price = aeUtils.toNumber(row[this.colsDef.unit_price]);
         node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
         node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]);

+ 67 - 0
app/middleware/ledger_audit_check.js

@@ -0,0 +1,67 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Ellisran
+ * @date 2020/10/15
+ * @version
+ */
+
+const status = require('../const/audit').ledger.status;
+const shenpiConst = require('../const/shenpi');
+const _ = require('lodash');
+
+module.exports = options => {
+    /**
+     * 标段校验 中间件
+     * 1. 读取标段数据(包括属性)
+     * 2. 检验用户是否可见标段(不校验具体权限)
+     *
+     * @param {function} next - 中间件继续执行的方法
+     * @return {void}
+     */
+    return function* ledgerAuditCheck(next) {
+        try {
+            if ((this.tender.data.ledger_status === status.uncheck || this.tender.data.ledger_status === status.checkNo) && this.tender.info.shenpi.ledger !== shenpiConst.sp_status.sqspr) {
+                const shenpi_status = this.tender.info.shenpi.ledger;
+                // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
+                const auditList = yield this.service.ledgerAudit.getAllDataByCondition({ where: { tender_id: this.tender.id, times: this.tender.data.ledger_times } });
+                const auditIdList = _.map(auditList, 'audit_id');
+                if (shenpi_status === shenpiConst.sp_status.gdspl) {
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: this.tender.id, sp_type: shenpiConst.sp_type.ledger, sp_status: shenpi_status } });
+                    const shenpiIdList = _.map(shenpiList, 'audit_id');
+                    // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
+                    if (!_.isEqual(auditIdList, shenpiIdList)) {
+                        yield this.service.ledgerAudit.updateNewAuditList(this.tender.data, shenpiIdList);
+                    }
+                } else if (shenpi_status === shenpiConst.sp_status.gdzs) {
+                    const shenpiInfo = yield this.service.shenpiAudit.getDataByCondition({ tid: this.tender.id, sp_type: shenpiConst.sp_type.ledger, sp_status: shenpi_status });
+                    // 判断最后一个id是否与固定终审id相同,不同则删除原审批流中如果存在的id和添加终审
+                    if (shenpiInfo && shenpiInfo.audit_id !== _.last(auditIdList)) {
+                        yield this.service.ledgerAudit.updateLastAudit(this.tender.data, auditList, shenpiInfo.audit_id);
+                    } else if (!shenpiInfo) {
+                        // 不存在终审人的状态下这里恢复为授权审批人
+                        this.tender.info.shenpi.ledger = shenpiConst.sp_status.sqspr;
+                    }
+                }
+            }
+            yield next;
+        } catch (err) {
+            console.log(err);
+            // 输出错误到日志
+            if (err.stack) {
+                this.logger.error(err);
+            } else {
+                this.getLogger('fail').info(JSON.stringify({
+                    error: err,
+                    project: this.session.sessionProject,
+                    user: this.session.sessionUser,
+                    body: this.session.body,
+                }));
+            }
+            // 重定向值标段管理
+            this.redirect(this.request.headers.referer);
+        }
+    };
+};

+ 25 - 0
app/middleware/material_check.js

@@ -8,6 +8,7 @@
  */
 
 const status = require('../const/audit').material.status;
+const shenpiConst = require('../const/shenpi');
 const _ = require('lodash');
 
 module.exports = options => {
@@ -103,6 +104,30 @@ module.exports = options => {
             // 调差的readOnly 指表格和页面只能看不能改,和审批无关
             material.readOnly = !((material.status === status.uncheck || material.status === status.checkNo) && accountId === material.user_id);
             this.material = material;
+            // 根据状态判断是否需要更新审批人列表
+            if ((material.status === status.uncheck || material.status === status.checkNo) && this.tender.info.shenpi.material !== shenpiConst.sp_status.sqspr) {
+                const shenpi_status = this.tender.info.shenpi.material;
+                // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
+                const auditList = yield this.service.materialAudit.getAllDataByCondition({ where: { mid: material.id, times: material.times } });
+                const auditIdList = _.map(auditList, 'aid');
+                if (shenpi_status === shenpiConst.sp_status.gdspl) {
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: material.tid, sp_type: shenpiConst.sp_type.material, sp_status: shenpi_status } });
+                    const shenpiIdList = _.map(shenpiList, 'audit_id');
+                    // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
+                    if (!_.isEqual(auditIdList, shenpiIdList)) {
+                        yield this.service.materialAudit.updateNewAuditList(material, shenpiIdList);
+                    }
+                } else if (shenpi_status === shenpiConst.sp_status.gdzs) {
+                    const shenpiInfo = yield this.service.shenpiAudit.getDataByCondition({ tid: material.tid, sp_type: shenpiConst.sp_type.material, sp_status: shenpi_status });
+                    // 判断最后一个id是否与固定终审id相同,不同则删除原审批流中如果存在的id和添加终审
+                    if (shenpiInfo && shenpiInfo.audit_id !== _.last(auditIdList)) {
+                        yield this.service.materialAudit.updateLastAudit(material, auditList, shenpiInfo.audit_id);
+                    } else if (!shenpiInfo) {
+                        // 不存在终审人的状态下这里恢复为授权审批人
+                        this.tender.info.shenpi.material = shenpiConst.sp_status.sqspr;
+                    }
+                }
+            }
             yield next;
         } catch (err) {
             console.log(err);

+ 25 - 0
app/middleware/stage_check.js

@@ -9,6 +9,7 @@
 
 const status = require('../const/audit').stage.status;
 const reviseStatus = require('../const/audit').revise.status;
+const shenpiConst = require('../const/shenpi');
 const _ = require('lodash');
 
 module.exports = options => {
@@ -114,6 +115,30 @@ module.exports = options => {
             const lastRevise = yield this.service.ledgerRevise.getLastestRevise(this.tender.id);
             stage.revising = (lastRevise && lastRevise.status !== reviseStatus.checked) || false;
             this.stage = stage;
+            // 根据状态判断是否需要更新审批人列表
+            if ((stage.status === status.uncheck || stage.status === status.checkNo) && this.tender.info.shenpi.stage !== shenpiConst.sp_status.sqspr) {
+                const shenpi_status = this.tender.info.shenpi.stage;
+                // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
+                const auditList = yield this.service.stageAudit.getAllDataByCondition({ where: { sid: stage.id, times: stage.times } });
+                const auditIdList = _.map(auditList, 'aid');
+                if (shenpi_status === shenpiConst.sp_status.gdspl) {
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: stage.tid, sp_type: shenpiConst.sp_type.stage, sp_status: shenpi_status } });
+                    const shenpiIdList = _.map(shenpiList, 'audit_id');
+                    // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
+                    if (!_.isEqual(auditIdList, shenpiIdList)) {
+                        yield this.service.stageAudit.updateNewAuditList(stage, shenpiIdList);
+                    }
+                } else if (shenpi_status === shenpiConst.sp_status.gdzs) {
+                    const shenpiInfo = yield this.service.shenpiAudit.getDataByCondition({ tid: stage.tid, sp_type: shenpiConst.sp_type.stage, sp_status: shenpi_status });
+                    // 判断最后一个id是否与固定终审id相同,不同则删除原审批流中如果存在的id和添加终审
+                    if (shenpiInfo && shenpiInfo.audit_id !== _.last(auditIdList)) {
+                        yield this.service.stageAudit.updateLastAudit(stage, auditList, shenpiInfo.audit_id);
+                    } else if (!shenpiInfo) {
+                        // 不存在终审人的状态下这里恢复为授权审批人
+                        this.tender.info.shenpi.stage = shenpiConst.sp_status.sqspr;
+                    }
+                }
+            }
             yield next;
         } catch (err) {
             this.helper.log(err);

+ 42 - 44
app/public/js/ledger.js

@@ -2990,44 +2990,38 @@ $(document).ready(function() {
     $('dl').on('click', 'dd', function () {
         const auditorId = parseInt($(this).data('id'))
         if (auditorId) {
-            postData('/tender/' + getTenderId() + '/ledger/audit/add', { auditorId }, (data) => {
+            postData('/tender/' + getTenderId() + '/ledger/audit/add', { auditorId }, (datas) => {
                 const html = [];
-                html.push('<li class="list-group-item" auditorId="' + data.audit_id + '"><a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
-                html.push('<span>');
-                html.push(data.audit_order + ' ');
-                html.push(data.name + ' ');
-                html.push('</span>');
-                html.push('<small class="text-muted">');
-                html.push(data.role);
-                html.push('</small></li>');
-                $('#auditors').append(html.join(''));
-
                 // 如果是重新上报,添加到重新上报列表中
                 const auditorshtml = [];
-                // 重新上报时。令其它的审批人流程图标转换
-                $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                for (let i = 0; i < $('#auditors-list li').length; i++) {
-                    $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
-                    $('#auditors-list2 li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
-                }
-                // 添加新审批人
-                auditorshtml.push('<li class="list-group-item" data-auditid="' + data.audit_id + '">');
-                auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
-                auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                auditorshtml.push('<span class="pull-right">终审</span>');
-                auditorshtml.push('</li>');
-                $('#auditors-list').append(auditorshtml.join(''));
-
-                const auditorshtml2 = [];
-                // 重新上报时。令其它的审批人流程图标转换
-                $('#auditors-list2 li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                // 添加新审批人
-                auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.audit_id + '">');
-                auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
-                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                auditorshtml2.push('<span class="pull-right">终审</span>');
-                auditorshtml2.push('</h5></li>');
-                $('#auditors-list2').append(auditorshtml2.join(''));
+                for (const [index,data] of datas.entries()) {
+                    if (index !== 0) {
+                        html.push('<li class="list-group-item" auditorId="' + data.audit_id + '">');
+                        if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== datas.length)) {
+                            html.push('<a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
+                        }
+                        html.push('<span>');
+                        html.push(data.audit_order + ' ');
+                        html.push(data.name + ' ');
+                        html.push('</span>');
+                        html.push('<small class="text-muted">');
+                        html.push(data.role);
+                        html.push('</small></li>');
+                    }
+                    auditorshtml.push('<li class="list-group-item" data-auditid="' + data.audit_id + '">');
+                    auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
+                    auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                    if (index === 0) {
+                        auditorshtml.push('<span class="pull-right">原报</span>');
+                    } else if (index+1 === datas.length) {
+                        auditorshtml.push('<span class="pull-right">终审</span>');
+                    } else {
+                        auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+                    }
+                    auditorshtml.push('</li>');
+                }
+                $('#auditors').html(html.join(''));
+                $('#auditors-list').html(auditorshtml.join(''));
             });
         }
     });
@@ -3045,19 +3039,19 @@ $(document).ready(function() {
 
             // 如果是重新上报
             // 令最后一个图标转换
-            $('#auditors-list li[data-auditid="' + data.auditorId + '"]').remove();
+            $('#auditors-list li[data-auditorid="' + data.auditorId + '"]').remove();
             if ($('#auditors-list li').length !== 0 && !$('#auditors-list li i').hasClass('fa-stop-circle')) {
                 $('#auditors-list li').eq($('#auditors-list li').length-1).children('i')
                     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
             }
-            $('#auditors-list2 li[data-auditid="' + data.auditorId + '"]').remove();
-            if ($('#auditors-list2 li').length !== 0 && !$('#auditors-list2 li i').hasClass('fa-stop-circle')) {
-                $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
-                    .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
-            }
+            // $('#auditors-list2 li[data-auditid="' + data.auditorId + '"]').remove();
+            // if ($('#auditors-list2 li').length !== 0 && !$('#auditors-list2 li i').hasClass('fa-stop-circle')) {
+            //     $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
+            //         .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
+            // }
             for (let i = 0; i < $('#auditors-list li').length; i++) {
-                $('#auditors-list li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审')
-                $('#auditors-list2 li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2 li').length ? '终' : transFormToChinese(i+1)) + '审')
+                $('#auditors-list li').eq(i).find('.pull-right').text(i === 0 ? '原报' : (i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审')
+                // $('#auditors-list2 li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2 li').length ? '终' : transFormToChinese(i+1)) + '审')
             }
         });
     });
@@ -3219,7 +3213,11 @@ $(document).ready(function() {
 // 检查上报情况
 function checkAuditorFrom () {
     if ($('#auditors li').length === 0) {
-        toastr.error('请先选择审批人,再上报数据');
+        if(shenpi_status === shenpiConst.sp_status.gdspl) {
+            toastr.error('请联系管理员添加审批人');
+        } else {
+            toastr.error('请先选择审批人,再上报数据');
+        }
         return false;
     } else {
         $('#hide-all').show();

+ 62 - 43
app/public/js/material_audit.js

@@ -79,46 +79,61 @@ $(document).ready(function () {
 
     // 添加到审批流程中
     $('dl').on('click', 'dd', function () {
-        const id = parseInt($(this).data('id'))
+        const id = parseInt($(this).data('id'));
         if (id) {
-            postData(getUrlPre() + '/audit/add', { auditorId: id }, (data) => {
+            postData(getUrlPre() + '/audit/add', { auditorId: id }, (datas) => {
                 const html = [];
-                html.push('<li class="list-group-item" auditorId="'+ data.aid +'"><a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
-                html.push('<span>');
-                html.push(data.order + ' ');
-                html.push(data.name + ' ');
-                html.push('</span>');
-                html.push('<small class="text-muted">');
-                html.push(data.role);
-                html.push('</small></li>');
-                $('#auditors').append(html.join(''));
-
                 // 如果是重新上报,添加到重新上报列表中
                 const auditorshtml = [];
-                // 重新上报时。令其它的审批人流程图标转换
-                $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                for (let i = 0; i < $('#auditors-list li').length; i++) {
-                    $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
-                    $('#auditors-list2 li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
+                for (const [index,data] of datas.entries()) {
+                    if (index !== 0) {
+                        html.push('<li class="list-group-item" auditorId="'+ data.aid +'">');
+                        if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== datas.length)) {
+                            html.push('<a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
+                        }
+                        html.push('<span>');
+                        html.push(data.order + ' ');
+                        html.push(data.name + ' ');
+                        html.push('</span>');
+                        html.push('<small class="text-muted">');
+                        html.push(data.role);
+                        html.push('</small></li>');
+                    }
+                    // 添加新审批人流程修改
+                    auditorshtml.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
+                    auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
+                    auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                    if (index === 0) {
+                        auditorshtml.push('<span class="pull-right">原报</span>');
+                    } else if (index+1 === datas.length) {
+                        auditorshtml.push('<span class="pull-right">终审</span>');
+                    } else {
+                        auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+                    }
+                    auditorshtml.push('</li>');
                 }
-                // 添加新审批人
-                auditorshtml.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
-                auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
-                auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                auditorshtml.push('<span class="pull-right">终审</span>');
-                auditorshtml.push('</li>');
-                $('#auditors-list').append(auditorshtml.join(''));
+                $('#auditors').html(html.join(''));
+
 
-                const auditorshtml2 = [];
                 // 重新上报时。令其它的审批人流程图标转换
-                $('#auditors-list2 li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                // 添加新审批人
-                auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
-                auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
-                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                auditorshtml2.push('<span class="pull-right">终审</span>');
-                auditorshtml2.push('</h5></li>');
-                $('#auditors-list2').append(auditorshtml2.join(''));
+                // $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
+                // for (let i = 0; i < $('#auditors-list li').length; i++) {
+                //     $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
+                //     $('#auditors-list2 li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
+                // }
+
+                $('#auditors-list').html(auditorshtml.join(''));
+
+                // const auditorshtml2 = [];
+                // // 重新上报时。令其它的审批人流程图标转换
+                // $('#auditors-list2 li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
+                // // 添加新审批人
+                // auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
+                // auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
+                // auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                // auditorshtml2.push('<span class="pull-right">终审</span>');
+                // auditorshtml2.push('</h5></li>');
+                // $('#auditors-list2').append(auditorshtml2.join(''));
             });
         }
     });
@@ -137,19 +152,19 @@ $(document).ready(function () {
 
             // 如果是重新上报
             // 令最后一个图标转换
-            $('#auditors-list li[data-auditid="' + data.auditorId + '"]').remove();
+            $('#auditors-list li[data-auditorid="' + data.auditorId + '"]').remove();
             if ($('#auditors-list li').length !== 0 && !$('#auditors-list li i').hasClass('fa-stop-circle')) {
                 $('#auditors-list li').eq($('#auditors-list li').length-1).children('i')
                     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
             }
-            $('#auditors-list2 li[data-auditid="' + data.auditorId + '"]').remove();
-            if ($('#auditors-list2 li').length !== 0 && !$('#auditors-list2 li i').hasClass('fa-stop-circle')) {
-                $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
-                    .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
-            }
-            for (let i = 0; i < $('#auditors-list').length; i++) {
-                $('#auditors-list').eq(i).find('.pull-right').text((i+1 === $('#auditors-list').length ? '终' : transFormToChinese(i+1)) + '审');
-                $('#auditors-list2').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2').length ? '终' : transFormToChinese(i+1)) + '审');
+            // $('#auditors-list2 li[data-auditid="' + data.auditorId + '"]').remove();
+            // if ($('#auditors-list2 li').length !== 0 && !$('#auditors-list2 li i').hasClass('fa-stop-circle')) {
+            //     $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
+            //         .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
+            // }
+            for (let i = 0; i < $('#auditors-list li').length; i++) {
+                $('#auditors-list li').eq(i).find('.pull-right').text(i === 0 ? '原报' : (i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审');
+                // $('#auditors-list2').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2').length ? '终' : transFormToChinese(i+1)) + '审');
             }
         });
     });
@@ -169,7 +184,11 @@ $(document).ready(function () {
 // 检查上报情况
 function checkAuditorFrom () {
     if ($('#auditors li').length === 0) {
-        toast('请先选择审批人,再上报数据', 'error', 'exclamation-circle');
+        if(shenpi_status === shenpiConst.sp_status.gdspl) {
+            toastr.err('请联系管理员添加审批人');
+        } else {
+            toastr.err('请先选择审批人,再上报数据');
+        }
         return false;
     }
     $('#hide-all').show();

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

@@ -310,7 +310,7 @@ const showSideTools = function (show) {
                     d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
                 }
 
-                $('#' + setting.id + '-time').html('检查时间:' + moment(data.check_time).format('YYYY-MM-DD hh:mm:ss'));
+                $('#' + setting.id + '-time').html('检查时间:' + moment(data.check_time).format('YYYY-MM-DD HH:mm:ss'));
                 SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Data, data.warning_data);
                 if (!his && setting.storeKey) {
                     setLocalCache(setting.storeKey, JSON.stringify(data));

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

@@ -11,7 +11,7 @@
 $(document).ready(function () {
     let timer = null;
     let oldSearchVal = null;
-    $('body').bind('input propertychange', '.gr-search', function(e) {
+    $('body').on('input propertychange', '.gr-search', function(e) {
         oldSearchVal = e.target.value;
         timer && clearTimeout(timer);
         timer = setTimeout(() => {

+ 52 - 54
app/public/js/stage_audit.js

@@ -114,59 +114,53 @@ $(document).ready(function () {
     //     });
     // });
     // 审批人分组选择
-    $('#account_group').change(function () {
-        let account_html = '<option value="0">选择审批人</option>';
-        for (const account of accountList) {
-            if ((parseInt($(this).val()) === 0 || parseInt($(this).val()) === account.account_group) && account.id !== parseInt(userID)) {
-                const role = account.role !== '' ? '(' + account.role + ')' : '';
-                const company = account.company !== '' ? ' -' + account.company : '';
-                account_html += '<option value="' + account.id + '">' + account.name + role + company + '</option>';
-            }
-        }
-        $('#account_list').html(account_html);
-    });
+    // $('#account_group').change(function () {
+    //     let account_html = '<option value="0">选择审批人</option>';
+    //     for (const account of accountList) {
+    //         if ((parseInt($(this).val()) === 0 || parseInt($(this).val()) === account.account_group) && account.id !== parseInt(userID)) {
+    //             const role = account.role !== '' ? '(' + account.role + ')' : '';
+    //             const company = account.company !== '' ? ' -' + account.company : '';
+    //             account_html += '<option value="' + account.id + '">' + account.name + role + company + '</option>';
+    //         }
+    //     }
+    //     $('#account_list').html(account_html);
+    // });
     // 添加到审批流程中
     $('dl').on('click', 'dd', function () {
         const id = parseInt($(this).data('id'));
         if (id !== 0) {
-            postData(getUrlPre() + '/audit/add', { auditorId: id }, (data) => {
+            postData(getUrlPre() + '/audit/add', { auditorId: id }, (datas) => {
                 const html = [];
-                html.push('<li class="list-group-item" auditorId="'+ data.aid +'"><a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
-                html.push('<span>');
-                html.push(data.order + ' ');
-                html.push(data.name + ' ');
-                html.push('</span>');
-                html.push('<small class="text-muted">');
-                html.push(data.role);
-                html.push('</small></li>');
-                $('#auditors').append(html.join(''));
-
                 // 如果是重新上报,添加到重新上报列表中
                 const auditorshtml = [];
-                // 重新上报时。令其它的审批人流程图标转换
-                $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                for (let i = 0; i < $('#auditors-list li').length; i++) {
-                    $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
-                    $('#auditors-list2 li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
+                for (const [index,data] of datas.entries()) {
+                    if (index !== 0) {
+                        html.push('<li class="list-group-item" auditorId="'+ data.aid +'">');
+                        if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== datas.length)) {
+                            html.push('<a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
+                        }
+                        html.push('<span>');
+                        html.push(data.order + ' ');
+                        html.push(data.name + ' ');
+                        html.push('</span>');
+                        html.push('<small class="text-muted">');
+                        html.push(data.role);
+                        html.push('</small></li>');
+                    }
+                    auditorshtml.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
+                    auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
+                    auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                    if (index === 0) {
+                        auditorshtml.push('<span class="pull-right">原报</span>');
+                    } else if (index+1 === datas.length) {
+                        auditorshtml.push('<span class="pull-right">终审</span>');
+                    } else {
+                        auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+                    }
+                    auditorshtml.push('</li>');
                 }
-                // 添加新审批人
-                auditorshtml.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
-                auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
-                auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                auditorshtml.push('<span class="pull-right">终审</span>');
-                auditorshtml.push('</li>');
-                $('#auditors-list').append(auditorshtml.join(''));
-
-                const auditorshtml2 = [];
-                // 重新上报时。令其它的审批人流程图标转换
-                $('#auditors-list2 li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-                // 添加新审批人
-                auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
-                auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
-                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
-                auditorshtml2.push('<span class="pull-right">终审</span>');
-                auditorshtml2.push('</h5></li>');
-                $('#auditors-list2').append(auditorshtml2.join(''));
+                $('#auditors').html(html.join(''));
+                $('#auditors-list').html(auditorshtml.join(''));
             });
         }
     });
@@ -185,19 +179,19 @@ $(document).ready(function () {
 
             // 如果是重新上报
             // 令最后一个图标转换
-            $('#auditors-list li[data-auditid="' + data.auditorId + '"]').remove();
+            $('#auditors-list li[data-auditorid="' + data.auditorId + '"]').remove();
             if ($('#auditors-list li').length !== 0 && !$('#auditors-list li i').hasClass('fa-stop-circle')) {
                 $('#auditors-list li').eq($('#auditors-list li').length-1).children('i')
                     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
             }
-            $('#auditors-list2 li[data-auditid="' + data.auditorId + '"]').remove();
-            if ($('#auditors-list2 li').length !== 0 && !$('#auditors-list2 li i').hasClass('fa-stop-circle')) {
-                $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
-                    .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
-            }
+            // $('#auditors-list2 li[data-auditid="' + data.auditorId + '"]').remove();
+            // if ($('#auditors-list2 li').length !== 0 && !$('#auditors-list2 li i').hasClass('fa-stop-circle')) {
+                // $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
+                //     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
+            // }
             for (let i = 0; i < $('#auditors-list li').length; i++) {
-                $('#auditors-list li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审');
-                $('#auditors-list2 li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2 li').length ? '终' : transFormToChinese(i+1)) + '审');
+                $('#auditors-list li').eq(i).find('.pull-right').text(i === 0 ? '原报' : (i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审');
+                // $('#auditors-list2 li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2 li').length ? '终' : transFormToChinese(i+1)) + '审');
             }
         });
     });
@@ -252,7 +246,11 @@ $(document).ready(function () {
 // 检查上报情况
 function checkAuditorFrom () {
     if ($('#auditors li').length === 0) {
-        toastr.error('请先选择审批人,再上报数据');
+        if(shenpi_status === shenpiConst.sp_status.gdspl) {
+            toastr.error('请联系管理员添加审批人');
+        } else {
+            toastr.error('请先选择审批人,再上报数据');
+        }
         return false;
     }
     $('#hide-all').show();

+ 4 - 2
app/public/js/stage_im.js

@@ -261,9 +261,11 @@ const stageIm = (function () {
                 im.org[f] = im[f];
             }
         }
-        im.custom_define = detail.custom_define ? detail.custom_define.split(',') : imFields;
+        im.custom_define = detail.custom_define ? detail.custom_define.split(',') : [];
         _.assignInWith(im, detail, function (oV, sV, key) {
-            return (im.custom_define.indexOf(key) > -1) ? sV : ((resetFields.indexOf(key) > -1) ? im.org[key] : oV);
+            return im.custom_define.length > 0
+                ? (im.custom_define.indexOf(key) > -1 ? sV : ((resetFields.indexOf(key) > -1) ? im.org[key] : oV))
+                : (imFields.indexOf(key) > -1 ? sV : ((resetFields.indexOf(key) > -1) ? im.org[key] : oV));
         });
         im.uuid = detail.uuid;
         im.doc_code = detail.doc_code;

+ 3 - 2
app/router.js

@@ -9,6 +9,7 @@ module.exports = app => {
     const projectManagerCheck = app.middlewares.projectManagerCheck();
     // 标段读取中间件
     const tenderCheck = app.middlewares.tenderCheck();
+    const ledgerAuditCheck = app.middlewares.ledgerAuditCheck();
     const uncheckTenderCheck = app.middlewares.uncheckTenderCheck();
     // 期读取中间件
     const stageCheck = app.middlewares.stageCheck();
@@ -131,7 +132,7 @@ module.exports = app => {
     app.get('/tender/:id/cooperation', sessionAuth, tenderCheck, 'tenderController.tenderCooperation');
 
     // 台账管理相关
-    app.get('/tender/:id/ledger', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.explode');
+    app.get('/tender/:id/ledger', sessionAuth, tenderCheck, uncheckTenderCheck, ledgerAuditCheck, 'ledgerController.explode');
     app.post('/tender/:id/ledger/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.loadExplodeData');
     app.post('/tender/:id/ledger/get-children', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.getChildren');
     app.post('/tender/:id/ledger/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.update');
@@ -140,7 +141,7 @@ module.exports = app => {
     app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.posUpdate');
     app.post('/tender/:id/pos/paste', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.posPaste');
     app.post('/tender/:id/ledger/deal2sgfh', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.deal2sgfh');
-    app.post('/tender/:id/ledger/check', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.check');
+    app.post('/tender/:id/ledger/check', sessionAuth, tenderCheck, uncheckTenderCheck, ledgerAuditCheck, 'ledgerController.check');
 
     // 台账审批相关
     app.get('/tender/:id/ledger/audit', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.index');

+ 79 - 14
app/service/ledger_audit.js

@@ -13,6 +13,7 @@ const smsTypeConst = require('../const/sms_type');
 const SMS = require('../lib/sms');
 const SmsAliConst = require('../const/sms_alitemplate');
 const wxConst = require('../const/wechat_template');
+const shenpiConst = require('../const/shenpi');
 const pushType = require('../const/audit').pushType;
 
 module.exports = app => {
@@ -148,17 +149,28 @@ module.exports = app => {
          * @param {Number} times - 第几次审批
          * @return {Promise<number>}
          */
-        async addAuditor(tenderId, auditorId, times = 1) {
-            const newOrder = await this.getNewOrder(tenderId, times);
-            const data = {
-                tender_id: tenderId,
-                audit_id: auditorId,
-                times,
-                audit_order: newOrder,
-                status: auditConst.status.uncheck,
-            };
-            const result = await this.db.insert(this.tableName, data);
-            return (result.effectRows = 1);
+        async addAuditor(tenderId, auditorId, times = 1, is_gdzs = 0) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                let newOrder = await this.getNewOrder(tenderId, times);
+                // 判断是否存在固定终审,存在则newOrder - 1并使终审order+1
+                newOrder = is_gdzs === 1 ? newOrder - 1 : newOrder;
+                if (is_gdzs) await this._syncOrderByDelete(transaction, tenderId, newOrder, times, '+');
+                const data = {
+                    tender_id: tenderId,
+                    audit_id: auditorId,
+                    times,
+                    audit_order: newOrder,
+                    status: auditConst.status.uncheck,
+                };
+                const result = await transaction.insert(this.tableName, data);
+                await transaction.commit();
+                return (result.effectRows = 1);
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+            return false;
         }
 
         /**
@@ -170,7 +182,7 @@ module.exports = app => {
          * @return {Promise<*>}
          * @private
          */
-        async _syncOrderByDelete(transaction, tenderId, order, times) {
+        async _syncOrderByDelete(transaction, tenderId, order, times, selfOperate = '-') {
             this.initSqlBuilder();
             this.sqlBuilder.setAndWhere('tender_id', {
                 value: tenderId,
@@ -186,7 +198,7 @@ module.exports = app => {
             });
             this.sqlBuilder.setUpdateData('audit_order', {
                 value: 1,
-                selfOperate: '-',
+                selfOperate: selfOperate,
             });
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
             const data = await transaction.query(sql, sqlParam);
@@ -230,7 +242,11 @@ module.exports = app => {
         async start(tenderId, times = 1) {
             const audit = await this.getDataByCondition({ tender_id: tenderId, times, audit_order: 1 });
             if (!audit) {
-                throw '审核人信息错误';
+                if(this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdspl) {
+                    throw '请联系管理员添加审批人';
+                } else {
+                    throw '请先选择审批人,再上报数据';
+                }
             }
             const sum = await this.ctx.service.ledger.addUp({ tender_id: tenderId /* , is_leaf: true*/ });
 
@@ -511,6 +527,55 @@ module.exports = app => {
             result.unshift(user);
             return result;
         }
+
+        async updateNewAuditList(tender, newIdList) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 先删除旧的审批流,再添加新的
+                transaction.delete(this.tableName, { tender_id: tender.id, times: tender.ledger_times });
+                const newAuditors = [];
+                let order = 1;
+                for (const aid of newIdList) {
+                    newAuditors.push({
+                        tender_id: tender.id, audit_id: aid,
+                        times: tender.ledger_times, audit_order: order, status: auditConst.status.uncheck,
+                    });
+                    order++;
+                }
+                if(newAuditors.length > 0) await transaction.insert(this.tableName, newAuditors);
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async updateLastAudit(tender, auditList, lastId) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 先判断auditList里的aid是否与lastId相同,相同则删除并重新更新order
+                const idList = this._.map(auditList, 'audit_id');
+                let order = idList.length + 1;
+                if (idList.indexOf(lastId) !== -1) {
+                    transaction.delete(this.tableName, { tender_id: tender.id, times: tender.ledger_times, audit_id: lastId });
+                    const audit = this._.find(auditList, { 'audit_id': lastId });
+                    // 顺移之后审核人流程顺序
+                    await this._syncOrderByDelete(transaction, tender.id, audit.audit_order, tender.ledger_times);
+                    order = order - 1;
+                }
+
+                // 添加终审
+                const newAuditor = {
+                    tender_id: tender.id, audit_id: lastId,
+                    times: tender.ledger_times, audit_order: order, status: auditConst.status.uncheck,
+                };
+                await transaction.insert(this.tableName, newAuditor);
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return LedgerAudit;

+ 21 - 30
app/service/login_logging.js

@@ -73,47 +73,38 @@ module.exports = app => {
             isp && (address += isp + ' ');
             ip && (address += `(${ip})`);
             return address;
+
         }
 
         /**
          * 发送请求获取详细地址
          * @param {String} ip - ip地址
-         * @param {Number} max - 最大重试次数
          * @return {Object} the result of request
          * @private
          */
-        async sendRequest(ip, max = 3) {
+        async sendRequest(ip) {
             return new Promise(resolve => {
-                const start = () => {
-                    if (max <= 0) {
-                        resolve(); // 已达到最大重试次数,返回空的执行承若
-                    }
-                    max--;
-                    this.ctx.curl(`https://api01.aliyun.venuscn.com/ip?ip=${ip}`, {
-                        dateType: 'json',
-                        encoding: 'utf8',
-                        timeout: 2000,
-                        headers: {
-                            Authorization: 'APPCODE 85c64bffe70445c4af9df7ae31c7bfcc',
-                        },
-                    }).then(({ status, data }) => {
-                        if (status === 200) {
-                            const result = JSON.parse(data.toString()).data;
-                            if (!result.ip) {
-                                start();
-                            } else {
-                                max++;
-                                resolve(result);
-                            }
+                this.ctx.curl(`https://api01.aliyun.venuscn.com/ip?ip=${ip}`, {
+                    dateType: 'json',
+                    encoding: 'utf8',
+                    timeout: 2000,
+                    headers: {
+                        Authorization: 'APPCODE 85c64bffe70445c4af9df7ae31c7bfcc',
+                    },
+                }).then(({ status, data }) => {
+                    if (status === 200) {
+                        const result = JSON.parse(data.toString()).data;
+                        if (!result.ip) {
+                            resolve({});
                         } else {
-                            max--;
-                            start();
+                            resolve(result);
                         }
-                    }).catch(() => {
-                        start();
-                    });
-                };
-                start();
+                    } else {
+                        resolve({});
+                    }
+                }).catch(() => {
+                    resolve({});
+                });
             });
         }
 

+ 82 - 16
app/service/material_audit.js

@@ -12,6 +12,7 @@ const auditConst = require('../const/audit').material;
 const pushType = require('../const/audit').pushType;
 const smsTypeConst = require('../const/sms_type');
 const wxConst = require('../const/wechat_template');
+const shenpiConst = require('../const/shenpi');
 
 module.exports = app => {
     class MaterialAudit extends app.BaseService {
@@ -103,18 +104,29 @@ module.exports = app => {
          * @param {Number} times - 第几次审批
          * @return {Promise<number>}
          */
-        async addAuditor(materialId, auditorId, times = 1) {
-            const newOrder = await this.getNewOrder(materialId, times);
-            const data = {
-                tid: this.ctx.tender.id,
-                mid: materialId,
-                aid: auditorId,
-                times,
-                order: newOrder,
-                status: auditConst.status.uncheck,
-            };
-            const result = await this.db.insert(this.tableName, data);
-            return result.effectRows = 1;
+        async addAuditor(materialId, auditorId, times = 1, is_gdzs = 0) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                let newOrder = await this.getNewOrder(materialId, times);
+                // 判断是否存在固定终审,存在则newOrder - 1并使终审order+1
+                newOrder = is_gdzs === 1 ? newOrder - 1 : newOrder;
+                if (is_gdzs) await this._syncOrderByDelete(transaction, materialId, newOrder, times, '+');
+                const data = {
+                    tid: this.ctx.tender.id,
+                    mid: materialId,
+                    aid: auditorId,
+                    times,
+                    order: newOrder,
+                    status: auditConst.status.uncheck,
+                };
+                const result = await transaction.insert(this.tableName, data);
+                await transaction.commit();
+                return result.effectRows = 1;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+            return false;
         }
 
         /**
@@ -126,7 +138,7 @@ module.exports = app => {
          * @return {Promise<*>}
          * @private
          */
-        async _syncOrderByDelete(transaction, materialId, order, times) {
+        async _syncOrderByDelete(transaction, materialId, order, times, selfOperate = '-') {
             this.initSqlBuilder();
             this.sqlBuilder.setAndWhere('mid', {
                 value: materialId,
@@ -142,7 +154,7 @@ module.exports = app => {
             });
             this.sqlBuilder.setUpdateData('order', {
                 value: 1,
-                selfOperate: '-',
+                selfOperate: selfOperate,
             });
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
             const data = await transaction.query(sql, sqlParam);
@@ -185,7 +197,12 @@ module.exports = app => {
         async start(materialId, times = 1) {
             const audit = await this.getDataByCondition({ mid: materialId, times, order: 1 });
             if (!audit) {
-                throw '请先选择审批人,再上报数据';
+                if(this.ctx.tender.info.shenpi.material === shenpiConst.sp_status.gdspl) {
+                    throw '请联系管理员添加审批人';
+                } else {
+                    throw '请先选择审批人,再上报数据';
+                }
+
             }
 
             const transaction = await this.db.beginTransaction();
@@ -243,7 +260,7 @@ module.exports = app => {
                     };
                     mehList.push(newMeh);
                 }
-                await transaction.insert(this.ctx.service.materialExponentHistory.tableName, mehList);
+                if(mehList.length !== 0) await transaction.insert(this.ctx.service.materialExponentHistory.tableName, mehList);
 
                 // 微信模板通知
                 const materialInfo = await this.ctx.service.material.getDataById(materialId);
@@ -846,6 +863,55 @@ module.exports = app => {
             const sqlParam = [tenderId];
             return this.db.query(sql, sqlParam);
         }
+
+        async updateNewAuditList(material, newIdList) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 先删除旧的审批流,再添加新的
+                transaction.delete(this.tableName, { mid: material.id, times: material.times });
+                const newAuditors = [];
+                let order = 1;
+                for (const aid of newIdList) {
+                    newAuditors.push({
+                        tid: material.tid, mid: material.id, aid,
+                        times: material.times, order, status: auditConst.status.uncheck,
+                    });
+                    order++;
+                }
+                if(newAuditors.length > 0) await transaction.insert(this.tableName, newAuditors);
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async updateLastAudit(material, auditList, lastId) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 先判断auditList里的aid是否与lastId相同,相同则删除并重新更新order
+                const idList = this._.map(auditList, 'aid');
+                let order = idList.length + 1;
+                if (idList.indexOf(lastId) !== -1) {
+                    transaction.delete(this.tableName, { mid: material.id, times: material.times, aid: lastId });
+                    const audit = this._.find(auditList, { 'aid': lastId });
+                    // 顺移之后审核人流程顺序
+                    await this._syncOrderByDelete(transaction, material.id, audit.order, material.times);
+                    order = order - 1;
+                }
+
+                // 添加终审
+                const newAuditor = {
+                    tid: material.tid, mid: material.id, aid: lastId,
+                    times: material.times, order, status: auditConst.status.uncheck,
+                };
+                await transaction.insert(this.tableName, newAuditor);
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return MaterialAudit;

+ 82 - 15
app/service/stage_audit.js

@@ -13,6 +13,7 @@ const smsTypeConst = require('../const/sms_type');
 const SMS = require('../lib/sms');
 const SmsAliConst = require('../const/sms_alitemplate');
 const wxConst = require('../const/wechat_template');
+const shenpiConst = require('../const/shenpi');
 const payConst = require('../const/deal_pay');
 const pushType = require('../const/audit').pushType;
 
@@ -163,18 +164,29 @@ module.exports = app => {
          * @param {Number} times - 第几次审批
          * @return {Promise<number>}
          */
-        async addAuditor(stageId, auditorId, times = 1) {
-            const newOrder = await this.getNewOrder(stageId, times);
-            const data = {
-                tid: this.ctx.tender.id,
-                sid: stageId,
-                aid: auditorId,
-                times,
-                order: newOrder,
-                status: auditConst.status.uncheck,
-            };
-            const result = await this.db.insert(this.tableName, data);
-            return (result.effectRows = 1);
+        async addAuditor(stageId, auditorId, times = 1, is_gdzs = 0) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                let newOrder = await this.getNewOrder(stageId, times);
+                // 判断是否存在固定终审,存在则newOrder - 1并使终审order+1
+                newOrder = is_gdzs === 1 ? newOrder - 1 : newOrder;
+                if (is_gdzs) await this._syncOrderByDelete(transaction, stageId, newOrder, times, '+');
+                const data = {
+                    tid: this.ctx.tender.id,
+                    sid: stageId,
+                    aid: auditorId,
+                    times,
+                    order: newOrder,
+                    status: auditConst.status.uncheck,
+                };
+                const result = await transaction.insert(this.tableName, data);
+                await transaction.commit();
+                return result.effectRows = 1;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+            return false;
         }
 
         /**
@@ -186,7 +198,7 @@ module.exports = app => {
          * @return {Promise<*>}
          * @private
          */
-        async _syncOrderByDelete(transaction, stageId, order, times) {
+        async _syncOrderByDelete(transaction, stageId, order, times, selfOperate = '-') {
             this.initSqlBuilder();
             this.sqlBuilder.setAndWhere('sid', {
                 value: stageId,
@@ -202,7 +214,7 @@ module.exports = app => {
             });
             this.sqlBuilder.setUpdateData('order', {
                 value: 1,
-                selfOperate: '-',
+                selfOperate: selfOperate,
             });
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
             const data = await transaction.query(sql, sqlParam);
@@ -246,7 +258,11 @@ module.exports = app => {
         async start(stageId, times = 1) {
             const audit = await this.getDataByCondition({ sid: stageId, times, order: 1 });
             if (!audit) {
-                throw '请先选择审批人,再上报数据';
+                if(this.ctx.tender.info.shenpi.stage === shenpiConst.sp_status.gdspl) {
+                    throw '请联系管理员添加审批人';
+                } else {
+                    throw '请先选择审批人,再上报数据';
+                }
             }
 
             const transaction = await this.db.beginTransaction();
@@ -1238,6 +1254,57 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        // 固定审批流-更新
+        async updateNewAuditList(stage, newIdList) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 先删除旧的审批流,再添加新的
+                transaction.delete(this.tableName, { sid: stage.id, times: stage.times });
+                const newAuditors = [];
+                let order = 1;
+                for (const aid of newIdList) {
+                    newAuditors.push({
+                        tid: stage.tid, sid: stage.id, aid,
+                        times: stage.times, order, status: auditConst.status.uncheck,
+                    });
+                    order++;
+                }
+                if(newAuditors.length > 0) await transaction.insert(this.tableName, newAuditors);
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        // 固定终审-更新
+        async updateLastAudit(stage, auditList, lastId) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 先判断auditList里的aid是否与lastId相同,相同则删除并重新更新order
+                const idList = this._.map(auditList, 'aid');
+                let order = idList.length + 1;
+                if (idList.indexOf(lastId) !== -1) {
+                    transaction.delete(this.tableName, { sid: stage.id, times: stage.times, aid: lastId });
+                    const audit = this._.find(auditList, { 'aid': lastId });
+                    // 顺移之后审核人流程顺序
+                    await this._syncOrderByDelete(transaction, stage.id, audit.order, stage.times);
+                    order = order - 1;
+                }
+
+                // 添加终审
+                const newAuditor = {
+                    tid: stage.tid, sid: stage.id, aid: lastId,
+                    times: stage.times, order, status: auditConst.status.uncheck,
+                };
+                await transaction.insert(this.tableName, newAuditor);
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return StageAudit;

+ 25 - 13
app/service/stage_change.js

@@ -40,13 +40,16 @@ module.exports = app => {
                 '  oc.p_code As c_code, oc.new_code As c_new_code' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid` From ' + this.tableName +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ? And lid = ? And pid = ?' +
-                '      GROUP By `lid`, `pid`' +
+                '      GROUP By `lid`, `pid`, `cid`, `cbid`' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
-                '  ON c.cid = oc.cid';
+                '  ON c.cid = oc.cid' +
+                '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
+                '  ON c.cbid = ocb.id' +
+                '  WHERE not ISNULL(ocb.id)';
             const sqlParam = [tid, sid, lid, pid ? pid : -1];
             return await this.db.query(sql, sqlParam);
         }
@@ -66,13 +69,16 @@ module.exports = app => {
                 '  oc.p_code As c_code, oc.new_code As c_new_code' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid` From ' + this.tableName +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?)) And lid = ? And pid = ?' +
                 '      GROUP By `lid`, `pid`' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
-                '  ON c.cid = oc.cid';
+                '  ON c.cid = oc.cid' +
+                '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
+                '  ON c.cbid = ocb.id' +
+                '  WHERE not ISNULL(ocb.id)';
             const sqlParam = [tid, sid, times, times, order, lid, pid ? pid : -1];
             return await this.db.query(sql, sqlParam);
         }
@@ -82,13 +88,16 @@ module.exports = app => {
                 '  oc.p_code As c_code, oc.new_code As c_new_code' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid` From ' + this.tableName +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ?' +
                 '      GROUP By `lid`, `pid`' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
-                '  ON c.cid = oc.cid';
+                '  ON c.cid = oc.cid'+
+                '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
+                '  ON c.cbid = ocb.id' +
+                '  WHERE not ISNULL(ocb.id)';
             const sqlParam = [tid, sid];
             return await this.db.query(sql, sqlParam);
         }
@@ -98,13 +107,16 @@ module.exports = app => {
                 '  oc.p_code As c_code, oc.new_code As c_new_code' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid` From ' + this.tableName +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?))' +
                 '      GROUP By `lid`, `pid`' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
-                '  ON c.cid = oc.cid';
+                '  ON c.cid = oc.cid'+
+                '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
+                '  ON c.cbid = ocb.id' +
+                '  WHERE not ISNULL(ocb.id)';
             const sqlParam = [tid, sid, times, times, order];
             return await this.db.query(sql, sqlParam);
         }

+ 10 - 10
app/view/dashboard/index.ejs

@@ -40,7 +40,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- t.id %>/ledger/audit" class="btn btn-sm btn-outline-primary">审批</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- (t.begin_time ? ctx.moment(t.begin_time).format('YYYY-MM-DD hh:mm:ss') : '') %></span>
+                                                        <span class="pull-right text-muted"><%- (t.begin_time ? ctx.moment(t.begin_time).format('YYYY-MM-DD HH:mm:ss') : '') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -53,7 +53,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- t.id %>/ledger" class="btn btn-sm btn-outline-primary">重新上报</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- (t.end_time ? ctx.moment(t.end_time).format('YYYY-MM-DD hh:mm:ss') : '') %></span>
+                                                        <span class="pull-right text-muted"><%- (t.end_time ? ctx.moment(t.end_time).format('YYYY-MM-DD HH:mm:ss') : '') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -68,7 +68,7 @@
                                                     <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- revise.t_id %>/revise/info" class="btn btn-sm btn-outline-primary"><% if (revise.status === acRevise.status.checking) { %>审批<% } else if (revise.status === acRevise.status.checkNo) { %>重新上报<% } %></a></div>
                                                 </div>
                                                 <p class="mt-1 mb-0"><%- revise.audit_name %><small class="ml-1 text-muted"><%- (revise.audit_role ? '- ' + revise.audit_role: '') %></small>
-                                                    <span class="pull-right text-muted"><%- (revise.end_time ? ctx.moment(revise.end_time).format('YYYY-MM-DD hh:mm:ss') : '') %></span>
+                                                    <span class="pull-right text-muted"><%- (revise.end_time ? ctx.moment(revise.end_time).format('YYYY-MM-DD HH:mm:ss') : '') %></span>
                                                 </p>
                                             </div>
                                         </li>
@@ -83,7 +83,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- audit.tid %>/measure/stage/<%- audit.sorder %>" class="btn btn-sm btn-outline-primary"><% if (audit.sstatus === acStage.status.checkNoPre) { %>重新<% } %>审批</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- ctx.moment(audit.begin_time).format('YYYY-MM-DD hh:mm:ss') %></span>
+                                                        <span class="pull-right text-muted"><%- ctx.moment(audit.begin_time).format('YYYY-MM-DD HH:mm:ss') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -96,7 +96,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- audit.tid %>/measure/stage/<%- audit.sorder %>" class="btn btn-sm btn-outline-primary">重新上报</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- ctx.moment(audit.end_time).format('YYYY-MM-DD hh:mm:ss') %></span>
+                                                        <span class="pull-right text-muted"><%- ctx.moment(audit.end_time).format('YYYY-MM-DD HH:mm:ss') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -111,7 +111,7 @@
                                                     <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- change.tid %>/change/<%- change.cid %>/info" class="btn btn-sm btn-outline-primary"><% if (change.cstatus === acChange.status.checking) { %>审批<% } else if (change.cstatus === acChange.status.backnew) { %>重新审批<% } else { %>重新上报<% } %></a></div>
                                                 </div>
                                                 <p class="mt-1 mb-0"><%- change.caname %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                    <span class="pull-right text-muted"><%- (change.sin_time ? ctx.moment(change.sin_time).format('YYYY-MM-DD hh:mm:ss') : '') %></span>
+                                                    <span class="pull-right text-muted"><%- (change.sin_time ? ctx.moment(change.sin_time).format('YYYY-MM-DD HH:mm:ss') : '') %></span>
                                                 </p>
                                             </div>
                                         </li>
@@ -126,7 +126,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- am.tid %>/measure/material/<%- am.morder %>" class="btn btn-sm btn-outline-primary">审批</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- ctx.moment(am.begin_time).format('YYYY-MM-DD hh:mm:ss') %></span>
+                                                        <span class="pull-right text-muted"><%- ctx.moment(am.begin_time).format('YYYY-MM-DD HH:mm:ss') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -139,7 +139,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- am.tid %>/measure/material/<%- am.morder %>" class="btn btn-sm btn-outline-primary">重新上报</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- ctx.moment(am.end_time).format('YYYY-MM-DD hh:mm:ss') %></span>
+                                                        <span class="pull-right text-muted"><%- ctx.moment(am.end_time).format('YYYY-MM-DD HH:mm:ss') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -155,7 +155,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- am.tid %>/advance/<%- am.vid %>/detail" class="btn btn-sm btn-outline-primary">审批</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- ctx.moment(am.create_time).format('YYYY-MM-DD hh:mm:ss') %></span>
+                                                        <span class="pull-right text-muted"><%- ctx.moment(am.create_time).format('YYYY-MM-DD HH:mm:ss') %></span>
                                                     </p>
                                                 </div>
                                             </li>
@@ -168,7 +168,7 @@
                                                         <div class="col-3 ml-auto text-right pl-0"><a href="/tender/<%- am.tid %>/advance/<%- am.vid %>/detail" class="btn btn-sm btn-outline-primary">重新上报</a></div>
                                                     </div>
                                                     <p class="mt-1 mb-0"><%- ctx.session.sessionUser.name %><small class="ml-1 text-muted"><%- (role ? '- ' + role : '') %></small>
-                                                        <span class="pull-right text-muted"><%- ctx.moment(am.end_time).format('YYYY-MM-DD hh:mm:ss') %></span>
+                                                        <span class="pull-right text-muted"><%- ctx.moment(am.end_time).format('YYYY-MM-DD HH:mm:ss') %></span>
                                                     </p>
                                                 </div>
                                             </li>

+ 1 - 1
app/view/ledger/explode.ejs

@@ -142,7 +142,7 @@
                                 <% if (dealBillsPermission) { %>
                                 <a href="#upload-deal" data-toggle="modal" data-target="#upload-deal" class="btn btn-sm btn-primary">上传签约清单</a>
                                 <% } else { %>
-                                <a href="javascript: void(0);" class="btn btn-sm btn-outline-dark">上传签约清单</a>
+                                <a href="javascript: void(0);" class="btn btn-sm btn-primary disabled">上传签约清单</a>
                                 <% } %>
                                 <a href="/tender/<%- ctx.tender.id %>/deal/download/签约清单.xlsx" class="btn btn-sm btn-primary" style="display: none">下载签约清单</a>
                             </div>

+ 13 - 2
app/view/ledger/explode_modal.ejs

@@ -94,6 +94,7 @@
             </div>
             <div class="modal-body">
                 <div class="dropdown text-right">
+                    <% if (ctx.tender.info.shenpi.ledger !== shenpiConst.sp_status.gdspl) { %>
                     <button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button"
                         id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
                         aria-expanded="false">
@@ -118,6 +119,7 @@
                             <% }) %>
                         </dl>
                     </div>
+                    <% } %>
                 </div>
                 <div class="card mt-3">
                     <div class="card-header">
@@ -127,8 +129,11 @@
                     <ul class="list-group list-group-flush" id="auditors">
                         <% for (let i = 0, iLen = auditorList.length; i < iLen; i++) { %>
                         <li class="list-group-item" auditorId="<%- auditorList[i].audit_id %>">
+                            <% if (ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.sqspr ||
+                                    (ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdzs && i+1 !== iLen)) { %>
                             <a href="javascript: void(0)" class="text-danger pull-right">移除</a>
-                            <%- auditorList[i].audit_order %> <%- auditorList[i].name %>
+                            <% } %>
+                            <span><%- auditorList[i].audit_order %> <%- auditorList[i].name %></span>
                             <small class="text-muted"><%- auditorList[i].role %></small>
                         </li>
                         <% } %>
@@ -160,7 +165,7 @@
                             <a class="sp-list-item" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" id="hideSp">修改审批流程</a>
                         <% } %>
                         <div class="card mt-3">
-                            <ul class="list-group list-group-flush">
+                            <ul class="list-group list-group-flush" id="auditors-list">
                                 <% auditors.forEach((item, idx) => { %>
                                 <% if (idx === 0) { %>
                                 <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
@@ -330,6 +335,12 @@
         </div>
     </div>
 </div>
+<% if (ctx.session.sessionUser.accountId === ctx.tender.data.user_id && (ctx.tender.data.ledger_status === auditConst.status.uncheck || ctx.tender.data.ledger_status === auditConst.status.checkNo)) { %>
+    <script>
+        const shenpi_status = <%- ctx.tender.info.shenpi.ledger %>;
+        const shenpiConst =  JSON.parse('<%- JSON.stringify(shenpiConst) %>');
+    </script>
+<% } %>
 <script>
     const cur_uid  = parseInt('<%- ctx.session.sessionUser.accountId %>');
     $('.sp-location-list').on('shown.bs.modal', function () {

+ 140 - 139
app/view/login/login.ejs

@@ -1,139 +1,140 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=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/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>
-        html{height:100%;}
-    </style>
-</head>
-<body class="login-body">
-<div class="login-bg img-<%- Math.floor(Math.random()*3 + 1); %>"></div>
-<div class="container">
-    <div class="row">
-        <div class="col-6">
-            <img src="/public/images/loginlogo.png">
-        </div>
-        <div class="col-6">
-            <% if (maintainData.status === maintainConst.status.ongoing) { %>
-                <form class="form-signin">
-                    <h4 class="text-center mb-3"><i class="fa fa-wrench"></i>系统正在维护</h4>
-                    <h4>预计恢复时间<%- (maintainData.duration !== maintainConst.duration.forever ? '为 ' + ctx.helper.dateTran(parseFloat(maintainData.maintain_time) + ctx.helper.timeAdd(maintainData.duration)) : ' 暂未确定') %></h4>
-                    <h4>造成不便敬请谅解。</h4>
-                </form>
-            <% } else { %>
-                <!--演示版-->
-                <form class="form-signin" method="post" action="/login">
-                    <h4 class="text-center mb-2">纵横云计量</h4>
-                    <h5 class="text-center mb-4 text-muted" id="project_name"></h5>
-                    <!--<nav class="nav nav-tabs nav-justified mb-3" role="tablist" id="login-tab">-->
-                    <!--<a class="nav-item nav-link" data-toggle="tab" data-type="1" href="#preview" role="tab">演示版登录</a>-->
-                    <!--<a class="nav-item nav-link active" data-toggle="tab" data-type="2" href="#paid" role="tab">项目版登录</a>-->
-                    <!--</nav>-->
-                    <div class="tab-content">
-                        <!--<div class="tab-pane active" id="preview" role="tabpanel">-->
-                        <!--<div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">-->
-                        <!--<input id="username" name="username" class="form-control form-control-sm" placeholder="通行账号 邮箱/手机" value="laiku123@qq.com" autofocus="">-->
-                        <!--</div>-->
-                        <!--<div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">-->
-                        <!--<input id="password" name="password" class="form-control form-control-sm" placeholder="输入密码" value="19930523" type="password">-->
-                        <!--</div>-->
-                        <!--</div>-->
-                        <div class="tab-pane active" id="paid" role="tabpanel">
-                            <div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
-                                <input id="project" class="form-control" name="project" placeholder="项目编号" autofocus="" />
-                            </div>
-                            <div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
-                                <input id="account" class="form-control" name="account" placeholder="输入账号" autofocus="" />
-                            </div>
-                            <div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
-                                <input id="project-password" name="project_password" class="form-control" placeholder="输入密码" type="password" />
-                            </div>
-                        </div>
-                        <div class="form-group">
-                            <div class="alert alert-danger" <% if(errorMessage === undefined || errorMessage === null) { %>style="display: none"<% } %> role="alert" id="error-msg">
-                                <% if(errorMessage !== undefined && errorMessage !== null) { %><strong>登录失败</strong> <%= errorMessage %><% } %>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="form-group">
-                        <button class="btn btn-primary btn-block" type="submit">登录</button>
-                        <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
-                        <input type="hidden" name="type" value="2" />
-                    </div>
-                    <div class="pt-1 d-flex justify-content-end">
-                        <a href="#fg-password" data-toggle="modal" data-target="#fg-password"  class="mr-3">忘记密码?</a>
-                    </div>
-                </form>
-            <% } %>
-            <!--项目版-->
-        </div>
-    </div>
-    <div class="text-white fixed-bottom"><p class="text-center mb-1">Copyright © 2019 <a href="https://smartcost.com.cn" target="_blank" class="text-white">珠海纵横创新软件有限公司</a>.All Rights Reserved.<a class="text-white ml-2" href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备14032472号</a></p></div>
-</div>
-<!--忘记项目版密码-->
-<div class="modal fade" id="fg-password" data-backdrop="static">
-    <div class="modal-dialog" role="document">
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title">找回密码</h5>
-            </div>
-            <div class="modal-body">
-                <div class="form-group">
-                    <label>项目编号</label>
-                    <input class="form-control" id="forget-project" placeholder="输入项目编号">
-                    <div class="invalid-feedback"></div>
-                </div>
-                <div class="form-group">
-                    <label>登录账号</label>
-                    <input class="form-control" id="forget-name" placeholder="输入登录账号">
-                    <div class="invalid-feedback"></div>
-                </div>
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary" id="forget-btn">重置密码</button>
-            </div>
-        </div>
-    </div>
-</div>
-<!--忘记项目版密码-->
-<div class="modal fade" id="fg-password-done" data-backdrop="static">
-    <div class="modal-dialog" role="document">
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title">密码发送成功</h5>
-            </div>
-            <div class="modal-body">
-                <h5>尊敬的 <b></b>,您的账号 <b></b>,新密码已经发送至 <b></b>,注意查收。</h5>
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="focus-pwd">关闭</button>
-            </div>
-        </div>
-    </div>
-</div>
-<!-- JS. -->
-<div class="toast" style="text-align: center">
-    <i class="icon fa"></i>
-    <span class="message"></span>
-</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/global.js"></script>
-<script>
-    const csrf = '<%= ctx.csrf %>'
-</script>
-<script src="/public/js/login.js"></script>
-</body>
-
-</html>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=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/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>
+        html{height:100%;}
+    </style>
+</head>
+<body class="login-body">
+<div class="login-bg img-<%- Math.floor(Math.random()*3 + 1); %>"></div>
+<div class="container">
+    <div class="row">
+        <div class="col-6">
+            <img src="/public/images/loginlogo.png">
+        </div>
+        <div class="col-6">
+            <% if (maintainData.status === maintainConst.status.ongoing) { %>
+                <form class="form-signin">
+                    <h4 class="text-center mb-3"><i class="fa fa-wrench"></i>系统正在维护</h4>
+                    <h4>预计恢复时间<%- (maintainData.duration !== maintainConst.duration.forever ? '为 ' + ctx.helper.dateTran(parseFloat(maintainData.maintain_time) + ctx.helper.timeAdd(maintainData.duration)) : ' 暂未确定') %></h4>
+                    <h4>造成不便敬请谅解。</h4>
+                </form>
+            <% } else { %>
+                <!--演示版-->
+                <form class="form-signin" method="post" action="/login">
+                    <!-- <h4 class="text-center mb-2">纵横云计量</h4> -->
+                    <h5 class="text-center mb-2" id="project_name"></h5>
+                    <h5 class="text-center mb-4 text-muted">用户登录</h5>
+                    <!--<nav class="nav nav-tabs nav-justified mb-3" role="tablist" id="login-tab">-->
+                    <!--<a class="nav-item nav-link" data-toggle="tab" data-type="1" href="#preview" role="tab">演示版登录</a>-->
+                    <!--<a class="nav-item nav-link active" data-toggle="tab" data-type="2" href="#paid" role="tab">项目版登录</a>-->
+                    <!--</nav>-->
+                    <div class="tab-content">
+                        <!--<div class="tab-pane active" id="preview" role="tabpanel">-->
+                        <!--<div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">-->
+                        <!--<input id="username" name="username" class="form-control form-control-sm" placeholder="通行账号 邮箱/手机" value="laiku123@qq.com" autofocus="">-->
+                        <!--</div>-->
+                        <!--<div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">-->
+                        <!--<input id="password" name="password" class="form-control form-control-sm" placeholder="输入密码" value="19930523" type="password">-->
+                        <!--</div>-->
+                        <!--</div>-->
+                        <div class="tab-pane active" id="paid" role="tabpanel">
+                            <div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                                <input id="project" class="form-control" name="project" placeholder="项目编号" autofocus="" />
+                            </div>
+                            <div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                                <input id="account" class="form-control" name="account" placeholder="输入账号" autofocus="" />
+                            </div>
+                            <div class="form-group <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                                <input id="project-password" name="project_password" class="form-control" placeholder="输入密码" type="password" />
+                            </div>
+                        </div>
+                        <div class="form-group">
+                            <div class="alert alert-danger" <% if(errorMessage === undefined || errorMessage === null) { %>style="display: none"<% } %> role="alert" id="error-msg">
+                                <% if(errorMessage !== undefined && errorMessage !== null) { %><strong>登录失败</strong> <%= errorMessage %><% } %>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="form-group">
+                        <button class="btn btn-primary btn-block" type="submit">登录</button>
+                        <input type="hidden" name="_csrf" value="<%= ctx.csrf %>" />
+                        <input type="hidden" name="type" value="2" />
+                    </div>
+                    <div class="pt-1 d-flex justify-content-end">
+                        <a href="#fg-password" data-toggle="modal" data-target="#fg-password"  class="mr-3">忘记密码?</a>
+                    </div>
+                </form>
+            <% } %>
+            <!--项目版-->
+        </div>
+    </div>
+    <div class="text-white fixed-bottom"><p class="text-center mb-1">Copyright © 2019 <a href="https://smartcost.com.cn" target="_blank" class="text-white">珠海纵横创新软件有限公司</a>.All Rights Reserved.<a class="text-white ml-2" href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备14032472号</a></p></div>
+</div>
+<!--忘记项目版密码-->
+<div class="modal fade" id="fg-password" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">找回密码</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>项目编号</label>
+                    <input class="form-control" id="forget-project" placeholder="输入项目编号">
+                    <div class="invalid-feedback"></div>
+                </div>
+                <div class="form-group">
+                    <label>登录账号</label>
+                    <input class="form-control" id="forget-name" placeholder="输入登录账号">
+                    <div class="invalid-feedback"></div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary" id="forget-btn">重置密码</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!--忘记项目版密码-->
+<div class="modal fade" id="fg-password-done" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">密码发送成功</h5>
+            </div>
+            <div class="modal-body">
+                <h5>尊敬的 <b></b>,您的账号 <b></b>,新密码已经发送至 <b></b>,注意查收。</h5>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="focus-pwd">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+<!-- JS. -->
+<div class="toast" style="text-align: center">
+    <i class="icon fa"></i>
+    <span class="message"></span>
+</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/global.js"></script>
+<script>
+    const csrf = '<%= ctx.csrf %>'
+</script>
+<script src="/public/js/login.js"></script>
+</body>
+
+</html>

+ 9 - 2
app/view/material/audit_modal.ejs

@@ -8,6 +8,7 @@
             </div>
             <div class="modal-body">
                 <div class="dropdown text-right">
+                    <% if (ctx.tender.info.shenpi.material !== shenpiConst.sp_status.gdspl) { %>
                     <button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button"
                         id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
                         aria-expanded="false">
@@ -34,6 +35,7 @@
                             <% }) %>
                         </dl>
                     </div>
+                    <% } %>
                 </div>
                 <div class="card mt-3">
                     <div class="card-header">
@@ -43,8 +45,11 @@
                     <ul class="list-group list-group-flush" id="auditors">
                         <% for (let i = 0, iLen = ctx.material.auditorList.length; i < iLen; i++) { %>
                         <li class="list-group-item" auditorId="<%- ctx.material.auditorList[i].aid %>">
+                            <% if (ctx.tender.info.shenpi.material === shenpiConst.sp_status.sqspr ||
+                                    (ctx.tender.info.shenpi.material === shenpiConst.sp_status.gdzs && i+1 !== iLen)) { %>
                             <a href="javascript: void(0)" class="text-danger pull-right">移除</a>
-                            <%- ctx.material.auditorList[i].order %> <%- ctx.material.auditorList[i].name %>
+                            <% } %>
+                            <span><%- ctx.material.auditorList[i].order %> <%- ctx.material.auditorList[i].name %></span>
                             <small class="text-muted"><%- ctx.material.auditorList[i].role %></small>
                         </li>
                         <% } %>
@@ -76,7 +81,7 @@
                             <a class="sp-list-item" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" id="hideSp">修改审批流程</a>
                         <% } %>
                         <div class="card mt-3">
-                            <ul class="list-group list-group-flush">
+                            <ul class="list-group list-group-flush" id="auditors-list">
                                 <% ctx.material.auditors2.forEach((item, idx) => { %>
                                 <% if (idx === 0) { %>
                                 <li class="list-group-item" data-auditorId="<%- item.aid %>">
@@ -679,6 +684,8 @@
     <script>
         const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
         const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
+        const shenpi_status = <%- ctx.tender.info.shenpi.material %>;
+        const shenpiConst =  JSON.parse('<%- JSON.stringify(shenpiConst) %>');
     </script>
 <% } %>
 <script>const cur_uid = parseInt('<%- ctx.session.sessionUser.accountId %>');</script>

+ 2 - 2
app/view/revise/history.ejs

@@ -22,7 +22,7 @@
                     </div>
                 </div>
                 <div class="d-inline-flex">
-                    <%- (revise.in_time ? ctx.moment(revise.in_time).format('YYYY-MM-DD hh:mm:ss') : '') %>
+                    <%- (revise.in_time ? ctx.moment(revise.in_time).format('YYYY-MM-DD HH:mm:ss') : '') %>
                 </div>
             </div>
             <div class="ml-auto">
@@ -81,7 +81,7 @@
                             </div>
                             <div class="form-group">
                                 <label >审批完成</label>
-                                <input id="end-time" type="" class="form-control form-control-sm" value="<%- (revise.end_time ? ctx.moment(revise.end_time).format('YYYY-MM-DD hh:mm:ss') : '') %>" disabled>
+                                <input id="end-time" type="" class="form-control form-control-sm" value="<%- (revise.end_time ? ctx.moment(revise.end_time).format('YYYY-MM-DD HH:mm:ss') : '') %>" disabled>
                             </div>
                         </div>
                     </div>

+ 1 - 1
app/view/revise/info.ejs

@@ -124,7 +124,7 @@
                         <div class="sjs-sh" style="overflow:auto">
                             <div class="form-group mt-2">
                                 <label >创建时间</label>
-                                <input type="" class="form-control form-control-sm" value="<%- ctx.moment(revise.in_time).format('YYYY-MM-DD hh:mm:ss') %>" disabled>
+                                <input type="" class="form-control form-control-sm" value="<%- ctx.moment(revise.in_time).format('YYYY-MM-DD HH:mm:ss') %>" disabled>
                             </div>
                             <div class="form-group mt-2">
                                 <label >提交人</label>

+ 3 - 1
app/view/shares/check_data_modal.ejs

@@ -101,6 +101,8 @@
                         setting.errorList.clearErrorData();
                         postData(url, data, function () {
                             window.location.reload();
+                        }, function () {
+                            window.location.reload();
                         });
                     }, 300);
                 }
@@ -111,4 +113,4 @@
         }
         return {checkAndPost};
     }
-</script>
+</script>

+ 9 - 2
app/view/stage/audit_modal.ejs

@@ -9,6 +9,7 @@
                 </div>
                 <div class="modal-body">
                     <div class="dropdown text-right">
+                        <% if (ctx.tender.info.shenpi.stage !== shenpiConst.sp_status.gdspl) { %>
                         <button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button" id="dropdownMenuButton"
                             data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                             添加审批流程
@@ -34,6 +35,7 @@
                                 <% }) %>
                             </dl>
                         </div>
+                        <% } %>
                     </div>
                     <div class="card mt-3">
                         <div class="card-header">
@@ -43,8 +45,11 @@
                             <ul class="list-group list-group-flush" id="auditors">
                                 <% for (let i = 0, iLen = ctx.stage.auditorList.length; i < iLen; i++) { %>
                                 <li class="list-group-item" auditorId="<%- ctx.stage.auditorList[i].aid %>">
+                                    <% if (ctx.tender.info.shenpi.stage === shenpiConst.sp_status.sqspr ||
+                                            (ctx.tender.info.shenpi.stage === shenpiConst.sp_status.gdzs && i+1 !== iLen)) { %>
                                     <a href="javascript: void(0)" class="text-danger pull-right">移除</a>
-                                    <%- ctx.stage.auditorList[i].order %> <%- ctx.stage.auditorList[i].name %>
+                                    <% } %>
+                                    <span><%- ctx.stage.auditorList[i].order %> <%- ctx.stage.auditorList[i].name %></span>
                                     <small class="text-muted"><%- ctx.stage.auditorList[i].role %></small>
                                 </li>
                                 <% } %>
@@ -79,7 +84,7 @@
                                 id="hideSp">修改审批流程</a>
                             <% } %>
                             <div class="card mt-3">
-                                <ul class="list-group list-group-flush">
+                                <ul class="list-group list-group-flush" id="auditors-list">
                                     <% ctx.stage.auditors2.forEach((item, idx) => { %>
                                     <% if (idx === 0) { %>
                                     <li class="list-group-item" data-auditorId="<%- item.aid %>">
@@ -795,6 +800,8 @@
 <script>
     const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
+    const shenpi_status = <%- ctx.tender.info.shenpi.stage %>;
+    const shenpiConst =  JSON.parse('<%- JSON.stringify(shenpiConst) %>');
 </script>
 <% } %>
 <script>

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

@@ -100,6 +100,9 @@
                                 <a href="#bd-set-5" data-toggle="modal" data-target="#bd-set-5" class="btn btn-sm btn-outline-primary">显示设置</a>
                                 <a href="#bd-set-6" data-toggle="modal" data-target="#bd-set-6" class="btn btn-sm btn-outline-primary">章节设置</a>
                                 <a href="#bd-set-7" data-toggle="modal" data-target="#bd-set-7" class="btn btn-sm btn-outline-primary">付款账号</a>
+                                <% if (ctx.session.sessionUser.is_admin) { %>
+                                <a href="/tender/<%- tender.id %>/shenpi" class="btn btn-sm btn-outline-primary">审批流程</a>
+                                <% } %>
                             </div>
                         </div>
                     </div>

+ 3 - 3
app/view/tender/shenpi.ejs

@@ -57,7 +57,7 @@
                                                                 <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>" data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
                                                                 <div class="dd-content" data-toggleid="<%- idx %>">
                                                                     <% group.groupList.forEach(item => { %>
-                                                                        <% if (item.id !== ctx.session.sessionUser.accountId) { %>
+                                                                        <% if (item.id !== ctx.tender.data.user_id) { %>
                                                                             <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>" >
                                                                     <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
                                                                                 class="ml-auto"><%- item.mobile %></span></p>
@@ -108,7 +108,7 @@
                                                                 <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>" data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
                                                                     <div class="dd-content" data-toggleid="<%- idx %>">
                                                                     <% group.groupList.forEach(item => { %>
-                                                                        <% if (item.id !== ctx.session.sessionUser.accountId) { %>
+                                                                        <% if (item.id !== ctx.tender.data.user_id) { %>
                                                                         <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>" >
                                                                         <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
                                                                                     class="ml-auto"><%- item.mobile %></span></p>
@@ -144,7 +144,7 @@
     const sp_status_list = JSON.parse('<%- JSON.stringify(shenpi.sp_status_list) %>');
     const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
-    const cur_uid = parseInt('<%- ctx.session.sessionUser.accountId %>');
+    const cur_uid = parseInt('<%- ctx.tender.data.user_id %>');
 </script>
 <script src="/public/js/shenpi.js"></script>
 <script>