瀏覽代碼

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

TonyKang 5 年之前
父節點
當前提交
fc5dc25864
共有 46 個文件被更改,包括 1253 次插入555 次删除
  1. 14 0
      app/controller/ledger_controller.js
  2. 4 0
      app/controller/login_controller.js
  3. 28 5
      app/controller/revise_controller.js
  4. 7 9
      app/controller/setting_controller.js
  5. 29 12
      app/controller/stage_controller.js
  6. 4 2
      app/controller/tender_controller.js
  7. 8 4
      app/controller/wap_controller.js
  8. 55 7
      app/extend/helper.js
  9. 11 12
      app/public/css/main.css
  10. 1 1
      app/public/js/global.js
  11. 8 65
      app/public/js/ledger.js
  12. 0 225
      app/public/js/ledger_search.js
  13. 39 24
      app/public/js/revise.js
  14. 27 1
      app/public/js/setting.js
  15. 326 35
      app/public/js/shares/cs_tools.js
  16. 102 25
      app/public/js/stage.js
  17. 1 0
      app/public/js/stage_audit.js
  18. 2 1
      app/public/js/tender_list.js
  19. 2 1
      app/public/js/tender_list_info.js
  20. 2 1
      app/public/js/tender_list_manage.js
  21. 2 1
      app/public/js/tender_list_progress.js
  22. 152 0
      app/public/js/wap/global.js
  23. 3 0
      app/router.js
  24. 2 2
      app/service/ledger_audit.js
  25. 15 7
      app/service/project_account.js
  26. 20 1
      app/service/report_memory.js
  27. 7 0
      app/service/rpt_gather_memory.js
  28. 1 1
      app/service/stage_audit.js
  29. 2 2
      app/service/stage_jgcl.js
  30. 4 2
      app/service/stage_pay.js
  31. 5 5
      app/view/measure/stage.ejs
  32. 5 0
      app/view/revise/info.ejs
  33. 4 2
      app/view/revise/info_modal.ejs
  34. 54 14
      app/view/setting/user_modal.ejs
  35. 57 29
      app/view/shares/check_data_modal.ejs
  36. 70 6
      app/view/stage/audit_modal.ejs
  37. 13 3
      app/view/stage/index.ejs
  38. 1 1
      app/view/stage/modal.ejs
  39. 10 8
      app/view/wap/dashboard.ejs
  40. 3 2
      app/view/wap/list.ejs
  41. 0 1
      app/view/wap/login.ejs
  42. 60 24
      app/view/wap/tender.ejs
  43. 60 4
      builder_report_index_define.js
  44. 13 10
      config/web.js
  45. 5 0
      sql/update.sql
  46. 15 0
      sql/update20200527.sql

+ 14 - 0
app/controller/ledger_controller.js

@@ -441,6 +441,20 @@ module.exports = app => {
             }
             }
         }
         }
 
 
+        async check(ctx) {
+            try {
+                const ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
+                const posData = this.ctx.tender.data.measure_type === measureType.tz.value
+                    ? await ctx.service.pos.getPosData({ tid: ctx.tender.id }) : [];
+                const data = ctx.helper.checkBillsWithPos(ledgerData, posData,
+                    ['sgfh_qty', 'qtcl_qty', 'sjcl_qty', 'quantity']);
+                ctx.body = { err: 0, msg: '', data: data };
+            } catch (err) {
+                this.log(err);
+                ctx.body = this.ajaxErrorBody(err, '检查数据错误');
+            }
+        }
+
         /**
         /**
          * 更新 部位明细数据
          * 更新 部位明细数据
          *
          *

+ 4 - 0
app/controller/login_controller.js

@@ -21,6 +21,10 @@ module.exports = app => {
          * @return {void}
          * @return {void}
          */
          */
         async index(ctx) {
         async index(ctx) {
+            if (ctx.helper.isMobile(ctx.request.header['user-agent'])) {
+                ctx.redirect('/wap');
+                return;
+            }
             const errorMessage = ctx.session.loginError;
             const errorMessage = ctx.session.loginError;
             // 显示完删除
             // 显示完删除
             ctx.session.loginError = null;
             ctx.session.loginError = null;

+ 28 - 5
app/controller/revise_controller.js

@@ -44,7 +44,7 @@ module.exports = app => {
             const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
             const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
             const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true);
             const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true);
             return (ctx.tender.data.user_id === ctx.session.sessionUser.accountId) &&
             return (ctx.tender.data.user_id === ctx.session.sessionUser.accountId) &&
-                (ctx.tender.data.ledger_status === audit.revise.status.checked) &&
+                (ctx.tender.data.ledger_status === audit.ledger.status.checked) &&
                 (!revise || !revise.valid || revise.status === audit.revise.status.checked) &&
                 (!revise || !revise.valid || revise.status === audit.revise.status.checked) &&
                 (!lastStage || lastStage.status !== audit.stage.status.checking);
                 (!lastStage || lastStage.status !== audit.stage.status.checking);
         }
         }
@@ -433,6 +433,30 @@ module.exports = app => {
             }
             }
         }
         }
 
 
+        async checkData(ctx) {
+            try {
+                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
+                if (!revise) throw '台账修订数据有误';
+
+                const billsFile = revise.bills_file ? this.ctx.app.config.filePath + revise.bills_file : undefined;
+                const reviseBills = billsFile && fs.existsSync(billsFile)
+                    ? JSON.parse(await fs.readFileSync(billsFile, 'utf8'))
+                    : await ctx.service.reviseBills.getData(ctx.tender.id);
+
+                const posFile = revise.pos_file ? this.ctx.app.config.filePath + revise.pos_file : undefined;
+                const revisePos = posFile && fs.existsSync(posFile)
+                    ? JSON.parse(await fs.readFileSync(posFile, 'utf8'))
+                    : await ctx.service.revisePos.getData(ctx.tender.id);
+
+                const data = ctx.helper.checkBillsWithPos(reviseBills, revisePos,
+                    ['sgfh_qty', 'qtcl_qty', 'sjcl_qty', 'quantity']);
+                ctx.body = { err: 0, msg: '', data: data };
+            } catch (err) {
+                this.log(err);
+                ctx.body = this.ajaxErrorBody(err, '检查数据错误');
+            }
+        }
+
         async history(ctx) {
         async history(ctx) {
             try {
             try {
                 const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id, false);
                 const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id, false);
@@ -776,7 +800,7 @@ module.exports = app => {
             }
             }
         }
         }
         /**
         /**
-         * 上报(post)
+         * 上报(ajax-post)
          *
          *
          * @param ctx
          * @param ctx
          * @return {Promise<void>}
          * @return {Promise<void>}
@@ -794,11 +818,10 @@ module.exports = app => {
 
 
                 await ctx.service.reviseAudit.start(revise, revise.times);
                 await ctx.service.reviseAudit.start(revise, revise.times);
 
 
-                ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
+                ctx.body = {err: 0, msg: '', data: {}};
             } catch (err) {
             } catch (err) {
                 this.log(err);
                 this.log(err);
-                this.postError(err, '上报失败');
-                ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
+                ctx.body = this.ajaxErrorBody(err, '上报失败');
             }
             }
         }
         }
         /**
         /**

+ 7 - 9
app/controller/setting_controller.js

@@ -310,10 +310,6 @@ module.exports = app => {
         }
         }
 
 
         async resetUserPassword(ctx) {
         async resetUserPassword(ctx) {
-            const response = {
-                err: 0,
-                msg: '',
-            };
             try {
             try {
                 // 获取项目数据
                 // 获取项目数据
                 const projectId = ctx.session.sessionProject.id;
                 const projectId = ctx.session.sessionProject.id;
@@ -328,19 +324,21 @@ module.exports = app => {
                 const accountId = parseInt(ctx.request.body.id);
                 const accountId = parseInt(ctx.request.body.id);
                 let password = ctx.request.body.reset_password;
                 let password = ctx.request.body.reset_password;
                 password = password.toString();
                 password = password.toString();
+                const account = ctx.request.body.account !== undefined ? ctx.request.body.account : '';
                 if (isNaN(accountId) || accountId <= 0 || password.length < 6) {
                 if (isNaN(accountId) || accountId <= 0 || password.length < 6) {
                     throw '参数错误';
                     throw '参数错误';
                 }
                 }
-                const result = await ctx.service.projectAccount.resetPassword(accountId, password);
+                const result = await ctx.service.projectAccount.resetPassword(accountId, password, account);
                 if (!result) {
                 if (!result) {
                     throw '重置密码失败!';
                     throw '重置密码失败!';
                 }
                 }
+                this.setMessage('保存账号数据成功', this.messageType.SUCCESS);
+                ctx.redirect(ctx.request.header.referer);
             } catch (error) {
             } catch (error) {
-                response.err = 1;
-                response.msg = error;
+                console.log(error);
+                this.setMessage(error.toString(), this.messageType.ERROR);
+                ctx.redirect(ctx.request.header.referer);
             }
             }
-
-            ctx.body = response;
         }
         }
 
 
         /**
         /**

+ 29 - 12
app/controller/stage_controller.js

@@ -323,6 +323,18 @@ module.exports = app => {
             }
             }
         }
         }
 
 
+        async check(ctx) {
+            try {
+                const ledgerData = await this._getStageLedgerData(ctx);
+                const posData = await this._getStagePosData(ctx);
+                const data = ctx.helper.checkBillsWithPos(ledgerData, posData, ['contract_qty', 'qc_qty']);
+                ctx.body = { err: 0, msg: '', data: data };
+            } catch (err) {
+                this.log(err);
+                ctx.body = this.ajaxErrorBody(err, '检查数据错误');
+            }
+        }
+
         /**
         /**
          * 获取期数据(截止上期 & 本期) (Ajax)
          * 获取期数据(截止上期 & 本期) (Ajax)
          * @param ctx
          * @param ctx
@@ -396,7 +408,8 @@ module.exports = app => {
                         responseData.data.curStageData = await ctx.service.stageBills.updateStageData(data.bills.stage);
                         responseData.data.curStageData = await ctx.service.stageBills.updateStageData(data.bills.stage);
                     }
                     }
                     if (data.bills.calcType) {
                     if (data.bills.calcType) {
-                        responseData.data = await ctx.service.stageBills.updateStageBillsCalcType(data.bills.calcType);                    }
+                        responseData.data = await ctx.service.stageBills.updateStageBillsCalcType(data.bills.calcType);
+                    }
                 }
                 }
                 await ctx.service.stage.updateCheckCalcFlag(ctx.stage.id, true);
                 await ctx.service.stage.updateCheckCalcFlag(ctx.stage.id, true);
                 await ctx.service.stage.updateCacheTime(ctx.stage.id);
                 await ctx.service.stage.updateCacheTime(ctx.stage.id);
@@ -999,11 +1012,10 @@ module.exports = app => {
 
 
                 await ctx.service.stageAudit.start(ctx.stage.id, ctx.stage.times);
                 await ctx.service.stageAudit.start(ctx.stage.id, ctx.stage.times);
 
 
-                ctx.redirect(ctx.request.header.referer);
+                ctx.body = {err: 0, msg: '', data: []};
             } catch (err) {
             } catch (err) {
                 this.log(err);
                 this.log(err);
-                ctx.session.postError = err.toString();
-                ctx.redirect(ctx.request.header.referer);
+                ctx.body = this.ajaxErrorBody(err, '上报失败');
             }
             }
         }
         }
         /**
         /**
@@ -1021,27 +1033,32 @@ module.exports = app => {
                 if (!this.ctx.stage.curAuditor || this.ctx.stage.curAuditor.aid !== ctx.session.sessionUser.accountId) {
                 if (!this.ctx.stage.curAuditor || this.ctx.stage.curAuditor.aid !== ctx.session.sessionUser.accountId) {
                     throw '您无权进行该操作';
                     throw '您无权进行该操作';
                 }
                 }
-                const data = {
-                    checkType: parseInt(ctx.request.body.checkType),
-                    opinion: ctx.request.body.opinion,
-                };
+                const data = JSON.parse(ctx.request.body.data);
+                //data.checkType = parseInt(data.checkType);
+                // const data = {
+                //     checkType: parseInt(ctx.request.body.checkType),
+                //     opinion: ctx.request.body.opinion,
+                // };
                 if (!data.checkType || isNaN(data.checkType)) {
                 if (!data.checkType || isNaN(data.checkType)) {
+                    console.log('error1');
                     throw '提交数据错误';
                     throw '提交数据错误';
                 }
                 }
                 if (data.checkType === auditConst.status.checkNo) {
                 if (data.checkType === auditConst.status.checkNo) {
                     if (!data.checkType || isNaN(data.checkType)) {
                     if (!data.checkType || isNaN(data.checkType)) {
+                        console.log('error2');
                         throw '提交数据错误';
                         throw '提交数据错误';
                     }
                     }
                 }
                 }
 
 
                 await ctx.service.stageAudit.check(ctx.stage.id, data, ctx.stage.times);
                 await ctx.service.stageAudit.check(ctx.stage.id, data, ctx.stage.times);
 
 
-                ctx.redirect(ctx.request.header.referer);
+                ctx.body = {err: 0, msg: '', data: []};//ctx.redirect(ctx.request.header.referer);
             } catch (err) {
             } catch (err) {
-                console.log(err);
+                //console.log(err);
                 this.log(err);
                 this.log(err);
-                ctx.session.postError = err.toString();
-                ctx.redirect(ctx.request.header.referer);
+                ctx.body = this.ajaxErrorBody(err, '提交失败');
+                // ctx.session.postError = err.toString();
+                // ctx.redirect(ctx.request.header.referer);
             }
             }
         }
         }
         /**
         /**

+ 4 - 2
app/controller/tender_controller.js

@@ -88,13 +88,15 @@ module.exports = app => {
                         if (t.lastStage.status === auditConst.stage.status.uncheck) {
                         if (t.lastStage.status === auditConst.stage.status.uncheck) {
                             const status_name = await this.ctx.service.projectAccount.getAccountInfoById(t.lastStage.user_id);
                             const status_name = await this.ctx.service.projectAccount.getAccountInfoById(t.lastStage.user_id);
                             t.status_users = status_name ? status_name.name : '';
                             t.status_users = status_name ? status_name.name : '';
+                            // const status_name = await this.ctx.service.stageAudit.getStatusName(t.lastStage.id, t.lastStage.times - 1);
+                            // t.status_users = status_name ? status_name.name : '';
                         } else {
                         } else {
-                            const status_name = await this.ctx.service.stageAudit.getStatusName(t.lastStage.id);
+                            const status_name = await this.ctx.service.stageAudit.getAuditorByStatus(t.lastStage.id, t.lastStage.status, t.lastStage.times);
                             t.status_users = status_name ? status_name.name : '';
                             t.status_users = status_name ? status_name.name : '';
                         }
                         }
                     } else {
                     } else {
                         if (t.ledger_status !== auditConst.ledger.status.uncheck) {
                         if (t.ledger_status !== auditConst.ledger.status.uncheck) {
-                            const status_name = await this.ctx.service.ledgerAudit.getStatusName(t.id);
+                            const status_name = await this.ctx.service.ledgerAudit.getStatusName(t.id, t.ledger_times);
                             t.status_users = status_name ? status_name.name : '';
                             t.status_users = status_name ? status_name.name : '';
                         }
                         }
                     }
                     }

+ 8 - 4
app/controller/wap_controller.js

@@ -22,6 +22,10 @@ module.exports = app => {
          * @return {void}
          * @return {void}
          */
          */
         async index(ctx) {
         async index(ctx) {
+            if (!ctx.helper.isMobile(ctx.request.header['user-agent'])) {
+                ctx.redirect('/');
+                return;
+            }
             const errorMessage = ctx.session.loginError;
             const errorMessage = ctx.session.loginError;
             // 显示完删除
             // 显示完删除
             ctx.session.loginError = null;
             ctx.session.loginError = null;
@@ -54,7 +58,6 @@ module.exports = app => {
          */
          */
         async login(ctx) {
         async login(ctx) {
             let loginType = ctx.request.body.type;
             let loginType = ctx.request.body.type;
-
             try {
             try {
                 loginType = parseInt(loginType);
                 loginType = parseInt(loginType);
                 const result = await ctx.service.projectAccount.accountLogin(ctx.request.body, loginType);
                 const result = await ctx.service.projectAccount.accountLogin(ctx.request.body, loginType);
@@ -242,10 +245,11 @@ module.exports = app => {
                         }
                         }
                     }
                     }
                     renderData.stage = stages[0];
                     renderData.stage = stages[0];
-                    renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stages[0].user_id);
-                    renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stages[0].id, renderData.stages[0].times);
+                    const times = renderData.stage.status === auditConst.stage.status.checkNo ? renderData.stage.times - 1 : renderData.stage.times;
+                    renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stage.user_id);
+                    renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stage.id, times);
                     // 获取审批流程中左边列表
                     // 获取审批流程中左边列表
-                    renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stages[0].id, renderData.stages[0].times);
+                    renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stage.id, times);
                 }
                 }
                 await ctx.render('wap/tender.ejs', renderData);
                 await ctx.render('wap/tender.ejs', renderData);
             } catch (err) {
             } catch (err) {

+ 55 - 7
app/extend/helper.js

@@ -965,13 +965,15 @@ module.exports = {
      * @returns {*}
      * @returns {*}
      */
      */
     async urlToShort(url) {
     async urlToShort(url) {
-        const apiUrl = 'https://api.uomg.com/api/long2dwz';
-        const data = {
-            dwzapi: 'tcn',
-            url,
-        };
-        const result = await this.sendRequest(apiUrl, data, 'get');
-        return result && result.code && result.code === 1 ? result.ae_url : url;
+        // const apiUrl = 'http://mrw.so/api.htm';
+        // const data = {
+        //     format: 'json',
+        //     url,
+        //     key: '5eccdd0144bb353b1cd45c31@0b0510deaba52dad36dc64dbecec5e54',
+        // };
+        // const result = await this.sendRequest(apiUrl, data, 'get');
+        // return result && result.err === '' && result.url ? result.url : url;
+        return url;
     },
     },
 
 
     /**
     /**
@@ -982,4 +984,50 @@ module.exports = {
     isWap(request) {
     isWap(request) {
         return request.url.indexOf('/wap/') !== -1;
         return request.url.indexOf('/wap/') !== -1;
     },
     },
+
+    checkBillsWithPos(bills, pos, fields) {
+        const result = {
+            error: [],
+            source: {
+                bills: [],
+                pos: [],
+            }
+        };
+        for (const b of bills) {
+            const pr = _.remove(pos, {lid: b.id});
+            const checkData = {}, calcData = {};
+            if (pr && pr.length > 0) {
+                for (const field of fields) {
+                    checkData[field] = b[field] ? b[field] : 0;
+                }
+                for (const p of pr) {
+                    for (const field of fields) {
+                        calcData[field] = this.add(calcData[field], p[field]);
+                    }
+                }
+                if (!_.isMatch(checkData, calcData)) {
+                    result.error.push({
+                        ledger_id: b.ledger_id,
+                        b_code: b.b_code,
+                        name: b.name,
+                        error: {checkData: checkData, calcData: calcData}
+                    });
+                    result.source.bills.push(b);
+                    for (const p of pr) {
+                        result.source.pos.push(p);
+                    }
+                }
+            }
+        }
+        return result;
+    },
+
+    /**
+     * 判断是否是移动端访问
+     * @param request
+     * @returns {*}
+     */
+    isMobile(agent) {
+        return agent.match(/(iphone|ipod|android)/i);
+    },
 }
 }

+ 11 - 12
app/public/css/main.css

@@ -80,23 +80,23 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 /*滚动条*/
 /*滚动条*/
 /* 滚动条 */
 /* 滚动条 */
 /*水平滚动条的样式*/
 /*水平滚动条的样式*/
-/*::-webkit-scrollbar-thumb:horizontal { 
+/*::-webkit-scrollbar-thumb:horizontal {
 	width: 5px;
 	width: 5px;
 	background-color: #e9ecef;
 	background-color: #e9ecef;
 	-webkit-border-radius: 0;
 	-webkit-border-radius: 0;
 }*/
 }*/
 /*滚动条的背景颜色,滚动条的圆角宽度*/
 /*滚动条的背景颜色,滚动条的圆角宽度*/
 /*::-webkit-scrollbar-track-piece {
 /*::-webkit-scrollbar-track-piece {
-	background-color: #efefef; 
-	-webkit-border-radius: 0; 
+	background-color: #efefef;
+	-webkit-border-radius: 0;
 }*/
 }*/
 /*滚动条的宽度,滚动条的高度*/
 /*滚动条的宽度,滚动条的高度*/
 /*::-webkit-scrollbar {
 /*::-webkit-scrollbar {
-	width: 14px; 
-	height: 14px; 
+	width: 14px;
+	height: 14px;
 }*/
 }*/
 /*垂直滚动条的样式*/
 /*垂直滚动条的样式*/
-/*::-webkit-scrollbar-thumb:vertical { 
+/*::-webkit-scrollbar-thumb:vertical {
 	height: 50px;
 	height: 50px;
 	background-color: #e9ecef;
 	background-color: #e9ecef;
 	-webkit-border-radius: 0;
 	-webkit-border-radius: 0;
@@ -105,7 +105,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 	border: 1px solid #ced4da;
 	border: 1px solid #ced4da;
 }*/
 }*/
 /*滚动条的hover样式*/
 /*滚动条的hover样式*/
-/*::-webkit-scrollbar-thumb:hover { 
+/*::-webkit-scrollbar-thumb:hover {
 	height: 50px;
 	height: 50px;
 	background-color: #ced4da;
 	background-color: #ced4da;
 	-webkit-border-radius: 0;
 	-webkit-border-radius: 0;
@@ -129,7 +129,6 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 }
 }
 .sjs-bottom{
 .sjs-bottom{
   height:400px;
   height:400px;
-  overflow-y: auto;
 }
 }
 .sjs-bottom-2{
 .sjs-bottom-2{
   height:360px;
   height:360px;
@@ -673,7 +672,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   font-size: 14px
   font-size: 14px
 }
 }
 .bd-toc {
 .bd-toc {
-  
+
     position: sticky;
     position: sticky;
     top:3rem;
     top:3rem;
     height: calc(100vh - 10rem);
     height: calc(100vh - 10rem);
@@ -828,7 +827,7 @@ body{
   line-height: 30px;
   line-height: 30px;
 }
 }
 .panel-title > .title-main .btn.pull-right {
 .panel-title > .title-main .btn.pull-right {
-    margin: 5px 0 0 0 
+    margin: 5px 0 0 0
 }
 }
 .panel-content{
 .panel-content{
   padding-top:35px;
   padding-top:35px;
@@ -1049,6 +1048,6 @@ a.maintain-icon .fa{
     }
     }
 }
 }
 
 
-a.maintain-icon:hover .fa{ 
+a.maintain-icon:hover .fa{
     animation-iteration-count:0
     animation-iteration-count:0
-}
+}

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

@@ -32,7 +32,7 @@ function autoFlashHeight(){
     $(".sjs-sh-4").height($(window).height()-cHeader-sBar4-92+55);
     $(".sjs-sh-4").height($(window).height()-cHeader-sBar4-92+55);
     $(".sjs-sh-5").height($(window).height()-cHeader-sBar5-92+55);
     $(".sjs-sh-5").height($(window).height()-cHeader-sBar5-92+55);
     for (const sh of $('.sjs-sh')) {
     for (const sh of $('.sjs-sh')) {
-        $(sh).height($(window).height()-cHeader-getObjHeight($('.sjs-bar', sh.parent))-92+55);
+        $(sh).height($(window).height()-cHeader-getObjHeight($('.sjs-bar', sh.parentNode))-92+55);
     }
     }
 };
 };
 $(window).resize(autoFlashHeight);
 $(window).resize(autoFlashHeight);

+ 8 - 65
app/public/js/ledger.js

@@ -56,30 +56,6 @@ $(document).ready(function() {
     });
     });
     const posSpread = SpreadJsObj.createNewSpread($('#pos-spread')[0]);
     const posSpread = SpreadJsObj.createNewSpread($('#pos-spread')[0]);
 
 
-
-    const showSideTools = function (show) {
-        const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
-        if (show) {
-            right.show();
-            autoFlashHeight();
-            /**
-             * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
-             * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
-             * 故需要通过最终的parent.width再计算一次left.width
-             *
-             * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
-             * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
-             *
-             */
-                //left.css('width', parent.width() - right.outerWidth());
-                //left.css('width', parent.width() - right.outerWidth());
-            const percent = 100 - right.outerWidth() /parent.width() * 100;
-            left.css('width', percent + '%');
-        } else {
-            left.width(parent.width());
-            right.hide();
-        }
-    };
     const errorList = $.cs_errorList({
     const errorList = $.cs_errorList({
         tabSelector: '#error-list-tab',
         tabSelector: '#error-list-tab',
         selector: '#error-list',
         selector: '#error-list',
@@ -92,7 +68,6 @@ $(document).ready(function() {
             ledgerSpread.refresh();
             ledgerSpread.refresh();
             if (posSpread) posSpread.refresh();
             if (posSpread) posSpread.refresh();
         },
         },
-        showSideTools: showSideTools,
     });
     });
 
 
     $.subMenu({
     $.subMenu({
@@ -2604,54 +2579,22 @@ $(document).ready(function() {
     });
     });
 
 
     const dataChecker = DataChecker({
     const dataChecker = DataChecker({
-        loadUrl: window.location.pathname + '/load',
-        loadData: {},
-        checkFun: function (data, progress) {
-            ledgerTree.loadDatas(data.bills);
-            treeCalc.calculateAll(ledgerTree);
-            SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
-
-            pos.loadDatas(data.pos);
+        checkUrl: window.location.pathname + '/check',
+        completeData: function (data) {
+            pos.updateDatas({update: data.source.pos});
+            const loadResult = ledgerTree.loadPostData({update: data.source.bills});
+            treeOperationObj.refreshTree(ledgerSpread.getActiveSheet(), loadResult);
             posOperationObj.loadCurPosData();
             posOperationObj.loadCurPosData();
-
-            const checkFields = ['sgfh_qty', 'qtcl_qty', 'sjcl_qty', 'quantity'], result = [];
-            const iLen = data.bills.length;
-            for (const [i, b] of data.bills.entries()) {
-                const pr = _.filter(data.pos, {lid: b.id});
-                if (pr && pr.length > 0) {
-                    const checkData = {}, calcData = {};
-                    for (const field of checkFields) {
-                        checkData[field] = b[field] ? b[field] : 0;
-                    }
-                    for (p of pr) {
-                        for (const field of checkFields) {
-                            calcData[field] = ZhCalc.add(calcData[field], p[field]);
-                        }
-                    }
-                    for (const field of checkFields) {
-                        calcData[field] = calcData[field] ? calcData[field] : 0;
-                    }
-                    if (!_.isMatch(checkData, calcData)) {
-                        result.push({
-                            ledger_id: b.ledger_id,
-                            b_code: b.b_code,
-                            name: b.name,
-                            serialNo: ledgerTree.getNodeIndex(ledgerTree.getItems(b.ledger_id)) + 1,
-                            error: {checkData: checkData, calcData: calcData}
-                        })
-                    }
-                    progress(parseInt((i+1)/iLen*100));
-                }
+            for (const e of data.error) {
+                e.serialNo = ledgerTree.getNodeIndex(ledgerTree.getItems(e.ledger_id)) + 1;
             }
             }
-            return result;
         },
         },
         errorList: errorList,
         errorList: errorList,
     });
     });
     $('[name=audit-start]').submit(function (e) {
     $('[name=audit-start]').submit(function (e) {
         if (checkAuditorFrom()) {
         if (checkAuditorFrom()) {
             $(this).parent().parent().parent().modal('hide');
             $(this).parent().parent().parent().modal('hide');
-            const formData = new FormData();
-            dataChecker.checkAndPost(this.action, formData);
+            dataChecker.checkAndPost(this.action, {});
             $('#hide-all').hide();
             $('#hide-all').hide();
         }
         }
         return false;
         return false;

+ 0 - 225
app/public/js/ledger_search.js

@@ -1,225 +0,0 @@
-'use strict';
-
-/**
- * 台账搜索相关
- * 多个页面均使用:
- * 0好台账:台账分解、台账审批、台账修订、部位台账
- * 期计量:计量台账、部位台账
- *
- * 搜索基于spreadjs,请放在gc.spread.sheets.all.10.0.1.min.js/spreadjs_zh.js之后
- *
- * @author Mai
- * @date
- * @version
- */
-
-(function($){
-    $.posSearch = function (setting) {
-        if (!setting.selector || !setting.searchSpread) return;
-        const searchHtml =
-            '                                <div class="ml-2">\n' +
-            '                                    <div class="input-group input-group-sm">\n' +
-            '                                        <input type="text" class="form-control" placeholder="输入名称查找" id="pos-keyword">\n' +
-            '                                        <div class="input-group-append">\n' +
-            '                                            <span class="input-group-text" id="pos-search-hint">结果:0</span>\n' +
-            '                                        </div>\n' +
-            '                                        <div class="input-group-append" >\n' +
-            '                                            <button class="btn btn-outline-secondary" type="button" title="上一个" id="search-pre-pos"><i class="fa fa-angle-double-left"></i></button>\n' +
-            '                                            <button class="btn btn-outline-secondary" type="button" title="下一个" id="search-next-pos"><i class="fa fa-angle-double-right"></i></button>\n' +
-            '                                        </div>\n' +
-            '                                    </div>\n' +
-            '                                </div>\n';
-        $(setting.selector).html(searchHtml);
-        const sheet = setting.searchSpread.getActiveSheet();
-        const searchObj = (function () {
-            let resultArr = [];
-            const search = function (keyword) {
-                if (keyword && keyword !== '') {
-                    resultArr = [];
-                    const sortData = sheet.zh_data;
-                    if (sortData) {
-                        for (let i = 0, iLength = sortData.length; i < iLength; i++) {
-                            const sd = sortData[i];
-                            if (sd.name && sd.name.indexOf(keyword) > -1) {
-                                resultArr.push({index: i, data: sd});
-                            }
-                        }
-                    }
-                } else {
-                    resultArr = [];
-                }
-                $('#pos-search-hint').html('结果:' + resultArr.length);
-            };
-            const searchAndLocate = function (keyword) {
-                search(keyword);
-                if (resultArr.length > 0) {
-                    const sel = sheet.getSelections()[0];
-                    const curRow = sel ? sel.row : 0;
-                    const pos = resultArr[0];
-                    if (pos.index !== curRow) {
-                        sheet.setSelection(pos.index, sel ? sel.col : 0, 1, 1);
-                        sheet.getParent().focus();
-                        sheet.showRow(pos.index, spreadNS.VerticalPosition.center);
-                    }
-                }
-            };
-            const locateNext = function () {
-                if (resultArr.length > 0) {
-                    const sel = sheet.getSelections()[0];
-                    const curRow = sel ? sel.row : 0;
-                    let next = _.find(resultArr, function (d) {
-                        return d.index > curRow;
-                    });
-                    if (!next) next = resultArr[0];
-                    if (next.index !== curRow) {
-                        sheet.setSelection(next.index, sel ? sel.col : 0, 1, 1);
-                        sheet.getParent().focus();
-                        sheet.showRow(next.index, spreadNS.VerticalPosition.center);
-                    }
-                }
-            };
-            const locatePre = function () {
-                if (resultArr.length > 0) {
-                    const sel = sheet.getSelections()[0];
-                    const curRow = sel ? sel.row : 0;
-                    let next = _.findLast(resultArr, function (d) {
-                        return d.index < curRow;
-                    });
-                    if (!next) next = resultArr[resultArr.length - 1];
-                    if (next.index !== curRow) {
-                        sheet.setSelection(next.index, sel ? sel.col : 0, 1, 1);
-                        sheet.getParent().focus();
-                        sheet.showRow(next.index, spreadNS.VerticalPosition.center);
-                    }
-                }
-            };
-            return {search, searchAndLocate, locateNext, locatePre};
-        })();
-        // $('#pos-keyword').bind('input propertychange', function () {
-        //     posSearch.search(this.value);
-        // });
-        $('#pos-keyword').bind('keydown', function(e){
-            if (e.keyCode == 13) searchObj.searchAndLocate(this.value);
-        });
-        $('#search-pre-pos').click(function () {
-            searchObj.locatePre();
-        });
-        $('#search-next-pos').click(function () {
-            searchObj.locateNext();
-        });
-        return searchObj;
-    };
-    $.billsSearch = function (setting) {
-        if (!setting.selector || !setting.searchSpread || !setting.resultSpreadSetting) return;
-        if (!setting.searchRangeStr) setting.searchRangeStr = '项目节编号/清单编号/名称';
-        const resultId = setting.id + '-search-result';
-        const obj = $(setting.selector);
-        obj.html(
-            '                        <div class="sjs-bar">\n' +
-            '                            <div class="input-group input-group-sm pb-1">\n' +
-            '                                <div class="input-group-prepend">\n' +
-            (setting.searchOver ? '                                    <div class="input-group-text"><input type="radio" name="searchType" id="over"> 超计</div>\n' : '') +
-            (setting.searchEmpty ? '                                    <div class="input-group-text"><input type="radio" name="searchType" id="empty"> 漏计</div>\n' : '') +
-            '                                </div>' +
-            '                                <input id="searchKeyword" type="text" class="form-control" placeholder="可查找 ' + setting.searchRangeStr + '" aria-label="Recipient\'s username" aria-describedby="button-addon2">\n' +
-            '                                <div class="input-group-append">\n' +
-            '                                    <button class="btn btn-outline-secondary" type="button"">搜索</button>\n' +
-            '                                </div>\n' +
-            '                            </div>\n' +
-            '                        </div>\n' +
-            '                        <div id="' + resultId + '" class="sjs-sh">\n' +
-            '                        </div>'
-        );
-        autoFlashHeight();
-        const resultSpread = SpreadJsObj.createNewSpread($('#' + resultId)[0]);
-        SpreadJsObj.initSheet(resultSpread.getActiveSheet(), setting.resultSpreadSetting);
-        SpreadJsObj.forbiddenSpreadContextMenu('#' + resultId, resultSpread);
-        const searchSheet = setting.searchSpread.getActiveSheet();
-        let searchResult = [];
-        const searchBills = function () {
-            const keyword = $('#searchKeyword', obj).val();
-            searchResult = [];
-            const sortData = SpreadJsObj.getSortData(searchSheet);
-            for (const node of sortData) {
-                if ((node.code && node.code.indexOf(keyword) > -1) ||
-                    node.b_code && node.b_code.indexOf(keyword) > -1 ||
-                    node.name && node.name.indexOf(keyword) > -1) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
-                }
-            }
-            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
-        };
-        const calculateCompletePercent = function (searchResult) {
-            if (!searchResult) return;
-            for (const sr of searchResult) {
-                const base = ZhCalc.add(sr.total_price, sr.end_qc_tp);
-                sr.complete_percent = base !== 0 ? ZhCalc.mul(ZhCalc.div(sr.end_gather_tp, base), 100, 2) : 0;
-            }
-        };
-        const searchOver = function () {
-            searchResult = [];
-            const sortData = SpreadJsObj.getSortData(searchSheet);
-            for (const node of sortData) {
-                if (node.children && node.children.length > 0) continue;
-                if (setting.checkOver && setting.checkOver(node)) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
-                }
-            }
-            calculateCompletePercent(searchResult);
-            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
-        };
-        const searchEmpty = function () {
-            searchResult = [];
-            const sortData = SpreadJsObj.getSortData(searchSheet);
-            for (const node of sortData) {
-                if (node.children && node.children.length > 0) continue;
-                if (setting.checkEmpty && setting.checkEmpty(node)) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
-                }
-            }
-            calculateCompletePercent(searchResult);
-            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
-        };
-        const searchLess = function () {
-            searchResult = [];
-            const sortData = SpreadJsObj.getSortData(searchSheet);
-            for (const node of sortData) {
-                if (node.children && node.children.length > 0) continue;
-                if (setting.checkLess && setting.checkLess(node)) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
-                }
-            }
-            calculateCompletePercent(searchResult);
-            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
-        };
-
-        $('input', obj).bind('keydown', function (e) {
-            if (e.keyCode == 13) searchBills();
-        });
-        $('button', obj).bind('click', () => {searchBills()});
-        $('#over', obj).bind('change', () => {searchOver()});
-        $('#empty', obj).bind('change', () => {searchLess()});
-        resultSpread.getActiveSheet().bind(spreadNS.Events.CellDoubleClick, function (e, info) {
-            const sheet = info.sheet;
-            const data = sheet.zh_data;
-            if (!data) { return }
-
-            const curBills = data[info.row];
-            if (!curBills) { return }
-
-            SpreadJsObj.locateTreeNode(searchSheet, curBills.ledger_id, true);
-            if (setting.afterLocated) {
-                setting.afterLocated();
-            }
-        });
-        return {spread: resultSpread};
-    };
-})(jQuery);

+ 39 - 24
app/public/js/revise.js

@@ -34,6 +34,20 @@ $(document).ready(() => {
 
 
     const posSearch = $.posSearch({selector: '#pos-search', searchSpread: posSpread});
     const posSearch = $.posSearch({selector: '#pos-search', searchSpread: posSpread});
 
 
+    const errorList = $.cs_errorList({
+        tabSelector: '#error-list-tab',
+        selector: '#error-list',
+        relaSpread: billsSpread,
+        storeKey: 'revise-error-' + window.location.pathname.split('/')[2] + '-' + window.location.pathname.split('/')[4],
+        afterLocated:  function () {
+            posSpreadObj.loadCurPosData();
+        },
+        afterShow: function () {
+            billsSpread.refresh();
+            if (posSpread) posSpread.refresh();
+        },
+    });
+
     // 初始化 节点树结构
     // 初始化 节点树结构
     const treeSetting = {
     const treeSetting = {
         id: 'ledger_id',
         id: 'ledger_id',
@@ -1940,29 +1954,6 @@ $(document).ready(() => {
         }
         }
     });
     });
 
 
-    const showSideTools = function (show) {
-        const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
-        if (show) {
-            right.show();
-            autoFlashHeight();
-            /**
-             * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
-             * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
-             * 故需要通过最终的parent.width再计算一次left.width
-             *
-             * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
-             * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
-             *
-             */
-                //left.css('width', parent.width() - right.outerWidth());
-                //left.css('width', parent.width() - right.outerWidth());
-            const percent = 100 - right.outerWidth() /parent.width() * 100;
-            left.css('width', percent + '%');
-        } else {
-            left.width(parent.width());
-            right.hide();
-        }
-    };
     $('#content-tab').addClass('active');
     $('#content-tab').addClass('active');
     $('#xd-content').addClass('active');
     $('#xd-content').addClass('active');
     showSideTools(true);
     showSideTools(true);
@@ -2109,7 +2100,7 @@ $(document).ready(() => {
             } else if (tab.attr('content') === '#bg-bills') {
             } else if (tab.attr('content') === '#bg-bills') {
                 bgBills.loadData();
                 bgBills.loadData();
                 bgBills.spread.refresh();
                 bgBills.spread.refresh();
-            } else if (tab.attr('content') === '#search' && !searchLedger) {
+            } else if (tab.attr('content') === '#search') {
                 if (!searchLedger) {
                 if (!searchLedger) {
                     searchLedger = $.billsSearch({
                     searchLedger = $.billsSearch({
                         selector: '#search',
                         selector: '#search',
@@ -2137,6 +2128,8 @@ $(document).ready(() => {
                     });
                     });
                 }
                 }
                 searchLedger.spread.refresh();
                 searchLedger.spread.refresh();
+            } else if (tab.attr('content') === '#error-list') {
+                errorList.spread.refresh();
             }
             }
         }
         }
         else {// 收起工具栏
         else {// 收起工具栏
@@ -2186,5 +2179,27 @@ $(document).ready(() => {
             }
             }
         });
         });
     })('a[name=showLevel]', billsSheet);
     })('a[name=showLevel]', billsSheet);
+
+    const dataChecker = DataChecker({
+        checkUrl: window.location.pathname + '/check',
+        completeData: function (data) {
+            pos.updateDatas({update: data.source.pos});
+            const loadResult = billsTree.loadPostData({update: data.source.bills});
+            billsTreeSpreadObj.refreshTree(billsSheet, loadResult);
+            posSpreadObj.loadCurPosData();
+            for (const e of data.error) {
+                e.serialNo = billsTree.getNodeIndex(billsTree.getItems(e.ledger_id)) + 1;
+            }
+        },
+        errorList: errorList,
+    });
+    $('[name=revise-start]').submit(function (e) {
+        if (checkAuditorFrom()) {
+            $(this).parent().parent().parent().modal('hide');
+            dataChecker.checkAndPost(this.action, {});
+            $('#hide-all').hide();
+        }
+        return false;
+    });
 });
 });
 
 

+ 27 - 1
app/public/js/setting.js

@@ -39,7 +39,10 @@ $(document).ready(() => {
         } else {
         } else {
             $('#edit-user input[name="mobile"]').siblings('small').hide();
             $('#edit-user input[name="mobile"]').siblings('small').hide();
         }
         }
-
+        $('#edit-password input[name="account"]').val(account.account);
+        $('#edit-password input[class="account-check"]').val(account.account);
+        $('#edit-password input[name="id"]').val(account.id);
+        $('#edit-password input[name="reset_password"]').val('');
     });
     });
 
 
     // 分配随机密码
     // 分配随机密码
@@ -48,6 +51,12 @@ $(document).ready(() => {
         $(this).parent().parent().find('input').val(password);
         $(this).parent().parent().find('input').val(password);
     });
     });
 
 
+    // 分配随机密码
+    $("#rand-password2").click(function() {
+        const password = randPassword();
+        $(this).parent().parent().find('input').val(password);
+    });
+
     // 重置密码
     // 重置密码
     let isChange = false;
     let isChange = false;
     $("#reset-password-btn").click(function() {
     $("#reset-password-btn").click(function() {
@@ -162,6 +171,23 @@ $(document).ready(() => {
     })
     })
 });
 });
 
 
+function checkPasswordForm() {
+    try {
+        if ($('#edit-password input[name="account"]').val() == '' || $('#edit-password input[name="account"]').hasClass('is-invalid')) {
+            throw '账号不能为空或已存在';
+        }
+        const resetPassword = $('#edit-password input[name="reset_password"]').val();
+        if (resetPassword.length < 6) {
+            throw '密码长度不能小于6';
+        }
+        if (!/^[0-9a-zA-Z*~!@&%$^\\(\\)#_\[\]\-\+={}|?'":,<>.`]+$/.test(resetPassword)) {
+            throw '密码只支持英文数字及符号';
+        }
+    } catch (err) {
+        toastr.error(err);
+        return false;
+    }
+}
 
 
 /**
 /**
  * 表单检测
  * 表单检测

+ 326 - 35
app/public/js/shares/cs_tools.js

@@ -1,16 +1,49 @@
 'use strict';
 'use strict';
 
 
 /**
 /**
+ * cs_errorList:错误列表
+ * 使用范围:
+ *    台账分解(原报)、台账修订(原报)、计量台账(所有角色)
  *
  *
+ * posSearch & billsSearch:台账搜索相关
+ * 使用范围:
+ *    0号台账:台账分解、台账审批、台账修订、部位台账;
+ *    期计量:计量台账、部位台账
+ *
+ * 所有工具均基于spreadjs,请放在gc.spread.sheets.all.10.0.1.min.js/spreadjs_zh.js之后
  *
  *
  * @author Mai
  * @author Mai
  * @date
  * @date
  * @version
  * @version
  */
  */
 
 
+const showSideTools = function (show) {
+    const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
+    if (show) {
+        right.show();
+        autoFlashHeight();
+        /**
+         * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
+         * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
+         * 故需要通过最终的parent.width再计算一次left.width
+         *
+         * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
+         * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
+         *
+         */
+            //left.css('width', parent.width() - right.outerWidth());
+            //left.css('width', parent.width() - right.outerWidth());
+        const percent = 100 - right.outerWidth() /parent.width() * 100;
+        left.css('width', percent + '%');
+    } else {
+        left.width(parent.width());
+        right.hide();
+    }
+};
+
 (function($){
 (function($){
     /**
     /**
-     *
+     * 错误列表
      * @param setting
      * @param setting
      * {
      * {
      *      tabSelector: 'a[content=#error-list]',
      *      tabSelector: 'a[content=#error-list]',
@@ -21,7 +54,6 @@
      * @returns {{spread: *}}
      * @returns {{spread: *}}
      */
      */
     $.cs_errorList = function (setting) {
     $.cs_errorList = function (setting) {
-        if (!setting.selector || !setting.relaSpread) return;
         if (!setting.spreadSetting) {
         if (!setting.spreadSetting) {
             setting.spreadSetting = {
             setting.spreadSetting = {
                 cols: [
                 cols: [
@@ -40,20 +72,303 @@
             };
             };
         }
         }
 
 
-        const resultId = setting.id + '-spread';
+        const clearErrorData = function () {
+            if (setting.storeKey) removeLocalCache(setting.storeKey);
+        };
+
+        const autoShowHistory = function (show) {
+            if (setting.storeKey) {
+                setLocalCache(setting.storeKey + '-showHis', show.toString());
+            }
+        };
+
+        if (setting.selector && setting.relaSpread) {
+            const resultId = setting.id + '-spread';
+            const obj = $(setting.selector);
+            obj.html(
+                '                        <div id="' + resultId + '" class="sjs-sh">\n' +
+                '                        </div>'
+            );
+            autoFlashHeight();
+
+            const spread = SpreadJsObj.createNewSpread($('#' + resultId)[0]);
+            const sheet = spread.getActiveSheet();
+            SpreadJsObj.initSheet(sheet, setting.spreadSetting);
+            SpreadJsObj.forbiddenSpreadContextMenu('#' + resultId, spread);
+
+            spread.getActiveSheet().bind(spreadNS.Events.CellDoubleClick, function (e, info) {
+                const sheet = info.sheet;
+                const data = sheet.zh_data;
+                if (!data) { return }
+
+                const curBills = data[info.row];
+                if (!curBills) { return }
+
+                SpreadJsObj.locateTreeNode(setting.relaSpread.getActiveSheet(), curBills.ledger_id, true);
+                console.log(curBills);
+                if (setting.afterLocated) {
+                    setting.afterLocated();
+                }
+            });
+
+            const loadErrorData = function (data, his = false) {
+                const sourceTree = setting.relaSpread.getActiveSheet().zh_tree;
+                if (!sourceTree) return;
+
+                for (const d of data) {
+                    d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
+                }
+                data.sort(function (a, b) {
+                    return a.serialNo - b.serialNo;
+                });
+
+                SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Data, data);
+                if (!his && setting.storeKey) {
+                    setLocalCache(setting.storeKey, JSON.stringify(data));
+                }
+                $(setting.tabSelector).show();
+            };
+            const showErrorList = function () {
+                const tab = $(setting.tabSelector), tabPanel = $(tab.attr('content'));
+                $('a', '#side-menu').removeClass('active');
+                tab.addClass('active');
+                $('.tab-content .tab-pane').removeClass('active');
+                tabPanel.addClass('active');
+                showSideTools(true);
+                spread.refresh();
+                if (setting.afterShow) setting.afterShow();
+            };
+            const loadHisErrorData = function () {
+                if (setting.storeKey) {
+                    const storeStr = getLocalCache(setting.storeKey);
+
+                    const storeData = storeStr ? JSON.parse(storeStr) : [];
+                    if (storeData.length > 0) {
+                        loadErrorData(storeData, true);
+                        const showHis = getLocalCache(setting.storeKey + '-showHis');
+                        if (showHis === 'true') {
+                            showErrorList();
+                            removeLocalCache(setting.storeKey + '-showHis');
+                        }
+                    }
+                }
+            };
+            return {
+                spread: spread,
+                loadErrorData: loadErrorData,
+                clearErrorData: clearErrorData,
+                loadHisErrorData: loadHisErrorData,
+                show: showErrorList,
+                autoShowHistory: autoShowHistory,
+            };
+        } else {
+            const loadErrorData = function (data) {
+                if (setting.storeKey) {
+                    setLocalCache(setting.storeKey, JSON.stringify(data));
+                }
+            };
+            return {
+                loadErrorData: loadErrorData,
+                clearErrorData: clearErrorData,
+                autoShowHistory: autoShowHistory,
+            };
+        }
+    };
+
+    $.posSearch = function (setting) {
+        if (!setting.selector || !setting.searchSpread) return;
+        const searchHtml =
+            '                                <div class="ml-2">\n' +
+            '                                    <div class="input-group input-group-sm">\n' +
+            '                                        <input type="text" class="form-control" placeholder="输入名称查找" id="pos-keyword">\n' +
+            '                                        <div class="input-group-append">\n' +
+            '                                            <span class="input-group-text" id="pos-search-hint">结果:0</span>\n' +
+            '                                        </div>\n' +
+            '                                        <div class="input-group-append" >\n' +
+            '                                            <button class="btn btn-outline-secondary" type="button" title="上一个" id="search-pre-pos"><i class="fa fa-angle-double-left"></i></button>\n' +
+            '                                            <button class="btn btn-outline-secondary" type="button" title="下一个" id="search-next-pos"><i class="fa fa-angle-double-right"></i></button>\n' +
+            '                                        </div>\n' +
+            '                                    </div>\n' +
+            '                                </div>\n';
+        $(setting.selector).html(searchHtml);
+        const sheet = setting.searchSpread.getActiveSheet();
+        const searchObj = (function () {
+            let resultArr = [];
+            const search = function (keyword) {
+                if (keyword && keyword !== '') {
+                    resultArr = [];
+                    const sortData = sheet.zh_data;
+                    if (sortData) {
+                        for (let i = 0, iLength = sortData.length; i < iLength; i++) {
+                            const sd = sortData[i];
+                            if (sd.name && sd.name.indexOf(keyword) > -1) {
+                                resultArr.push({index: i, data: sd});
+                            }
+                        }
+                    }
+                } else {
+                    resultArr = [];
+                }
+                $('#pos-search-hint').html('结果:' + resultArr.length);
+            };
+            const searchAndLocate = function (keyword) {
+                search(keyword);
+                if (resultArr.length > 0) {
+                    const sel = sheet.getSelections()[0];
+                    const curRow = sel ? sel.row : 0;
+                    const pos = resultArr[0];
+                    if (pos.index !== curRow) {
+                        sheet.setSelection(pos.index, sel ? sel.col : 0, 1, 1);
+                        sheet.getParent().focus();
+                        sheet.showRow(pos.index, spreadNS.VerticalPosition.center);
+                    }
+                }
+            };
+            const locateNext = function () {
+                if (resultArr.length > 0) {
+                    const sel = sheet.getSelections()[0];
+                    const curRow = sel ? sel.row : 0;
+                    let next = _.find(resultArr, function (d) {
+                        return d.index > curRow;
+                    });
+                    if (!next) next = resultArr[0];
+                    if (next.index !== curRow) {
+                        sheet.setSelection(next.index, sel ? sel.col : 0, 1, 1);
+                        sheet.getParent().focus();
+                        sheet.showRow(next.index, spreadNS.VerticalPosition.center);
+                    }
+                }
+            };
+            const locatePre = function () {
+                if (resultArr.length > 0) {
+                    const sel = sheet.getSelections()[0];
+                    const curRow = sel ? sel.row : 0;
+                    let next = _.findLast(resultArr, function (d) {
+                        return d.index < curRow;
+                    });
+                    if (!next) next = resultArr[resultArr.length - 1];
+                    if (next.index !== curRow) {
+                        sheet.setSelection(next.index, sel ? sel.col : 0, 1, 1);
+                        sheet.getParent().focus();
+                        sheet.showRow(next.index, spreadNS.VerticalPosition.center);
+                    }
+                }
+            };
+            return {search, searchAndLocate, locateNext, locatePre};
+        })();
+        // $('#pos-keyword').bind('input propertychange', function () {
+        //     posSearch.search(this.value);
+        // });
+        $('#pos-keyword').bind('keydown', function(e){
+            if (e.keyCode == 13) searchObj.searchAndLocate(this.value);
+        });
+        $('#search-pre-pos').click(function () {
+            searchObj.locatePre();
+        });
+        $('#search-next-pos').click(function () {
+            searchObj.locateNext();
+        });
+        return searchObj;
+    };
+    $.billsSearch = function (setting) {
+        if (!setting.selector || !setting.searchSpread || !setting.resultSpreadSetting) return;
+        if (!setting.searchRangeStr) setting.searchRangeStr = '项目节编号/清单编号/名称';
+        const resultId = setting.id + '-search-result';
         const obj = $(setting.selector);
         const obj = $(setting.selector);
         obj.html(
         obj.html(
+            '                        <div class="sjs-bar">\n' +
+            '                            <div class="input-group input-group-sm pb-1">\n' +
+            '                                <div class="input-group-prepend">\n' +
+            (setting.searchOver ? '                                    <div class="input-group-text"><input type="radio" name="searchType" id="over"> 超计</div>\n' : '') +
+            (setting.searchEmpty ? '                                    <div class="input-group-text"><input type="radio" name="searchType" id="empty"> 漏计</div>\n' : '') +
+            '                                </div>' +
+            '                                <input id="searchKeyword" type="text" class="form-control" placeholder="可查找 ' + setting.searchRangeStr + '" aria-label="Recipient\'s username" aria-describedby="button-addon2">\n' +
+            '                                <div class="input-group-append">\n' +
+            '                                    <button class="btn btn-outline-secondary" type="button"">搜索</button>\n' +
+            '                                </div>\n' +
+            '                            </div>\n' +
+            '                        </div>\n' +
             '                        <div id="' + resultId + '" class="sjs-sh">\n' +
             '                        <div id="' + resultId + '" class="sjs-sh">\n' +
             '                        </div>'
             '                        </div>'
         );
         );
         autoFlashHeight();
         autoFlashHeight();
+        const resultSpread = SpreadJsObj.createNewSpread($('#' + resultId)[0]);
+        SpreadJsObj.initSheet(resultSpread.getActiveSheet(), setting.resultSpreadSetting);
+        SpreadJsObj.forbiddenSpreadContextMenu('#' + resultId, resultSpread);
+        const searchSheet = setting.searchSpread.getActiveSheet();
+        let searchResult = [];
+        const searchBills = function () {
+            const keyword = $('#searchKeyword', obj).val();
+            searchResult = [];
+            const sortData = SpreadJsObj.getSortData(searchSheet);
+            for (const node of sortData) {
+                if ((node.code && node.code.indexOf(keyword) > -1) ||
+                    node.b_code && node.b_code.indexOf(keyword) > -1 ||
+                    node.name && node.name.indexOf(keyword) > -1) {
+                    const data = JSON.parse(JSON.stringify(node));
+                    data.visible = true;
+                    searchResult.push(data);
+                }
+            }
+            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
+        };
+        const calculateCompletePercent = function (searchResult) {
+            if (!searchResult) return;
+            for (const sr of searchResult) {
+                const base = ZhCalc.add(sr.total_price, sr.end_qc_tp);
+                sr.complete_percent = base !== 0 ? ZhCalc.mul(ZhCalc.div(sr.end_gather_tp, base), 100, 2) : 0;
+            }
+        };
+        const searchOver = function () {
+            searchResult = [];
+            const sortData = SpreadJsObj.getSortData(searchSheet);
+            for (const node of sortData) {
+                if (node.children && node.children.length > 0) continue;
+                if (setting.checkOver && setting.checkOver(node)) {
+                    const data = JSON.parse(JSON.stringify(node));
+                    data.visible = true;
+                    searchResult.push(data);
+                }
+            }
+            calculateCompletePercent(searchResult);
+            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
+        };
+        const searchEmpty = function () {
+            searchResult = [];
+            const sortData = SpreadJsObj.getSortData(searchSheet);
+            for (const node of sortData) {
+                if (node.children && node.children.length > 0) continue;
+                if (setting.checkEmpty && setting.checkEmpty(node)) {
+                    const data = JSON.parse(JSON.stringify(node));
+                    data.visible = true;
+                    searchResult.push(data);
+                }
+            }
+            calculateCompletePercent(searchResult);
+            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
+        };
+        const searchLess = function () {
+            searchResult = [];
+            const sortData = SpreadJsObj.getSortData(searchSheet);
+            for (const node of sortData) {
+                if (node.children && node.children.length > 0) continue;
+                if (setting.checkLess && setting.checkLess(node)) {
+                    const data = JSON.parse(JSON.stringify(node));
+                    data.visible = true;
+                    searchResult.push(data);
+                }
+            }
+            calculateCompletePercent(searchResult);
+            SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
+        };
 
 
-        const spread = SpreadJsObj.createNewSpread($('#' + resultId)[0]);
-        const sheet = spread.getActiveSheet();
-        SpreadJsObj.initSheet(sheet, setting.spreadSetting);
-        SpreadJsObj.forbiddenSpreadContextMenu('#' + resultId, spread);
-
-        spread.getActiveSheet().bind(spreadNS.Events.CellDoubleClick, function (e, info) {
+        $('input', obj).bind('keydown', function (e) {
+            if (e.keyCode == 13) searchBills();
+        });
+        $('button', obj).bind('click', () => {searchBills()});
+        $('#over', obj).bind('change', () => {searchOver()});
+        $('#empty', obj).bind('change', () => {searchLess()});
+        resultSpread.getActiveSheet().bind(spreadNS.Events.CellDoubleClick, function (e, info) {
             const sheet = info.sheet;
             const sheet = info.sheet;
             const data = sheet.zh_data;
             const data = sheet.zh_data;
             if (!data) { return }
             if (!data) { return }
@@ -61,35 +376,11 @@
             const curBills = data[info.row];
             const curBills = data[info.row];
             if (!curBills) { return }
             if (!curBills) { return }
 
 
-            SpreadJsObj.locateTreeNode(setting.relaSpread.getActiveSheet(), curBills.ledger_id, true);
-            console.log(curBills);
+            SpreadJsObj.locateTreeNode(searchSheet, curBills.ledger_id, true);
             if (setting.afterLocated) {
             if (setting.afterLocated) {
                 setting.afterLocated();
                 setting.afterLocated();
             }
             }
         });
         });
-
-        const loadErrorData = function (data, his = false) {
-            SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Data, data);
-            if (!his && setting.storeKey) {
-                setLocalCache(setting.storeKey, JSON.stringify(data));
-            }
-            $(setting.tabSelector).show();
-        };
-        if (setting.storeKey) {
-            const storeStr = getLocalCache(setting.storeKey);
-            const storeData = storeStr ? JSON.parse(storeStr) : [];
-            if (storeData.length > 0) loadErrorData(storeData, true);
-        }
-        const showErrorList = function () {
-            const tab = $(setting.tabSelector), tabPanel = $(tab.attr('content'));
-            $('a', '#side-menu').removeClass('active');
-            tab.addClass('active');
-            $('.tab-content .tab-pane').removeClass('active');
-            tabPanel.addClass('active');
-            setting.showSideTools(true);
-            spread.refresh();
-            if (setting.afterShow) setting.afterShow();
-        };
-        return {spread: spread, loadErrorData: loadErrorData, show: showErrorList};
+        return {spread: resultSpread};
     };
     };
 })(jQuery);
 })(jQuery);

+ 102 - 25
app/public/js/stage.js

@@ -508,6 +508,20 @@ $(document).ready(() => {
     };
     };
     SpreadJsObj.initSheet(spSpread.getActiveSheet(), posSpreadSetting);
     SpreadJsObj.initSheet(spSpread.getActiveSheet(), posSpreadSetting);
 
 
+    const errorList = $.cs_errorList({
+        tabSelector: '#error-list-tab',
+        selector: '#error-list',
+        relaSpread: slSpread,
+        storeKey: 'stage-error-' + stage.id,
+        afterLocated:  function () {
+            stagePosSpreadObj.loadCurPosData();
+        },
+        afterShow: function () {
+            slSpread.refresh();
+            if (spSpread) spSpread.refresh();
+        },
+    });
+
     const stageTreeSpreadObj = {
     const stageTreeSpreadObj = {
         loadExprToInput(sheet) {
         loadExprToInput(sheet) {
             const sel = sheet.getSelections()[0];
             const sel = sheet.getSelections()[0];
@@ -1358,6 +1372,7 @@ $(document).ready(() => {
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
             $(".sp-wrap").height(bcontent-30);
             $(".sp-wrap").height(bcontent-30);
             spSpread.refresh();
             spSpread.refresh();
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
         }
         }
     });
     });
 
 
@@ -1378,6 +1393,7 @@ $(document).ready(() => {
         // 加载中间计量
         // 加载中间计量
         stageIm.init(stage, imType);
         stageIm.init(stage, imType);
         stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.changeData);
         stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.changeData);
+        errorList.loadHisErrorData();
     }, null, true);
     }, null, true);
     spSpread.bind(spreadNS.Events.EditEnded, stagePosSpreadObj.editEnded);
     spSpread.bind(spreadNS.Events.EditEnded, stagePosSpreadObj.editEnded);
     spSpread.bind(spreadNS.Events.ClipboardPasting, stagePosSpreadObj.clipboardPasting);
     spSpread.bind(spreadNS.Events.ClipboardPasting, stagePosSpreadObj.clipboardPasting);
@@ -1678,6 +1694,36 @@ $(document).ready(() => {
                 detail.spread.refresh();
                 detail.spread.refresh();
             }
             }
             if (checkedChanges) checkedChanges.refresh();
             if (checkedChanges) checkedChanges.refresh();
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+        }
+    });
+
+    // 中间计量加载上下窗口resizer
+    $.divResizer({
+        select: '#zhongjian-spr',
+        callback: function () {
+            if (detail) {
+                detail.spread.refresh();
+            }
+            $('.zhongjian-msg').height($('#zhongjian .sjs-bottom').height());
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+        }
+    });
+
+    // 附件加载上下窗口resizer
+    $.divResizer({
+        select: '#file-spr',
+        callback: function () {
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+        }
+    });
+
+    // 变更令加载上下窗口resizer
+    $.divResizer({
+        select: '#change-spr',
+        callback: function () {
+            if (checkedChanges) checkedChanges.refresh();
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
         }
         }
     });
     });
 
 
@@ -2515,35 +2561,12 @@ $(document).ready(() => {
     $('a', '.right-nav').bind('click', function () {
     $('a', '.right-nav').bind('click', function () {
         //const main = $('#main-view'), tool = $('#tools-view');
         //const main = $('#main-view'), tool = $('#tools-view');
         const tab = $(this), tabPanel = $(tab.attr('content'));
         const tab = $(this), tabPanel = $(tab.attr('content'));
-        const showTools = function (show) {
-            const left = $('#main-view'), right = $('#tools-view'), parent = left.parent();
-            if (show) {
-                right.show();
-                autoFlashHeight();
-                /**
-                 * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
-                 * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
-                 * 故需要通过最终的parent.width再计算一次left.width
-                 *
-                 * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
-                 * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
-                 *
-                 */
-                    //left.css('width', parent.width() - right.outerWidth());
-                    //left.css('width', parent.width() - right.outerWidth());
-                const percent = 100 - right.outerWidth() /parent.width() * 100;
-                left.css('width', percent + '%');
-            } else {
-                right.hide();
-                left.css('width', '100%');
-            }
-        };
         if (!tab.hasClass('active')) {
         if (!tab.hasClass('active')) {
             $('a', '.side-menu').removeClass('active');
             $('a', '.side-menu').removeClass('active');
             $('.tab-content .tab-select-show').removeClass('active');
             $('.tab-content .tab-select-show').removeClass('active');
             tab.addClass('active');
             tab.addClass('active');
             tabPanel.addClass('active');
             tabPanel.addClass('active');
-            showTools(tab.hasClass('active'));
+            showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#search' && !searchLedger) {
             if (tab.attr('content') === '#search' && !searchLedger) {
                 searchLedger = $.billsSearch({
                 searchLedger = $.billsSearch({
                     selector: '#search',
                     selector: '#search',
@@ -2610,6 +2633,12 @@ $(document).ready(() => {
                 if (!detail) {
                 if (!detail) {
                     detail = new Detail($('#detail-spread'));
                     detail = new Detail($('#detail-spread'));
                     detail.spread.refresh();
                     detail.spread.refresh();
+                    $('#zhongjian .sjs-bottom').height('400px');
+                    $('.zhongjian-msg').height($('#zhongjian .sjs-bottom').height());
+                } else {
+                    detail.spread.refresh();
+                    $('#zhongjian .sjs-bottom').height('400px');
+                    $('.zhongjian-msg').height($('#zhongjian .sjs-bottom').height());
                 }
                 }
             }
             }
             if (tab.attr('content') === '#checked-change') {
             if (tab.attr('content') === '#checked-change') {
@@ -2620,12 +2649,18 @@ $(document).ready(() => {
                         reloadObj: $('#refresh-cc'),
                         reloadObj: $('#refresh-cc'),
                     });
                     });
                     checkedChanges.refresh();
                     checkedChanges.refresh();
+                } else {
+                    $('#ccb-spread').height('400px');
+                    checkedChanges.refresh();
                 }
                 }
             }
             }
+            if (tab.attr('content') === '#error-list') {
+                errorList.spread.refresh();
+            }
         } else {
         } else {
             tab.removeClass('active');
             tab.removeClass('active');
             tabPanel.removeClass('active');
             tabPanel.removeClass('active');
-            showTools(tab.hasClass('active'));
+            showSideTools(tab.hasClass('active'));
         }
         }
         slSpread.refresh();
         slSpread.refresh();
         spSpread.refresh();
         spSpread.refresh();
@@ -2871,4 +2906,46 @@ $(document).ready(() => {
             }
             }
         });
         });
     })('a[name=showLevel]', slSpread.getActiveSheet());
     })('a[name=showLevel]', slSpread.getActiveSheet());
+
+    const dataChecker = DataChecker({
+        checkUrl: window.location.pathname + '/check',
+        completeData: function (data) {
+            stagePos.updateDatas({pos: data.source.pos});
+            const refreshData = stageTree.loadPostStageData({bills: data.source.bills});
+            stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), refreshData);
+            stagePosSpreadObj.loadCurPosData();
+            for (const e of data.error) {
+                e.serialNo = stageTree.getNodeIndex(stageTree.getItems(e.ledger_id)) + 1;
+            }
+        },
+        errorList: errorList,
+    });
+    $('[name=stage-start]').submit(function (e) {
+        if (checkAuditorFrom()) {
+            $(this).parent().parent().parent().modal('hide');
+            dataChecker.checkAndPost(this.action, {});
+            $('#hide-all').hide();
+        }
+        return false;
+    });
+    $('#audit-check0').submit(function (e) {
+        $(this).parent().parent().modal('hide');
+        const data = {
+            opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType: parseInt($('[name=checkType]', this).val()),
+        };
+        dataChecker.checkAndPost(this.action, data);
+        $('#hide-all').hide();
+        return false;
+    });
+    $('#audit-check2').submit(function (e) {
+        $(this).parent().parent().modal('hide');
+        const data = {
+            opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType: parseInt($('[name=checkType]', this).val()),
+        };
+        dataChecker.checkAndPost(this.action, data);
+        $('#hide-all').hide();
+        return false;
+    });
 });
 });

+ 1 - 0
app/public/js/stage_audit.js

@@ -160,6 +160,7 @@ function checkAuditorFrom () {
         return false;
         return false;
     }
     }
     $('#hide-all').show();
     $('#hide-all').show();
+    return true;
 }
 }
 // texterea换行
 // texterea换行
 function auditCheck(i) {
 function auditCheck(i) {

+ 2 - 1
app/public/js/tender_list.js

@@ -343,7 +343,8 @@ function bindTenderUrl() {
         });
         });
         if (!tender) return;
         if (!tender) return;
         if (tender.measure_type) {
         if (tender.measure_type) {
-            window.location.href = '/tender/' + tenderId;
+            // window.location.href = '/tender/' + tenderId;
+            window.open('/tender/' + tenderId, '_blank');
         } else {
         } else {
             for (const a of $('a', '#jlms')) {
             for (const a of $('a', '#jlms')) {
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');

+ 2 - 1
app/public/js/tender_list_info.js

@@ -399,7 +399,8 @@ function bindTenderUrl() {
             return t.id === tenderId;
             return t.id === tenderId;
         });
         });
         if (tender.measure_type) {
         if (tender.measure_type) {
-            window.location.href = '/tender/' + tenderId;
+            // window.location.href = '/tender/' + tenderId;
+            window.open('/tender/' + tenderId, '_blank');
         } else {
         } else {
             for (const a of $('a', '#jlms')) {
             for (const a of $('a', '#jlms')) {
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');

+ 2 - 1
app/public/js/tender_list_manage.js

@@ -334,7 +334,8 @@ function bindTenderUrl() {
             return t.id === tenderId;
             return t.id === tenderId;
         });
         });
         if (tender.measure_type) {
         if (tender.measure_type) {
-            window.location.href = '/tender/' + tenderId;
+            // window.location.href = '/tender/' + tenderId;
+            window.open('/tender/' + tenderId, '_blank');
         } else {
         } else {
             for (const a of $('a', '#jlms')) {
             for (const a of $('a', '#jlms')) {
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');

+ 2 - 1
app/public/js/tender_list_progress.js

@@ -374,7 +374,8 @@ function bindTenderUrl() {
             return t.id === tenderId;
             return t.id === tenderId;
         });
         });
         if (tender.measure_type) {
         if (tender.measure_type) {
-            window.location.href = '/tender/' + tenderId;
+            // window.location.href = '/tender/' + tenderId;
+            window.open('/tender/' + tenderId, '_blank');
         } else {
         } else {
             for (const a of $('a', '#jlms')) {
             for (const a of $('a', '#jlms')) {
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');
                 a.href = '/tender/' + tenderId + '/type?type=' + $(a).attr('mst');

+ 152 - 0
app/public/js/wap/global.js

@@ -1,3 +1,55 @@
+$(function () {
+    $('a').on('click', function () {
+        if ($(this).hasClass('show-loading')) {
+            showWaitingView();
+        }
+    });
+    $('[data-toggle="tooltip"]').tooltip();
+    $('[data-toggle="popover"]').popover();
+})
+/**
+ * 动态请求数据
+ * @param {String} url - 请求链接
+ * @param data - 提交数据
+ * @param {function} successCallback - 返回成功回调
+ * @param {function} errorCallBack - 返回失败回调
+ */
+const postData = function (url, data, successCallback, errorCallBack, showWaiting = true) {
+    if (showWaiting) showWaitingView();
+    $.ajax({
+        type:"POST",
+        url: url,
+        data: {'data': JSON.stringify(data)},
+        dataType: 'json',
+        cache: false,
+        timeout: 60000,
+        beforeSend: function(xhr) {
+            let csrfToken = Cookies.get('csrfToken');
+            xhr.setRequestHeader('x-csrf-token', csrfToken);
+        },
+        success: function(result){
+            if (result.err === 0) {
+                if (successCallback) {
+                    successCallback(result.data);
+                }
+            } else {
+                toastr.error('error: ' + result.msg);
+                if (errorCallBack) {
+                    errorCallBack(result.msg);
+                }
+            }
+            if (showWaiting) closeWaitingView();
+        },
+        error: function(jqXHR, textStatus, errorThrown){
+            toastr.error('error: ' + textStatus + " " + errorThrown);
+            if (errorCallBack) {
+                errorCallBack();
+            }
+            if (showWaiting) closeWaitingView();
+        }
+    });
+};
+
 /**
 /**
  * 提示框
  * 提示框
  *
  *
@@ -95,3 +147,103 @@ function trimInvalidChar(str) {
 function cleanSymbols(str) {
 function cleanSymbols(str) {
     return $.trim(str).replace(/\\/g, '').replace(/\'/g, '').replace(/\"/g, '').replace(/\</g, '').replace(/\|/g, '');
     return $.trim(str).replace(/\\/g, '').replace(/\'/g, '').replace(/\"/g, '').replace(/\</g, '').replace(/\|/g, '');
 }
 }
+
+//关闭等待窗口
+function closeWaitingView() {
+    bShowWaiting = false;
+    const time = parseInt(new Date());
+    setTimeout(function () {
+        var bgDiv = document.getElementById("bgDiv");
+        var msgDiv = document.getElementById("msgDiv");
+        //移除背景遮罩层div
+        if(bgDiv != null){
+            document.body.removeChild(bgDiv);
+        }
+        //移除中间信息提示层div
+        if(msgDiv != null){
+            document.body.removeChild(msgDiv);
+        }
+    }, Math.max(beginWaitingTime - time + 500, 0));
+}
+//显示等待窗口
+function showWaitingView() {
+    // bShowWaiting = true;
+    // setTimeout(function () {
+    //     if (!bShowWaiting) return;
+    //     beginWaitingTime = parseInt(new Date());
+    //     var msgw = 300; //提示窗口的宽度
+    //     var msgh = 100; //提示窗口的高度
+    //
+    //     var sWidth, sHeight;
+    //     sWidth = document.body.clientWidth;
+    //     sHeight = document.body.clientHeight;
+    //
+    //     //背景遮罩层div
+    //     var bgObj = document.createElement("div");
+    //     bgObj.setAttribute('id', 'bgDiv');
+    //     bgObj.style.zIndex = '9998';
+    //     bgObj.style.position = "absolute";
+    //     bgObj.style.top = "0px";
+    //     bgObj.style.background = "#888";
+    //     bgObj.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=3,opacity=25,finishOpacity=75";
+    //     bgObj.style.opacity = "0.6";
+    //     bgObj.style.left = "0px";
+    //     bgObj.style.width = sWidth + "px";
+    //     bgObj.style.height = sHeight + "px";
+    //     document.body.appendChild(bgObj);
+    //
+    //     //信息提示层div
+    //     var msgObj = document.createElement("div");
+    //     msgObj.style.zIndex = '9999';
+    //     msgObj.setAttribute("id", "msgDiv");
+    //     msgObj.setAttribute("align", "center");
+    //     msgObj.style.position = "absolute";
+    //     msgObj.style.font = "12px/1.6em Verdana, Geneva, Arial, Helvetica, sans-serif";
+    //     msgObj.style.width = msgw + "px";
+    //     msgObj.style.height = msgh + "px";
+    //     msgObj.style.top = (document.documentElement.scrollTop + (sHeight - msgh) / 2) + "px";
+    //     msgObj.style.left = (sWidth - msgw) / 2 + "px";
+    //     document.body.appendChild(msgObj);
+    //
+    //     //中间等待图标
+    //     document.getElementById("msgDiv").innerHTML = '<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>';
+    // }, 1000);
+    beginWaitingTime = parseInt(new Date());
+    var msgw = 300; //提示窗口的宽度
+    var msgh = 100; //提示窗口的高度
+
+    var sWidth, sHeight;
+    sWidth = document.body.clientWidth;
+    sHeight = document.body.clientHeight;
+
+    //背景遮罩层div
+    var bgObj = document.createElement("div");
+    bgObj.setAttribute('id', 'bgDiv');
+    bgObj.style.zIndex = '9998';
+    bgObj.style.position = "absolute";
+    bgObj.style.top = "0px";
+    // bgObj.style.background = "#888";
+    bgObj.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=3,opacity=25,finishOpacity=75";
+    bgObj.style.opacity = "0.6";
+    bgObj.style.left = "0px";
+    bgObj.style.width = sWidth + "px";
+    bgObj.style.height = sHeight + "px";
+    document.body.appendChild(bgObj);
+
+    //信息提示层div
+    var msgObj = document.createElement("div");
+    msgObj.style.zIndex = '9999';
+    msgObj.setAttribute("id", "msgDiv");
+    msgObj.setAttribute("align", "center");
+    msgObj.style.position = "fixed";
+    msgObj.style.font = "12px/1.6em Verdana, Geneva, Arial, Helvetica, sans-serif";
+    msgObj.style.width = msgw + "px";
+    msgObj.style.height = msgh + "px";
+    // msgObj.style.top = (document.documentElement.scrollTop + (sHeight - msgh) / 2) + "px";
+    msgObj.style.top = "50%";
+    msgObj.style.left = (sWidth - msgw) / 2 + "px";
+    document.body.appendChild(msgObj);
+
+    //中间等待图标
+    document.getElementById("msgDiv").innerHTML = '<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>';
+}

+ 3 - 0
app/router.js

@@ -109,6 +109,7 @@ module.exports = app => {
     app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, 'ledgerController.posUpdate');
     app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, 'ledgerController.posUpdate');
     app.post('/tender/:id/pos/paste', sessionAuth, tenderCheck, 'ledgerController.posPaste');
     app.post('/tender/:id/pos/paste', sessionAuth, tenderCheck, 'ledgerController.posPaste');
     app.post('/tender/:id/ledger/deal2sgfh', sessionAuth, tenderCheck, 'ledgerController.deal2sgfh');
     app.post('/tender/:id/ledger/deal2sgfh', sessionAuth, tenderCheck, 'ledgerController.deal2sgfh');
+    app.post('/tender/:id/ledger/check', sessionAuth, tenderCheck, 'ledgerController.check');
     // 台账审批相关
     // 台账审批相关
     app.get('/tender/:id/ledger/audit', sessionAuth, tenderCheck, 'ledgerAuditController.index');
     app.get('/tender/:id/ledger/audit', sessionAuth, tenderCheck, 'ledgerAuditController.index');
     app.post('/tender/:id/ledger/audit/add', sessionAuth, tenderCheck, 'ledgerAuditController.add');
     app.post('/tender/:id/ledger/audit/add', sessionAuth, tenderCheck, 'ledgerAuditController.add');
@@ -136,6 +137,7 @@ module.exports = app => {
     app.post('/tender/:id/revise/info/load', sessionAuth, tenderCheck, 'reviseController.loadInfoData');
     app.post('/tender/:id/revise/info/load', sessionAuth, tenderCheck, 'reviseController.loadInfoData');
     app.post('/tender/:id/revise/info/update', sessionAuth, tenderCheck, 'reviseController.update');
     app.post('/tender/:id/revise/info/update', sessionAuth, tenderCheck, 'reviseController.update');
     app.post('/tender/:id/revise/info/upload-excel/:ueType', sessionAuth, tenderCheck, 'reviseController.uploadExcel');
     app.post('/tender/:id/revise/info/upload-excel/:ueType', sessionAuth, tenderCheck, 'reviseController.uploadExcel');
+    app.post('/tender/:id/revise/info/check', sessionAuth, tenderCheck, 'reviseController.checkData');
     // 查看修订数据
     // 查看修订数据
     app.get('/tender/:id/revise/history', sessionAuth, tenderCheck, 'reviseController.history');
     app.get('/tender/:id/revise/history', sessionAuth, tenderCheck, 'reviseController.history');
     app.post('/tender/:id/revise/history/load', sessionAuth, tenderCheck, 'reviseController.loadHistoryData');
     app.post('/tender/:id/revise/history/load', sessionAuth, tenderCheck, 'reviseController.loadHistoryData');
@@ -172,6 +174,7 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/update', sessionAuth, tenderCheck, stageCheck, 'stageController.updateStageData');
     app.post('/tender/:id/measure/stage/:order/update', sessionAuth, tenderCheck, stageCheck, 'stageController.updateStageData');
     app.post('/tender/:id/measure/stage/:order/valid-change', sessionAuth, tenderCheck, stageCheck, 'stageController.searchValidChange');
     app.post('/tender/:id/measure/stage/:order/valid-change', sessionAuth, tenderCheck, stageCheck, 'stageController.searchValidChange');
     app.post('/tender/:id/measure/stage/:order/use-change', sessionAuth, tenderCheck, stageCheck, 'stageController.useChange');
     app.post('/tender/:id/measure/stage/:order/use-change', sessionAuth, tenderCheck, stageCheck, 'stageController.useChange');
+    app.post('/tender/:id/measure/stage/:order/check', sessionAuth, tenderCheck, stageCheck, 'stageController.check');
     // 计量附件
     // 计量附件
     app.post('/tender/:id/measure/stage/:order/upload/file', sessionAuth, tenderCheck, stageCheck, 'stageController.uploadFile');
     app.post('/tender/:id/measure/stage/:order/upload/file', sessionAuth, tenderCheck, stageCheck, 'stageController.uploadFile');
     app.get('/tender/:id/measure/stage/:order/download/file/:fid', sessionAuth, 'stageController.downloadFile');
     app.get('/tender/:id/measure/stage/:order/download/file/:fid', sessionAuth, 'stageController.downloadFile');

+ 2 - 2
app/service/ledger_audit.js

@@ -50,11 +50,11 @@ module.exports = app => {
          * @param {Number} times - 第几次审批
          * @param {Number} times - 第几次审批
          * @returns {Promise<*>}
          * @returns {Promise<*>}
          */
          */
-        async getStatusName(tenderId) {
+        async getStatusName(tenderId, times) {
             const sql = 'SELECT pa.`name` ' +
             const sql = 'SELECT pa.`name` ' +
                 'FROM ?? AS la, ?? AS pa ' +
                 'FROM ?? AS la, ?? AS pa ' +
                 'WHERE la.`tender_id` = ?' +
                 'WHERE la.`tender_id` = ?' +
-                '    and la.`audit_id` = pa.`id` and la.`status` != ? ORDER BY la.`id` DESC';
+                '    and la.`audit_id` = pa.`id` and la.`status` != ? ORDER BY la.`times` DESC, la.`audit_order` DESC';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, tenderId, auditConst.status.uncheck];
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, tenderId, auditConst.status.uncheck];
             return await this.db.queryOne(sql, sqlParam);
             return await this.db.queryOne(sql, sqlParam);
         }
         }

+ 15 - 7
app/service/project_account.js

@@ -510,7 +510,7 @@ module.exports = app => {
          * @param {String} password - 重置的密码
          * @param {String} password - 重置的密码
          * @return {Boolean} - 重置结果
          * @return {Boolean} - 重置结果
          */
          */
-        async resetPassword(accountId, password) {
+        async resetPassword(accountId, password, account = '') {
             // 初始化事务
             // 初始化事务
             this.transaction = await this.db.beginTransaction();
             this.transaction = await this.db.beginTransaction();
             let result = false;
             let result = false;
@@ -521,13 +521,21 @@ module.exports = app => {
                     throw '不存在对应账号';
                     throw '不存在对应账号';
                 }
                 }
                 // 加密密码
                 // 加密密码
-                const encryptPassword = crypto.createHmac('sha1', accountData.account).update(password)
+                const encryptPassword = account ? crypto.createHmac('sha1', account).update(password)
+                    .digest().toString('base64') : crypto.createHmac('sha1', accountData.account).update(password)
                     .digest().toString('base64');
                     .digest().toString('base64');
                 // 更新账号密码
                 // 更新账号密码
-                const sql = 'UPDATE ?? SET password=? WHERE id=? AND password != ?;';
-                const sqlParam = [this.tableName, encryptPassword, accountId, 'SSO password'];
-                const operate = await this.transaction.query(sql, sqlParam);
-                result = operate.affectedRows > 0;
+                if (account) {
+                    const sql = 'UPDATE ?? SET account=?,password=? WHERE id=? AND password != ?;';
+                    const sqlParam = [this.tableName, account, encryptPassword, accountId, 'SSO password'];
+                    const operate = await this.transaction.query(sql, sqlParam);
+                    result = operate.affectedRows > 0;
+                } else {
+                    const sql = 'UPDATE ?? SET password=? WHERE id=? AND password != ?;';
+                    const sqlParam = [this.tableName, encryptPassword, accountId, 'SSO password'];
+                    const operate = await this.transaction.query(sql, sqlParam);
+                    result = operate.affectedRows > 0;
+                }
 
 
                 if (!result) {
                 if (!result) {
                     throw '更新密码失败';
                     throw '更新密码失败';
@@ -536,7 +544,7 @@ module.exports = app => {
                 // 发送短信
                 // 发送短信
                 if (accountData.auth_mobile !== '') {
                 if (accountData.auth_mobile !== '') {
                     const sms = new SMS(this.ctx);
                     const sms = new SMS(this.ctx);
-                    const content = '【纵横计量支付】账号:' + accountData.account + ',密码重置为:' + password;
+                    const content = '【纵横计量支付】账号:' + (account ? account : accountData.account) + ',密码重置为:' + password;
                     sms.send(accountData.auth_mobile, content);
                     sms.send(accountData.auth_mobile, content);
                 }
                 }
 
 

+ 20 - 1
app/service/report_memory.js

@@ -34,8 +34,9 @@ const billsFields = (function () {
     const stage = cur.concat(pre, end, final);
     const stage = cur.concat(pre, end, final);
     const stageEnd = pre.concat(end, final);
     const stageEnd = pre.concat(end, final);
     const bgl = ['qc_bgl_code'];
     const bgl = ['qc_bgl_code'];
+    const leafXmj = ['leaf_xmj_id'];
 
 
-    return {cur, pre, end, final, stage, stageEnd, bgl};
+    return {cur, pre, end, final, stage, stageEnd, bgl, leafXmj};
 })();
 })();
 const posFields = (function () {
 const posFields = (function () {
     const cur = ['contract_qty', 'qc_qty', 'gather_qty', 'postil'];
     const cur = ['contract_qty', 'qc_qty', 'gather_qty', 'postil'];
@@ -333,6 +334,15 @@ module.exports = app => {
             }
             }
         }
         }
 
 
+        _calcLeafXmjRela() {
+            for (const node of this.billsTree.nodes) {
+                if (node.b_code) {
+                    const leafXmj = this.billsTree.getLeafXmjParent(node);
+                    node.leaf_xmj_id = leafXmj.id;
+                }
+            }
+        }
+
         async getStageBillsData(tid, sid, fields) {
         async getStageBillsData(tid, sid, fields) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.tender.checkTender(tid);
             if (sid) {
             if (sid) {
@@ -367,6 +377,10 @@ module.exports = app => {
                 await this._calcBillsBgl();
                 await this._calcBillsBgl();
             }
             }
 
 
+            if (this._checkFieldsExist(fields, billsFields.leafXmj)) {
+                this._calcLeafXmjRela();
+            }
+
             return this.billsTree.getDatas([
             return this.billsTree.getDatas([
                 'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
                 'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
                 'code', 'b_code', 'name', 'unit', 'unit_price',
                 'code', 'b_code', 'name', 'unit', 'unit_price',
@@ -380,6 +394,7 @@ module.exports = app => {
                 'final_tp', 'final_ratio',
                 'final_tp', 'final_ratio',
                 'qc_bgl_code',
                 'qc_bgl_code',
                 'chapter',
                 'chapter',
+                'leaf_xmj_id',
             ]);
             ]);
         }
         }
 
 
@@ -530,6 +545,10 @@ module.exports = app => {
                 }
                 }
             });
             });
 
 
+            if (this._checkFieldsExist(fields, billsFields.leafXmj)) {
+                this._calcLeafXmjRela();
+            }
+
             return this.billsTree.getDefaultDatas();
             return this.billsTree.getDefaultDatas();
             // return this.billsTree.getDatas([
             // return this.billsTree.getDatas([
             //     'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',                 //8
             //     'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',                 //8

+ 7 - 0
app/service/rpt_gather_memory.js

@@ -445,6 +445,13 @@ module.exports = app => {
                 info.tp = sum.total_price;
                 info.tp = sum.total_price;
                 info.deal_tp = sum.deal_tp;
                 info.deal_tp = sum.deal_tp;
             }
             }
+            info.deal_info = tender.info.deal_info;
+            info.construction_unit = tender.info.construction_unit;
+            info.tech_param = tender.info.tech_param;
+            info.deal_param = tender.info.deal_param;
+            info.pay_account = tender.info.pay_account;
+            info.deal_param.contractPriceWithoutZL = this.ctx.helper.sub(info.deal_param.contractPrice,
+                info.deal_param.zanLiePrice);
             return info;
             return info;
         }
         }
         async _getStageTenderInfo(stage, info) {
         async _getStageTenderInfo(stage, info) {

+ 1 - 1
app/service/stage_audit.js

@@ -85,7 +85,7 @@ module.exports = app => {
             const sql = 'SELECT pa.`name` ' +
             const sql = 'SELECT pa.`name` ' +
                 'FROM ?? AS sa, ?? AS pa ' +
                 'FROM ?? AS sa, ?? AS pa ' +
                 'WHERE sa.`sid` = ?' +
                 'WHERE sa.`sid` = ?' +
-                '    and sa.`aid` = pa.`id` and sa.`status` != ? ORDER BY sa.`id` DESC';
+                '    and sa.`aid` = pa.`id` and sa.`status` != ? ORDER BY sa.`times` DESC, sa.`order` DESC';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, auditConst.status.uncheck];
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, auditConst.status.uncheck];
             return await this.db.queryOne(sql, sqlParam);
             return await this.db.queryOne(sql, sqlParam);
         }
         }

+ 2 - 2
app/service/stage_jgcl.js

@@ -31,7 +31,7 @@ module.exports = app => {
                         stimes: this.ctx.stage.curTimes, sorder: this.ctx.stage.curOrder
                         stimes: this.ctx.stage.curTimes, sorder: this.ctx.stage.curOrder
                     });
                     });
                     if (h) {
                     if (h) {
-                        d.arrive_qty = h.arrive_qty;
+                        d.arrive_qty = h.arrive_qty ? h.arrive_qty : h.arraive_qty;
                         d.arrive_tp = h.arrive_tp;
                         d.arrive_tp = h.arrive_tp;
                         d.deduct_qty = h.deduct_qty;
                         d.deduct_qty = h.deduct_qty;
                         d.deduct_tp = h.deduct_tp;
                         d.deduct_tp = h.deduct_tp;
@@ -198,7 +198,7 @@ module.exports = app => {
                 } else {
                 } else {
                     history.push({
                     history.push({
                         stimes: this.ctx.stage.curTimes, sorder: this.ctx.stage.curOrder,
                         stimes: this.ctx.stage.curTimes, sorder: this.ctx.stage.curOrder,
-                        arraive_qty: d.arrive_qty, arrive_tp: d.arrive_tp,
+                        arrive_qty: d.arrive_qty, arrive_tp: d.arrive_tp,
                         deduct_qty: d.deduct_qty, deduct_tp: d.deduct_tp
                         deduct_qty: d.deduct_qty, deduct_tp: d.deduct_tp
                     });
                     });
                 }
                 }

+ 4 - 2
app/service/stage_pay.js

@@ -270,8 +270,10 @@ module.exports = app => {
             if (!stage || !transaction || !times || order === undefined) {
             if (!stage || !transaction || !times || order === undefined) {
                 throw '数据错误';
                 throw '数据错误';
             }
             }
-            const sql = 'INSERT INTO ?? (`tid`, `sid`, `pid`, `stimes`, `sorder`, `name`, `tp`, `expr`, `pause`, `attachment`, `pre_tp`, `end_tp`, `pre_finish`, `start_stage_order`) ' +
-                        '  SELECT SP.`tid`, SP.`sid`, SP.`pid`, ?, ?, SP.name, SP.`tp`, SP.`expr`, SP.`pause`, SP.`attachment`, SP.`pre_tp`, SP.`end_tp`, SP.`pre_finish`, SP.`start_stage_order` ' +
+            const sql = 'INSERT INTO ?? (`tid`, `sid`, `pid`, `stimes`, `sorder`, `name`, `tp`, `expr`, `pause`, `attachment`,' +
+                        '    `pre_tp`, `end_tp`, `pre_used`, `pre_finish`, `start_stage_order`) ' +
+                        '  SELECT SP.`tid`, SP.`sid`, SP.`pid`, ?, ?, SP.name, SP.`tp`, SP.`expr`, SP.`pause`, SP.`attachment`,' +
+                        '     SP.`pre_tp`, SP.`end_tp`, SP.`pre_used`, SP.`pre_finish`, SP.`start_stage_order` ' +
                         '  FROM ?? As SP, ?? As P ' +
                         '  FROM ?? As SP, ?? As P ' +
                         '  WHERE SP.`sid` = ? AND SP.`stimes` = ? AND SP.`sorder` = ? And SP.`pid` = P.`id` And P.`valid`';
                         '  WHERE SP.`sid` = ? AND SP.`stimes` = ? AND SP.`sorder` = ? And SP.`pid` = P.`id` And P.`valid`';
             const sqlParam = [this.tableName, times, order, this.tableName, this.ctx.service.pay.tableName,
             const sqlParam = [this.tableName, times, order, this.tableName, this.ctx.service.pay.tableName,

+ 5 - 5
app/view/measure/stage.ejs

@@ -36,7 +36,7 @@
                     <% for (const s of stages) { %>
                     <% for (const s of stages) { %>
                     <tr>
                     <tr>
                         <td>
                         <td>
-                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>">第 <%- s.order %> 期</a>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank">第 <%- s.order %> 期</a>
                             <% if (s.status !== auditConst.status.checked && s.user_id === ctx.session.sessionUser.accountId) { %>
                             <% if (s.status !== auditConst.status.checked && s.user_id === ctx.session.sessionUser.accountId) { %>
                             <a href="#edit" data-toggle="modal" data-target="#edit"><i class="fa fa-pencil-square-o "></i></a>
                             <a href="#edit" data-toggle="modal" data-target="#edit"><i class="fa fa-pencil-square-o "></i></a>
                             <% } %>
                             <% } %>
@@ -56,13 +56,13 @@
                         </td>
                         </td>
                         <td class="text-center">
                         <td class="text-center">
                             <% if (s.status === auditConst.status.uncheck && s.user_id === ctx.session.sessionUser.accountId) { %>
                             <% if (s.status === auditConst.status.uncheck && s.user_id === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
                             <% } else if (s.status === auditConst.status.checkNo && s.curAuditor && s.user_id === ctx.session.sessionUser.accountId) { %>
                             <% } else if (s.status === auditConst.status.checkNo && s.curAuditor && s.user_id === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
                             <% } else if (s.status === auditConst.status.checking && s.curAuditor && s.curAuditor.aid === ctx.session.sessionUser.accountId) { %>
                             <% } else if (s.status === auditConst.status.checking && s.curAuditor && s.curAuditor.aid === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
                             <% } else if (s.status === auditConst.status.checkNoPre && s.curAuditor && s.curAuditor2.aid === ctx.session.sessionUser.accountId) { %>
                             <% } else if (s.status === auditConst.status.checkNoPre && s.curAuditor && s.curAuditor2.aid === ctx.session.sessionUser.accountId) { %>
-                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
+                            <a href="<%- '/tender/' + ctx.tender.id + '/measure/stage/' + s.order %>" target="_blank" class="btn <%- auditConst.statusButtonClass[s.status] %> btn-sm"><%- auditConst.statusButton[s.status] %></a>
                             <% } else { %>
                             <% } else { %>
                             <span class="<%- auditConst.auditStringClass[s.status] %>"><%- auditConst.auditString[s.status] %></span>
                             <span class="<%- auditConst.auditStringClass[s.status] %>"><%- auditConst.auditString[s.status] %></span>
                             <% } %>
                             <% } %>

+ 5 - 0
app/view/revise/info.ejs

@@ -170,6 +170,8 @@
                         <div id="bg-bills-spread" class="sjs-sh">
                         <div id="bg-bills-spread" class="sjs-sh">
                         </div>
                         </div>
                     </div>
                     </div>
+                    <div id="error-list" class="tab-pane">
+                    </div>
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
@@ -195,6 +197,9 @@
                 <li class="nav-item">
                 <li class="nav-item">
                     <a class="nav-link" content="#bg-bills" href="javascript: void(0);">变更清单</a>
                     <a class="nav-link" content="#bg-bills" href="javascript: void(0);">变更清单</a>
                 </li>
                 </li>
+                <li class="nav-item">
+                    <a class="nav-link" content="#error-list" id="error-list-tab" href="javascript: void(0);" style="display: none;">错误列表</a>
+                </li>
             </ul>
             </ul>
         </div>
         </div>
     </div>
     </div>

+ 4 - 2
app/view/revise/info_modal.ejs

@@ -80,7 +80,7 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <form class="modal-footer" method="post" action="/tender/<%- ctx.tender.id %>/revise/audit/start" onsubmit="return checkAuditorFrom()">
+            <form class="modal-footer" method="post" action="/tender/<%- ctx.tender.id %>/revise/audit/start" name="revise-start">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
                 <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
@@ -191,7 +191,7 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <form class="modal-footer" action="/tender/<%- ctx.tender.id %>/revise/audit/start" method="post" onsubmit="return checkAuditorFrom()">
+            <form class="modal-footer" action="/tender/<%- ctx.tender.id %>/revise/audit/start" method="post" name="revise-start">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <button type="submit" class="btn btn-primary btn-sm">确认上报</button>
                 <button type="submit" class="btn btn-primary btn-sm">确认上报</button>
@@ -569,6 +569,7 @@
 <% include ../shares/merge_peg_modal.ejs %>
 <% include ../shares/merge_peg_modal.ejs %>
 <% include ../shares/import_excel_modal.ejs %>
 <% include ../shares/import_excel_modal.ejs %>
 <% include ../shares/delete_hint_modal.ejs %>
 <% include ../shares/delete_hint_modal.ejs %>
+<% include ../shares/check_data_modal.ejs %>
 <script>
 <script>
     <% if (ctx.session.sessionUser.accountId === revise.uid && (revise.status === audit.status.uncheck || revise.status === audit.status.checkNo)) { %>
     <% if (ctx.session.sessionUser.accountId === revise.uid && (revise.status === audit.status.uncheck || revise.status === audit.status.checkNo)) { %>
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
@@ -689,6 +690,7 @@
             return false;
             return false;
         }
         }
         $('#hide-all').show();
         $('#hide-all').show();
+        return true;
     }
     }
 
 
     // texterea换行
     // texterea换行

+ 54 - 14
app/view/setting/user_modal.ejs

@@ -82,37 +82,37 @@
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
                     <label>登录账号<b class="text-danger">*</b></label>
                     <label>登录账号<b class="text-danger">*</b></label>
-                    <input class="form-control form-control-sm" value="" name="account" placeholder="支持英文数字组合" type="text">
+                    <input class="form-control form-control-sm" value="" name="account" readonly placeholder="支持英文数字组合" type="text">
                     <input value="" class="account-check" type="hidden">
                     <input value="" class="account-check" type="hidden">
                     <div class="invalid-feedback">
                     <div class="invalid-feedback">
                         该账号已存在。
                         该账号已存在。
                     </div>
                     </div>
                 </div>
                 </div>
-                <div class="form-group">
-                    <label>登录密码</label>
-                    <div class="input-group">
-                        <input type="text" id="reset-password" class="form-control" placeholder="密码支持英文数字及符号">
-                        <div class="input-group-append">
-                            <button id="reset-password-btn" class="btn btn-outline-secondary btn-sm" type="button">修改密码</button>
-                        </div>
-                    </div>
-                    <span class="form-text text-success">如果账号已有认证手机,密码也将发送至该手机。</span>
-                </div>
+                <!--<div class="form-group">-->
+                    <!--<label>登录密码</label>-->
+                    <!--<div class="input-group">-->
+                        <!--<input type="text" id="reset-password" class="form-control form-control-sm" placeholder="密码支持英文数字及符号">-->
+                        <!--<div class="input-group-append">-->
+                            <!--<button id="reset-password-btn" class="btn btn-outline-secondary btn-sm" type="button">修改密码</button>-->
+                        <!--</div>-->
+                    <!--</div>-->
+                    <!--<span class="form-text text-success">如果账号已有认证手机,密码也将发送至该手机。</span>-->
+                <!--</div>-->
                 <div class="form-group">
                 <div class="form-group">
                     <label>姓名<b class="text-danger">*</b></label>
                     <label>姓名<b class="text-danger">*</b></label>
                     <input class="form-control form-control-sm" value="" name="name" type="text">
                     <input class="form-control form-control-sm" value="" name="name" type="text">
                     <small class="form-text text-muted">修改姓名,将影响所有该账号参与数据</small>
                     <small class="form-text text-muted">修改姓名,将影响所有该账号参与数据</small>
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
-                    <label>认证手机</label>
-                    <input class="form-control" data-mobile="auth-mobile" value="" type="text" readonly>
+                    <label>认证手机(短信通知)</label>
+                    <input class="form-control form-control-sm" data-mobile="auth-mobile" value="" type="text" readonly>
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
                     <label>单位名称<b class="text-danger">*</b></label>
                     <label>单位名称<b class="text-danger">*</b></label>
                     <input class="form-control form-control-sm" value="" name="company" type="text">
                     <input class="form-control form-control-sm" value="" name="company" type="text">
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
-                    <label>角色/职位<b class="text-danger">*</b></label>
+                    <label>职位名称<b class="text-danger">*</b></label>
                     <input class="form-control form-control-sm" value="" name="role" type="text">
                     <input class="form-control form-control-sm" value="" name="role" type="text">
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
@@ -128,6 +128,7 @@
             <div class="modal-footer">
             <div class="modal-footer">
                 <input type="hidden" name="id" id="user-id" value="">
                 <input type="hidden" name="id" id="user-id" value="">
                 <!--<button type="button" class="btn btn-outline-danger btn-sm" data-dismiss="modal">删除账号</button>-->
                 <!--<button type="button" class="btn btn-outline-danger btn-sm" data-dismiss="modal">删除账号</button>-->
+                <button type="button" class="btn btn-sm btn-outline-primary" data-toggle="modal" data-target="#edit-password"  data-dismiss="modal">修改账号/密码</button>
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <button type="submit" class="btn btn-primary btn-sm">提交修改</button>
                 <button type="submit" class="btn btn-primary btn-sm">提交修改</button>
             </div>
             </div>
@@ -174,3 +175,42 @@
         </div>
         </div>
     </div>
     </div>
 </div>
 </div>
+<!--弹出修改帐号名-->
+<div class="modal" tabindex="-1" role="dialog" id="edit-password">
+    <div class="modal-dialog" role="document">
+        <form method="post" action="/setting/user/reset/password" class="modal-content" onsubmit="return checkPasswordForm();">
+            <div class="modal-header">
+                <h5 class="modal-title">修改账号/密码</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>登录账号<b class="text-danger">*</b></label>
+                    <input class="form-control form-control-sm" placeholder="支持英文数字组合" type="text" name="account" value="">
+                    <input value="" class="account-check" type="hidden">
+                    <div class="invalid-feedback">
+                        该账号已存在。
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>登录密码<b class="text-danger">*</b></label>
+                    <div class="input-group input-group-sm">
+                        <input type="text" name="reset_password" class="form-control" placeholder="密码支持英文数字及符号">
+                        <div class="input-group-append">
+                            <button id="rand-password2" class="btn btn-outline-secondary" type="button">随机生成</button>
+                        </div>
+                    </div>
+                </div>
+                <div class="alert alert-warning py-1 px-2">若修改登录账号,必须重新设置新密码。新密码会发送至已认证手机。</div>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
+                <input type="hidden" name="id" value="">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-sm btn-primary">提交修改</button>
+            </div>
+        </form>
+    </div>
+</div>

+ 57 - 29
app/view/shares/check_data_modal.ejs

@@ -8,7 +8,7 @@
             <div class="modal-body">
             <div class="modal-body">
                 <h5>数据计算中,完成后会自动进入审批流程设置。</h5>
                 <h5>数据计算中,完成后会自动进入审批流程设置。</h5>
                 <div class="progress">
                 <div class="progress">
-                    <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
+                    <div class="progress-bar" id="check-progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
@@ -37,49 +37,77 @@
      *
      *
      * @param setting
      * @param setting
      * {
      * {
-     *      loadUrl,
-     *      loadData,
-     *      checkFun,
+     *      checkUrl,
+     *      checkData,
+     *      reloadDifferSource,
      *      errorList
      *      errorList
      * }
      * }
      */
      */
     const DataChecker = function (setting) {
     const DataChecker = function (setting) {
+        let progressInterval;
         $('#show-error-list').click(function () {
         $('#show-error-list').click(function () {
+            <% if (!ctx.stage || ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order) { %>
             $('#check').modal('hide');
             $('#check').modal('hide');
             setting.errorList.show();
             setting.errorList.show();
+            <% } else { %>
+            setting.errorList.autoShowHistory(true);
+            window.location.pathname = '/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>';
+            <% } %>
         });
         });
-        const loadCheckData = function () {
-            const promise = new Promise(function (resolve, reject) {
-                postData(setting.loadUrl, setting.loadData, function (result) {
-                    resolve(result);
-                });
-            });
-            return promise;
-        }
         const progress = function (percent) {
         const progress = function (percent) {
-            $('.progress-bar').attr('aria-valuenow', percent).width(percent + '%').html(percent + '%');
+            $('#check-progress').attr('aria-valuenow', percent).width(percent + '%').html(percent + '%');
         }
         }
-        const addProgress = function (percent) {
-            const oldPercent = parseInt($('.progress-bar').attr('aria-valuenow'));
-            progress(oldPercent + percent);
+        const fakeProgress = function () {
+            const processObj = $('#check-progress');
+            let count = 0;
+            progressInterval = setInterval(function () {
+                const pos = parseInt(processObj.attr('aria-valuenow'));
+                if (pos < 10) {                        // 1
+                    progress(pos + 2);
+                } else if (pos < 20) {                 // 2
+                    progress(pos + 1);
+                } else if (pos < 90) {                 // 4
+                    count += 1;
+                    if (count % 2 === 0) {
+                        progress(pos + 1);
+                    }
+                }  else if (pos < 100) {               // 20
+                    count += 1;
+                    if (count % 40 === 0) {
+                        progress(pos + 1);
+                    }
+                }
+            }, 100);
         }
         }
-        const checkAndPost = async function (postUrl, postForm) {
+        const stopFakeProgess = function (fun) {
+            progress(100);
+            clearInterval(progressInterval);
+        }
+        const checkAndPost = async function (url, data) {
             progress(0);
             progress(0);
             $('#check').modal('show');
             $('#check').modal('show');
-            const lastestData = await loadCheckData();
-            progress(50);
-            const result = setting.checkFun(lastestData, addProgress);
-            progress(100);
-            setTimeout(function () {
-                if (result && result.length > 0) {
-                    $('#check-error-hint').modal('show');
-                    setting.errorList.loadErrorData(result);
+            fakeProgress();
+            postData(setting.checkUrl, setting.checkData ? setting.checkData : {}, function (result) {
+                if (result.error && result.error.length > 0) {
+                    if (setting.completeData) setting.completeData(result);
+                    setting.errorList.loadErrorData(result.error);
+                    stopFakeProgess();
+                    setTimeout(function () {
+                        $('#check-error-hint').modal('show');
+                    }, 300);
                 } else {
                 } else {
-                    postDataWithFile(postUrl, postForm, function (data) {
-                        if (data.url) window.location.href = data.url;
-                    });
+                    stopFakeProgess();
+                    setTimeout(function () {
+                        setting.errorList.clearErrorData();
+                        postData(url, data, function () {
+                            window.location.reload();
+                        });
+                    }, 300);
                 }
                 }
-            }, 1000);
+            }, function () {
+                $('#check').modal('hide');
+                stopFakeProgess();
+            });
         }
         }
         return {checkAndPost};
         return {checkAndPost};
     }
     }

+ 70 - 6
app/view/stage/audit_modal.ejs

@@ -65,7 +65,7 @@
                             </div>
                             </div>
                         </div>
                         </div>
                     </div>
                     </div>
-                    <form class="modal-footer" method="post" action="<%- preUrl %>/audit/start" onsubmit="return checkAuditorFrom()">
+                    <form class="modal-footer" method="post" action="<%- preUrl %>/audit/start" name="stage-start">
                         <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                         <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                         <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                         <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                         <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
                         <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
@@ -80,7 +80,7 @@
         <!--审批通过-->
         <!--审批通过-->
         <div class="modal fade" id="sp-done" data-backdrop="static">
         <div class="modal fade" id="sp-done" data-backdrop="static">
             <div class="modal-dialog modal-lg" role="document">
             <div class="modal-dialog modal-lg" role="document">
-                <form class="modal-content" action="<%- preUrl %>/audit/check" method="post" onsubmit="return auditCheck(0);">
+                <form class="modal-content" action="<%- preUrl %>/audit/check" method="post" id="audit-check0">
                     <div class="modal-header">
                     <div class="modal-header">
                         <h5 class="modal-title">审批通过</h5>
                         <h5 class="modal-title">审批通过</h5>
                     </div>
                     </div>
@@ -238,7 +238,7 @@
         <!--审批退回-->
         <!--审批退回-->
         <div class="modal fade" id="sp-back" data-backdrop="static">
         <div class="modal fade" id="sp-back" data-backdrop="static">
             <div class="modal-dialog modal-lg" role="document">
             <div class="modal-dialog modal-lg" role="document">
-                <form class="modal-content modal-lg" action="<%- preUrl %>/audit/check" method="post" onsubmit="return auditCheck(1);">
+                <form class="modal-content modal-lg" action="<%- preUrl %>/audit/check" method="post" id="audit-check1">
                     <div class="modal-header">
                     <div class="modal-header">
                         <h5 class="modal-title">审批退回</h5>
                         <h5 class="modal-title">审批退回</h5>
                     </div>
                     </div>
@@ -937,7 +937,7 @@
                             </div>
                             </div>
                         </div>
                         </div>
                     </div>
                     </div>
-                    <form class="modal-footer" method="post" action="<%- preUrl %>/audit/start" onsubmit="return checkAuditorFrom()">
+                    <form class="modal-footer" method="post" action="<%- preUrl %>/audit/start" name="stage-start">
                         <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                         <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                         <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                         <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                         <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
                         <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
@@ -1103,7 +1103,7 @@
         <!--审批通过-->
         <!--审批通过-->
         <div class="modal fade" id="sp-done" data-backdrop="static">
         <div class="modal fade" id="sp-done" data-backdrop="static">
             <div class="modal-dialog modal-lg" role="document">
             <div class="modal-dialog modal-lg" role="document">
-                <form class="modal-content" action="<%- preUrl %>/audit/check" method="post" onsubmit="return auditCheck(2);">
+                <form class="modal-content" action="<%- preUrl %>/audit/check" method="post" id="audit-check2">
                     <div class="modal-header">
                     <div class="modal-header">
                         <h5 class="modal-title">审批通过</h5>
                         <h5 class="modal-title">审批通过</h5>
                     </div>
                     </div>
@@ -1261,7 +1261,7 @@
         <!--审批退回-->
         <!--审批退回-->
         <div class="modal fade" id="sp-back" data-backdrop="static">
         <div class="modal fade" id="sp-back" data-backdrop="static">
             <div class="modal-dialog modal-lg" role="document">
             <div class="modal-dialog modal-lg" role="document">
-                <form class="modal-content" action="<%- preUrl %>/audit/check" method="post" onsubmit="return auditCheck(3);">
+                <form class="modal-content" action="<%- preUrl %>/audit/check" method="post" id="audit-check3">
                     <div class="modal-header">
                     <div class="modal-header">
                         <h5 class="modal-title">审批退回</h5>
                         <h5 class="modal-title">审批退回</h5>
                     </div>
                     </div>
@@ -1490,3 +1490,67 @@
         </div>
         </div>
     <% } %>
     <% } %>
 <% } %>
 <% } %>
+<% include ../shares/check_data_modal.ejs %>
+<script>
+    <% if (ctx.url !== '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order) { %>
+    const dataChecker = DataChecker({
+        checkUrl: '/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>/check',
+        errorList: $.cs_errorList({
+            storeKey: 'stage-error-' + <%- ctx.stage.id %>,
+        }),
+    });
+
+    $('[name=stage-start]').submit(function (e) {
+        if (checkAuditorFrom()) {
+            $(this).parent().parent().parent().modal('hide');
+            dataChecker.checkAndPost(this.action, {});
+            $('#hide-all').hide();
+        }
+        return false;
+    });
+    $('#audit-check0').submit(function (e) {
+        $(this).parent().parent().modal('hide');
+        const data = {
+            opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType: parseInt($('[name=checkType]', this).val()),
+        };
+        dataChecker.checkAndPost(this.action, data);
+        $('#hide-all').hide();
+        return false;
+    });
+    $('#audit-check2').submit(function (e) {
+        $(this).parent().parent().modal('hide');
+        const data = {
+            opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType: parseInt($('[name=checkType]', this).val()),
+        };
+        dataChecker.checkAndPost(this.action, data);
+        $('#hide-all').hide();
+        return false;
+    });
+    <% } %>
+    $('#audit-check1').submit(function (e) {
+        $(this).parent().parent().modal('hide');
+        const data = {
+            opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType: parseInt($('[name=checkType]:checked', this).val()),
+        };
+        postData(this.action, data, function () {
+            window.location.reload();
+        });
+        $('#hide-all').hide();
+        return false;
+    });
+    $('#audit-check3').submit(function (e) {
+        $(this).parent().parent().modal('hide');
+        const data = {
+            opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType: parseInt($('[name=checkType]:checked', this).val()),
+        };
+        postData(this.action, data, function () {
+            window.location.reload();
+        });
+        $('#hide-all').hide();
+        return false;
+    });
+</script>

+ 13 - 3
app/view/stage/index.ejs

@@ -41,7 +41,7 @@
         <div class="c-header p-0">
         <div class="c-header p-0">
         </div>
         </div>
         <div class="row w-100 sub-content">
         <div class="row w-100 sub-content">
-            <div id="main-view" class="c-body" style="width: 100%">
+            <div id="left-view" class="c-body" style="width: 100%">
                 <!--上部分-->
                 <!--上部分-->
                 <div class="sjs-height-1" id="stage-ledger">
                 <div class="sjs-height-1" id="stage-ledger">
                 </div>
                 </div>
@@ -99,8 +99,8 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
-            <div id="tools-view" class="c-body" style="display: none; width: 33%;">
-                <div class="resize-x" id="right-spr" r-Type="width" div1="#main-view" div2="#tools-view" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
+            <div id="right-view" class="c-body" style="display: none; width: 33%;">
+                <div class="resize-x" id="right-spr" r-Type="width" div1="#left-view" div2="#right-view" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
                 <div class="tab-content">
                 <div class="tab-content">
                     <!--中间计量-->
                     <!--中间计量-->
                     <div id="zhongjian" class="tab-pane tab-select-show">
                     <div id="zhongjian" class="tab-pane tab-select-show">
@@ -110,6 +110,8 @@
                         <div class="sjs-height-5" id="detail-spread" style="overflow:hidden">
                         <div class="sjs-height-5" id="detail-spread" style="overflow:hidden">
                         </div>
                         </div>
                         <div class="sjs-bottom">
                         <div class="sjs-bottom">
+                            <div class="resize-y" id="zhongjian-spr" r-Type="height" div1=".sjs-height-5" div2=".sjs-bottom" title="调整大小"><!--调整上下高度条--></div>
+                            <div class="zhongjian-msg" style="height:400px;overflow-y: auto">
                             <% if (!stage.readOnly) { %>
                             <% if (!stage.readOnly) { %>
                             <legend class="sticky-top bg-white">
                             <legend class="sticky-top bg-white">
                                 <div class="d-flex justify-content-end mb-1">
                                 <div class="d-flex justify-content-end mb-1">
@@ -206,6 +208,7 @@
                                     <p><a href="#imgview" data-toggle="modal" data-target="#imgview"><img src="" id="calc-img" class="w-100"></a></p>
                                     <p><a href="#imgview" data-toggle="modal" data-target="#imgview"><img src="" id="calc-img" class="w-100"></a></p>
                                 </div>
                                 </div>
                             </div>
                             </div>
+                            </div>
                         </div>
                         </div>
                     </div>
                     </div>
                     <!--查找定位-->
                     <!--查找定位-->
@@ -266,6 +269,7 @@
                                 </div>
                                 </div>
                             </div>
                             </div>
                             <div class="sjs-bottom">
                             <div class="sjs-bottom">
+                                <div class="resize-y" id="file-spr" r-Type="height" div1=".sjs-height-3" div2=".sjs-bottom" title="调整大小"><!--调整上下高度条--></div>
                                 <br>
                                 <br>
                                 <div class="tab-content" id="showAttachment" style="display: none" file-id="">
                                 <div class="tab-content" id="showAttachment" style="display: none" file-id="">
                                     <div class="sjs-bottom-2">
                                     <div class="sjs-bottom-2">
@@ -497,9 +501,12 @@
                         </div>
                         </div>
                         <div class="sjs-height-5" id="cc-spread" style="overflow:hidden">
                         <div class="sjs-height-5" id="cc-spread" style="overflow:hidden">
                         </div>
                         </div>
+                        <div class="resize-y" id="change-spr" r-Type="height" div1="#cc-spread" div2=".sjs-bottom" title="调整大小"><!--调整上下高度条--></div>
                         <div class="sjs-bottom" id="ccb-spread">
                         <div class="sjs-bottom" id="ccb-spread">
                         </div>
                         </div>
                     </div>
                     </div>
+                    <div id="error-list" class="tab-pane">
+                    </div>
                 </div>
                 </div>
             </div>
             </div>
         </div>
         </div>
@@ -521,6 +528,9 @@
                 <li class="nav-item">
                 <li class="nav-item">
                     <a class="nav-link" content="#checked-change" href="javascript: void(0);">变更令</a>
                     <a class="nav-link" content="#checked-change" href="javascript: void(0);">变更令</a>
                 </li>
                 </li>
+                <li class="nav-item">
+                    <a class="nav-link" content="#error-list" id="error-list-tab" href="javascript: void(0);" style="display: none;">错误列表</a>
+                </li>
             </ul>
             </ul>
         </div>
         </div>
     </div>
     </div>

+ 1 - 1
app/view/stage/modal.ejs

@@ -265,7 +265,7 @@
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
                     <label>中间计量表号前缀</label>
                     <label>中间计量表号前缀</label>
-                    <input type="text" class="form-control form-control-sm" value="<%- ctx.stage.im_pre ? ctx.stage.im_pre : '' %>" id="im-pre" maxlength="10">
+                    <input type="text" class="form-control form-control-sm" value="<%- ctx.stage.im_pre ? ctx.stage.im_pre : '' %>" id="im-pre" maxlength="20">
                 </div>
                 </div>
                 <div class="form-group">
                 <div class="form-group">
                     <label> </label>
                     <label> </label>

+ 10 - 8
app/view/wap/dashboard.ejs

@@ -47,12 +47,12 @@
                         <div class="d-flex justify-content-between"><span>第<%- audit.order %>期</span><span><%- audit.s_time %></span></div>
                         <div class="d-flex justify-content-between"><span>第<%- audit.order %>期</span><span><%- audit.s_time %></span></div>
                         <div class="my-2">
                         <div class="my-2">
                             <table class="table table-sm table-bordered">
                             <table class="table table-sm table-bordered">
-                                <tr><th>本期合同计量</th><td class="text-right"><%- ctx.helper.formatMoney(audit.contract_tp) %></td></tr>
-                                <tr><th>本期数量变更计量</th><td class="text-right"><%- ctx.helper.formatMoney(audit.qc_tp) %></td></tr>
-                                <tr><th>本期完成计量</th><td class="text-right"><%- ctx.helper.formatMoney(audit.gather_tp) %></td></tr>
-                                <tr><th>截止上期完成计量</th><td class="text-right"><%- ctx.helper.formatMoney(audit.pre_gather_tp) %></td></tr>
-                                <tr><th>截止本期完成计量</th><td class="text-right"><%- ctx.helper.formatMoney(audit.end_gather_tp) %></td></tr>
-                                <tr><th>本期应付</th><td class="text-right"><%- ctx.helper.formatMoney(audit.yf_tp) %></td></tr>
+                                <tr><th>本期合同计量</th><td class="text-right"><%- audit.contract_tp ? audit.contract_tp : 0 %></td></tr>
+                                <tr><th>本期数量变更计量</th><td class="text-right"><%- audit.qc_tp ? audit.qc_tp : 0 %></td></tr>
+                                <tr><th>本期完成计量</th><td class="text-right"><%- audit.gather_tp ? audit.gather_tp : 0 %></td></tr>
+                                <tr><th>截止上期完成计量</th><td class="text-right"><%- audit.pre_gather_tp ? audit.pre_gather_tp : 0 %></td></tr>
+                                <tr><th>截止本期完成计量</th><td class="text-right"><%- audit.end_gather_tp ? audit.end_gather_tp : 0 %></td></tr>
+                                <tr><th>本期应付</th><td class="text-right"><%- audit.yf_tp ? audit.yf_tp : 0 %></td></tr>
                             </table>
                             </table>
                         </div>
                         </div>
                         <div class="">
                         <div class="">
@@ -69,10 +69,10 @@
         <nav class="fixed-bottom navbar-dark bg-light border-top">
         <nav class="fixed-bottom navbar-dark bg-light border-top">
           <ul class="nav nav-fill my-2">
           <ul class="nav nav-fill my-2">
               <li class="nav-item">
               <li class="nav-item">
-                <a class="nav-link active" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
+                <a class="nav-link active show-loading" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
               </li>
               </li>
               <li class="nav-item">
               <li class="nav-item">
-                <a class="nav-link text-muted" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
+                <a class="nav-link text-muted show-loading" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
               </li>
               </li>
             </ul>
             </ul>
         </nav>
         </nav>
@@ -82,6 +82,8 @@
     <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
     <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/popper/popper.min.js"></script>
     <script src="/public/js/bootstrap/bootstrap.min.js"></script>
     <script src="/public/js/bootstrap/bootstrap.min.js"></script>
+    <script src="/public/js/cookies.js"></script>
+    <script src="/public/js/wap/global.js"></script>
 </body>
 </body>
 
 
 </html>
 </html>

+ 3 - 2
app/view/wap/list.ejs

@@ -48,10 +48,10 @@
     <nav class="fixed-bottom navbar-dark bg-light border-top">
     <nav class="fixed-bottom navbar-dark bg-light border-top">
         <ul class="nav nav-fill my-2">
         <ul class="nav nav-fill my-2">
             <li class="nav-item">
             <li class="nav-item">
-                <a class="nav-link text-muted" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
+                <a class="nav-link text-muted show-loading" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
             </li>
             </li>
             <li class="nav-item">
             <li class="nav-item">
-                <a class="nav-link active " href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
+                <a class="nav-link active show-loading" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
             </li>
             </li>
         </ul>
         </ul>
     </nav>
     </nav>
@@ -70,6 +70,7 @@
 <script src="/public/js/lodash.js"></script>
 <script src="/public/js/lodash.js"></script>
 <script src="/public/js/lz-string/lz-string.js"></script>
 <script src="/public/js/lz-string/lz-string.js"></script>
 <script src="/public/js/number-precision.js"></script>
 <script src="/public/js/number-precision.js"></script>
+<script src="/public/js/cookies.js"></script>
 <script src="/public/js/wap/global.js"></script>
 <script src="/public/js/wap/global.js"></script>
 <script src="/public/js/decimal.min.js"></script>
 <script src="/public/js/decimal.min.js"></script>
 <script src="/public/js/zh_calc.js"></script>
 <script src="/public/js/zh_calc.js"></script>

+ 0 - 1
app/view/wap/login.ejs

@@ -63,7 +63,6 @@
         </div>
         </div>
     </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>
 <!-- JS. -->
 <!-- JS. -->
 <div class="toast" style="text-align: center">
 <div class="toast" style="text-align: center">

+ 60 - 24
app/view/wap/tender.ejs

@@ -22,7 +22,10 @@
     <!--顶部-->
     <!--顶部-->
     <nav class="fixed-top bg-dark">
     <nav class="fixed-top bg-dark">
         <div class="my-2 d-flex justify-content-between">
         <div class="my-2 d-flex justify-content-between">
-            <span class="text-white ml-3"><a href="/wap/list" class="mr-2 text-white"><i class="fa fa-chevron-left"></i></a>标段概况</span>
+            <span class="text-white ml-3"><a href="/wap/list" class="mr-2 text-white show-loading"><i class="fa fa-chevron-left"></i>标段概况</a></span>
+            <a tabindex="0" href="javascript:void(0)" class="text-white text-truncate text-center"
+               style="width:150px" data-toggle="popover" data-placement="top"
+               data-content="<%- tender.name %>" data-trigger="focus"><%- tender.name %></a>
             <div class="mr-3">
             <div class="mr-3">
                 <div class="dropdown">
                 <div class="dropdown">
                     <button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown">
                     <button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown">
@@ -54,16 +57,22 @@
                 <!--图表-->
                 <!--图表-->
                 <div class="card mb-3 mr-1 mt-3">
                 <div class="card mb-3 mr-1 mt-3">
                     <div class="card-body">
                     <div class="card-body">
-                        <h5 class="card-title">月进度表</h5>
-                        <div id="chartContainer3" style="height: 300px; width: 100%;">
+                        <h5 class="card-title">期进度表</h5>
+                        <div style="overflow-x:scroll;padding-bottom: 10px">
+                            <div id="chartContainer4" style="height: 300px; width: 250%;">
+                            </div>
                         </div>
                         </div>
+                        <p class="text-center text-muted m-0">左右滑动</p>
                     </div>
                     </div>
                 </div>
                 </div>
                 <div class="card mb-3 mr-1">
                 <div class="card mb-3 mr-1">
                     <div class="card-body">
                     <div class="card-body">
-                        <h5 class="card-title">期进度表</h5>
-                        <div id="chartContainer4" style="height: 300px; width: 100%;">
+                        <h5 class="card-title">月进度表</h5>
+                        <div style="overflow-x:scroll;padding-bottom: 10px">
+                            <div id="chartContainer3" style="height: 300px; width: 320%;">
+                            </div>
                         </div>
                         </div>
+                        <p class="text-center text-muted m-0">左右滑动</p>
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
@@ -84,31 +93,31 @@
                             <tbody><tr>
                             <tbody><tr>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期合同计量</p>
                                     <p class="mb-0">本期合同计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((s.contract_tp ? s.contract_tp : 0)) %></b>
+                                    <b>¥<%- s.contract_tp ? s.contract_tp : 0 %></b>
                                 </td>
                                 </td>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期数量变更计量</p>
                                     <p class="mb-0">本期数量变更计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((s.qc_tp ? s.qc_tp : 0)) %></b>
+                                    <b>¥<%- s.qc_tp ? s.qc_tp : 0 %></b>
                                 </td>
                                 </td>
                             </tr>
                             </tr>
                             <tr>
                             <tr>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期完成计量</p>
                                     <p class="mb-0">本期完成计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((s.tp ? s.tp : 0)) %></b>
+                                    <b>¥<%- s.tp ? s.tp : 0 %></b>
                                 </td>
                                 </td>
                                 <td>
                                 <td>
                                     <p class="mb-0">截止上期完成计量</p>
                                     <p class="mb-0">截止上期完成计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((s.pre_tp ? s.pre_tp : 0)) %></b>
+                                    <b>¥<%- s.pre_tp ? s.pre_tp : 0 %></b>
                                 </td>
                                 </td>
                             </tr>
                             </tr>
                             <tr>
                             <tr>
                                 <td>
                                 <td>
                                     <p class="mb-0">截止本期完成计量</p>
                                     <p class="mb-0">截止本期完成计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((s.end_tp ? s.end_tp : 0)) %></b>
+                                    <b>¥<%- s.end_tp ? s.end_tp : 0 %></b>
                                 </td>
                                 </td>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期应付</p>
                                     <p class="mb-0">本期应付</p>
-                                    <b>¥<%- ctx.helper.formatMoney((s.yf_tp ? s.yf_tp : 0)) %></b>
+                                    <b>¥<%- s.yf_tp ? s.yf_tp : 0 %></b>
                                 </td>
                                 </td>
                             </tr>
                             </tr>
                             </tbody></table>
                             </tbody></table>
@@ -134,31 +143,31 @@
                             <tbody><tr>
                             <tbody><tr>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期合同计量</p>
                                     <p class="mb-0">本期合同计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((stage.contract_tp ? stage.contract_tp : 0)) %></b>
+                                    <b>¥<%- stage.contract_tp ? stage.contract_tp : 0 %></b>
                                 </td>
                                 </td>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期数量变更计量</p>
                                     <p class="mb-0">本期数量变更计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((stage.qc_tp ? stage.qc_tp : 0)) %></b>
+                                    <b>¥<%- stage.qc_tp ? stage.qc_tp : 0 %></b>
                                 </td>
                                 </td>
                             </tr>
                             </tr>
                             <tr>
                             <tr>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期完成计量</p>
                                     <p class="mb-0">本期完成计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((stage.tp ? stage.tp : 0)) %></b>
+                                    <b>¥<%- stage.tp ? stage.tp : 0 %></b>
                                 </td>
                                 </td>
                                 <td>
                                 <td>
                                     <p class="mb-0">截止上期完成计量</p>
                                     <p class="mb-0">截止上期完成计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((stage.pre_tp ? stage.pre_tp : 0)) %></b>
+                                    <b>¥<%- stage.pre_tp ? stage.pre_tp : 0 %></b>
                                 </td>
                                 </td>
                             </tr>
                             </tr>
                             <tr>
                             <tr>
                                 <td>
                                 <td>
                                     <p class="mb-0">截止本期完成计量</p>
                                     <p class="mb-0">截止本期完成计量</p>
-                                    <b>¥<%- ctx.helper.formatMoney((stage.end_tp ? stage.end_tp : 0)) %></b>
+                                    <b>¥<%- stage.end_tp ? stage.end_tp : 0 %></b>
                                 </td>
                                 </td>
                                 <td>
                                 <td>
                                     <p class="mb-0">本期应付</p>
                                     <p class="mb-0">本期应付</p>
-                                    <b>¥<%- ctx.helper.formatMoney((stage.yf_tp ? stage.yf_tp : 0)) %></b>
+                                    <b>¥<%- stage.yf_tp ? stage.yf_tp : 0 %></b>
                                 </td>
                                 </td>
                             </tr>
                             </tr>
                             </tbody></table>
                             </tbody></table>
@@ -222,10 +231,10 @@
     <nav class="fixed-bottom navbar-dark bg-light border-top">
     <nav class="fixed-bottom navbar-dark bg-light border-top">
         <ul class="nav nav-fill my-2">
         <ul class="nav nav-fill my-2">
             <li class="nav-item">
             <li class="nav-item">
-                <a class="nav-link text-muted" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
+                <a class="nav-link text-muted show-loading" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
             </li>
             </li>
             <li class="nav-item">
             <li class="nav-item">
-                <a class="nav-link active " href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
+                <a class="nav-link active show-loading" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
             </li>
             </li>
         </ul>
         </ul>
     </nav>
     </nav>
@@ -234,7 +243,7 @@
 <!--审批通过弹窗-->
 <!--审批通过弹窗-->
 <div class="modal" tabindex="-1" role="dialog" id="sp-done">
 <div class="modal" tabindex="-1" role="dialog" id="sp-done">
     <div class="modal-dialog" role="document">
     <div class="modal-dialog" role="document">
-        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" onsubmit="return auditCheck(0);">
+        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" id="audit-check0">
             <div class="modal-header">
             <div class="modal-header">
                 <h5 class="modal-title">审批通过</h5>
                 <h5 class="modal-title">审批通过</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
@@ -258,8 +267,8 @@
 </div>
 </div>
 <!--审批退回弹窗-->
 <!--审批退回弹窗-->
 <div class="modal" tabindex="-1" role="dialog" id="sp-back">
 <div class="modal" tabindex="-1" role="dialog" id="sp-back">
-    < class="modal-dialog" role="document">
-        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" onsubmit="return auditCheck(1);">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/tender/<%- stage.tid %>/measure/stage/<%- stage.order %>/audit/check" method="post" id="audit-check1">
             <div class="modal-header">
             <div class="modal-header">
                 <h5 class="modal-title">审批通过</h5>
                 <h5 class="modal-title">审批通过</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
@@ -273,7 +282,7 @@
                 </div>
                 </div>
                 <div class="alert alert-warning">
                 <div class="alert alert-warning">
                     <div class="custom-control custom-radio custom-control-inline">
                     <div class="custom-control custom-radio custom-control-inline">
-                        <input type="radio" id="inlineRadio1" class="custom-control-input" value="<%- auditConst.status.checkNo %>" <% if (audit.order === 1 || audit.aid === stage.auditors[0].aid) { %>checked<% } %>>
+                        <input type="radio" id="customRadioInline1" name="checkType" class="custom-control-input" value="<%- auditConst.status.checkNo %>" <% if (audit.order === 1 || audit.aid === stage.auditors[0].aid) { %>checked<% } %>>
                         <label class="custom-control-label" for="customRadioInline1">退回上报 <%- stage.user.name %></label>
                         <label class="custom-control-label" for="customRadioInline1">退回上报 <%- stage.user.name %></label>
                     </div>
                     </div>
                     <% if (audit.order > 1 && audit.aid !== stage.auditors[0].aid) { %>
                     <% if (audit.order > 1 && audit.aid !== stage.auditors[0].aid) { %>
@@ -298,7 +307,8 @@
 <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
 <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/popper/popper.min.js"></script>
 <script src="/public/js/bootstrap/bootstrap.min.js"></script>
 <script src="/public/js/bootstrap/bootstrap.min.js"></script>
-<!--<script src="js/global.js"></script>-->
+<script src="/public/js/cookies.js"></script>
+<script src="/public/js/wap/global.js"></script>
 <script type="text/javascript">
 <script type="text/javascript">
     //4 标段期数计量进度//
     //4 标段期数计量进度//
     var myChart = echarts.init(document.getElementById('chartContainer4'));
     var myChart = echarts.init(document.getElementById('chartContainer4'));
@@ -535,9 +545,35 @@
             $('#shenpi').addClass('active');
             $('#shenpi').addClass('active');
             $('.nav-item a[href="#shenpi"]').addClass('active');
             $('.nav-item a[href="#shenpi"]').addClass('active');
         }
         }
+
+        $('#audit-check0').submit(function (e) {
+            if (auditCheck(0)) {
+                const data = {
+                    opinion: $('[name=opinion]', this).val(),
+                    checkType: parseInt($('[name=checkType]', this).val()),
+                };
+                postData(this.action, data, function () {
+                    window.location.reload();
+                });
+            }
+            return false;
+        });
+        $('#audit-check1').submit(function (e) {
+            if (auditCheck(1)) {
+                const data = {
+                    opinion: $('[name=opinion]', this).val(),
+                    checkType: parseInt($('[name=checkType]:checked', this).val()),
+                };
+                postData(this.action, data, function () {
+                    window.location.reload();
+                });
+            }
+            return false;
+        });
     })
     })
 
 
     // texterea换行
     // texterea换行
+
     function auditCheck(i) {
     function auditCheck(i) {
         const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
         const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
         $('textarea[name="opinion"]').eq(i).val(opinion);
         $('textarea[name="opinion"]').eq(i).val(opinion);

+ 60 - 4
builder_report_index_define.js

@@ -263,7 +263,9 @@ const stage_bills = {
         { name: '章节编号', field: 'chapter', type: dataType.str },
         { name: '章节编号', field: 'chapter', type: dataType.str },
 
 
         { name: '预留扩展字段_1', field: 'ex_value1', type: dataType.currency },
         { name: '预留扩展字段_1', field: 'ex_value1', type: dataType.currency },
-        { name: '预留扩展字段_2', field: 'ex_value1', type: dataType.currency },
+        { name: '预留扩展字段_2', field: 'ex_value2', type: dataType.currency },
+
+        { name: '最底层项目节id', field: 'leaf_xmj_id', type: dataType.str },
     ],
     ],
 };
 };
 const stage_bills_compare = {
 const stage_bills_compare = {
@@ -386,6 +388,7 @@ const stage_bills_compare = {
         { name: '本期-完成-金额_9', field: 'r9_gather_tp', type: dataType.currency, tag: {type: 'tp'} },
         { name: '本期-完成-金额_9', field: 'r9_gather_tp', type: dataType.currency, tag: {type: 'tp'} },
 
 
         { name: '章节编号', field: 'chapter', type: dataType.str },
         { name: '章节编号', field: 'chapter', type: dataType.str },
+        { name: '最底层项目节id', field: 'leaf_xmj_id', type: dataType.str },
     ],
     ],
 };
 };
 // 期 - 计量单元
 // 期 - 计量单元
@@ -790,11 +793,64 @@ const gather_tender_info = {
         { name: '截止本期-变更-金额', field: 'end_qc_tp', type: dataType.currency },
         { name: '截止本期-变更-金额', field: 'end_qc_tp', type: dataType.currency },
         { name: '截止本期-完成-金额', field: 'end_gather_tp', type: dataType.currency },
         { name: '截止本期-完成-金额', field: 'end_gather_tp', type: dataType.currency },
 
 
-        { name: '截止上期-应付', field: 'pre_yf', type: dataType.currency },
-        { name: '本期-应付', field: 'yf', type: dataType.currency },
-        { name: '截止本期-应付', field: 'end_yf', type: dataType.currency },
+        { name: '截止上期-应付', field: 'pre_yf_tp', type: dataType.currency },
+        { name: '本期-应付', field: 'yf_tp', type: dataType.currency },
+        { name: '截止本期-应付', field: 'end_yf_tp', type: dataType.currency },
 
 
         { name: '签约清单-金额', field: 'deal_bills_tp', type: dataType.currency },
         { name: '签约清单-金额', field: 'deal_bills_tp', type: dataType.currency },
+
+        { name: '合同信息-建设项目名称', field: 'deal_info.buildName', type: dataType.str},
+        { name: '合同信息-合同编号', field: 'deal_info.dealCode', type: dataType.str},
+        { name: '合同信息-合同名称', field: 'deal_info.dealName', type: dataType.str},
+
+        { name: '参建单位-建设单位-单位名称', field: 'construction_unit.build.company', type: dataType.str},
+        { name: '参建单位-建设单位-法人代表', field: 'construction_unit.build.corporation', type: dataType.str},
+        { name: '参建单位-建设单位-签订日期', field: 'construction_unit.build.date', type: dataType.str},
+
+        { name: '参建单位-承包单位1-单位名称', field: 'construction_unit.contract1.company', type: dataType.str},
+        { name: '参建单位-承包单位1-法人代表', field: 'construction_unit.contract1.corporation', type: dataType.str},
+        { name: '参建单位-承包单位1-签订日期', field: 'construction_unit.contract1.date', type: dataType.str},
+
+        { name: '参建单位-承包单位2-单位名称', field: 'construction_unit.contract2.company', type: dataType.str},
+        { name: '参建单位-承包单位2-法人代表', field: 'construction_unit.contract2.corporation', type: dataType.str},
+        { name: '参建单位-承包单位2-签订日期', field: 'construction_unit.contract2.date', type: dataType.str},
+
+        { name: '参建单位-监理单位1-单位名称', field: 'construction_unit.supervision1.company', type: dataType.str},
+        { name: '参建单位-监理单位1-法人代表', field: 'construction_unit.supervision1.corporation', type: dataType.str},
+        { name: '参建单位-监理单位1-签订日期', field: 'construction_unit.supervision1.date', type: dataType.str},
+
+        { name: '参建单位-监理单位2-单位名称', field: 'construction_unit.supervision2.company', type: dataType.str},
+        { name: '参建单位-监理单位2-法人代表', field: 'construction_unit.supervision2.corporation', type: dataType.str},
+        { name: '参建单位-监理单位2-签订日期', field: 'construction_unit.supervision2.date', type: dataType.str},
+
+        { name: '技术参数-公路等级', field: 'tech_param.loadLevel', type: dataType.int},
+        { name: '技术参数-长度(KM)', field: 'tech_param.loadLength', type: dataType.int},
+        { name: '技术参数-起始桩号', field: 'tech_param.startPeg', type: dataType.str},
+        { name: '技术参数-终止桩号', field: 'tech_param.endPeg', type: dataType.str},
+        { name: '技术参数-车道数', field: 'tech_param.laneCount', type: dataType.int},
+        { name: '技术参数-合同工期', field: 'tech_param.dealPeriod', type: dataType.str},
+        { name: '技术参数-开工日期', field: 'tech_param.startDate', type: dataType.str},
+        { name: '技术参数-计划完工日期', field: 'tech_param.planEndDate', type: dataType.str},
+
+        { name: '合同参数-签约合同价', field: 'deal_param.contractPrice', type: dataType.currency },
+        { name: '合同参数-暂列金额', field: 'deal_param.zanLiePrice', type: dataType.currency },
+        { name: '合同参数-签约合同价(不含暂列金额)', field: 'deal_param.contractPriceWithoutZL', type: dataType.currency },
+        { name: '合同参数-签约开工预付款', field: 'deal_param.startAdvance', type: dataType.currency },
+        { name: '合同参数-签约材料预付款', field: 'deal_param.materialAdvance', type: dataType.currency },
+
+        { name: '付款账号-工程款账户-开户名称', field: 'pay_account.project.name', type: dataType.str },
+        { name: '付款账号-工程款账户-开户银行', field: 'pay_account.project.bank', type: dataType.str },
+        { name: '付款账号-工程款账户-开户账号', field: 'pay_account.project.account', type: dataType.str },
+        { name: '付款账号-工程款账户-分账划拨比例(%)', field: 'pay_account.project.rate', type: dataType.str },
+        { name: '付款账号-工程款账户-联系人', field: 'pay_account.project.contact', type: dataType.str },
+        { name: '付款账号-工程款账户-联系电话', field: 'pay_account.project.phone', type: dataType.str },
+
+        { name: '付款账号-农民工工资专用账户-开户名称', field: 'pay_account.worker.name', type: dataType.str },
+        { name: '付款账号-农民工工资专用账户-开户银行', field: 'pay_account.worker.bank', type: dataType.str },
+        { name: '付款账号-农民工工资专用账户-开户账号', field: 'pay_account.worker.account', type: dataType.str },
+        { name: '付款账号-农民工工资专用账户-分账划拨比例(%)', field: 'pay_account.worker.rate', type: dataType.str },
+        { name: '付款账号-农民工工资专用账户-联系人', field: 'pay_account.worker.contact', type: dataType.str },
+        { name: '付款账号-农民工工资专用账户-联系电话', field: 'pay_account.worker.phone', type: dataType.str },
     ],
     ],
 };
 };
 const gather_stage_pay = {
 const gather_stage_pay = {

+ 13 - 10
config/web.js

@@ -136,14 +136,13 @@ const JsFiles = {
                     "/public/js/math.min.js",
                     "/public/js/math.min.js",
                     "/public/js/file-saver/FileSaver.js",
                     "/public/js/file-saver/FileSaver.js",
                     "/public/js/shares/export_excel.js",
                     "/public/js/shares/export_excel.js",
-                    "/public/js/shares/cs_tools.js",
                 ],
                 ],
                 mergeFiles: [
                 mergeFiles: [
                     "/public/js/sub_menu.js",
                     "/public/js/sub_menu.js",
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/shares/merge_peg.js",
                     "/public/js/shares/merge_peg.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
@@ -157,14 +156,13 @@ const JsFiles = {
                 files: [
                 files: [
                     "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
                     "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
                     "/public/js/decimal.min.js",
                     "/public/js/decimal.min.js",
-                    "/public/js/shares/cs_tools.js",
                 ],
                 ],
                 mergeFiles: [
                 mergeFiles: [
                     "/public/js/sub_menu.js",
                     "/public/js/sub_menu.js",
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/ledger_audit.js",
                     "/public/js/ledger_audit.js",
@@ -184,7 +182,7 @@ const JsFiles = {
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/shares/bills_pos_convert.js",
                     "/public/js/shares/bills_pos_convert.js",
@@ -220,7 +218,7 @@ const JsFiles = {
                     "/public/js/sub_menu.js",
                     "/public/js/sub_menu.js",
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/std_lib.js",
                     "/public/js/std_lib.js",
@@ -243,7 +241,7 @@ const JsFiles = {
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/shares/merge_peg.js",
                     "/public/js/shares/merge_peg.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
@@ -262,7 +260,7 @@ const JsFiles = {
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/revise_history.js",
                     "/public/js/revise_history.js",
@@ -284,7 +282,7 @@ const JsFiles = {
                     "/public/js/msg_box.js",
                     "/public/js/msg_box.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/shares/merge_peg.js",
                     "/public/js/shares/merge_peg.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
@@ -306,6 +304,7 @@ const JsFiles = {
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/stage_im.js",
                     "/public/js/stage_im.js",
                     "/public/js/stage_detail.js",
                     "/public/js/stage_detail.js",
                     "/public/js/stage_audit.js",
                     "/public/js/stage_audit.js",
@@ -320,6 +319,7 @@ const JsFiles = {
                 mergeFiles: [
                 mergeFiles: [
                     "/public/js/sub_menu.js",
                     "/public/js/sub_menu.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/stage_pay.js",
                     "/public/js/stage_pay.js",
                     "/public/js/stage_audit.js",
                     "/public/js/stage_audit.js",
                 ],
                 ],
@@ -338,7 +338,7 @@ const JsFiles = {
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
-                    "/public/js/ledger_search.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/shares/bills_pos_convert.js",
                     "/public/js/shares/bills_pos_convert.js",
@@ -356,6 +356,7 @@ const JsFiles = {
                     "/public/js/sub_menu.js",
                     "/public/js/sub_menu.js",
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/stage_change.js",
                     "/public/js/stage_change.js",
@@ -375,6 +376,7 @@ const JsFiles = {
                     "/public/js/sub_menu.js",
                     "/public/js/sub_menu.js",
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/gcl_gather.js",
                     "/public/js/gcl_gather.js",
@@ -396,6 +398,7 @@ const JsFiles = {
                     "/public/js/div_resizer.js",
                     "/public/js/div_resizer.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/shares/sjs_setting.js",
                     "/public/js/shares/sjs_setting.js",
+                    "/public/js/shares/cs_tools.js",
                     "/public/js/zh_calc.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
                     "/public/js/path_tree.js",
                     "/public/js/stage_compare.js",
                     "/public/js/stage_compare.js",

+ 5 - 0
sql/update.sql

@@ -0,0 +1,5 @@
+UPDATE `zh_stage_pay` sp
+  LEFT JOIN `zh_stage` s ON sp.sid = s.id
+  LEFT JOIN `zh_pay` p ON sp.pid = p.id
+  SET sp.`pre_used` = 1
+  WHERE (sp.`start_stage_order` < s.`order` OR ((not IsNULL(sp.pre_tp)) AND sp.pre_tp) AND sp.`pre_used` = 0 AND p.`ptype` = 1;

+ 15 - 0
sql/update20200527.sql

@@ -0,0 +1,15 @@
+ALTER TABLE `zh_project` ADD `office_share` VARCHAR(1000) NULL COMMENT '办事处共享(office id列表)' AFTER `office`;
+
+ALTER TABLE `zh_project` ADD `manager_office` TINYINT(3) NULL DEFAULT NULL COMMENT '负责人办事处' AFTER `manager_id`;
+
+UPDATE `zh_project` SET `manager_office`=`office`;
+
+UPDATE `zh_project` as a, `zh_manager` as b SET a.`creator`= b.`id` WHERE a.`creator` LIKE '%付青青%' AND b.`username` = '付青青';
+UPDATE `zh_project` as a, `zh_manager` as b SET a.`creator`= b.`id` WHERE a.`creator` LIKE '%梁琪波%' AND b.`username` = '梁琪波';
+UPDATE `zh_project` as a, `zh_manager` as b SET a.`creator`= b.`id` WHERE a.`creator` LIKE '%曾沛文%' AND b.`username` = '曾沛文';
+UPDATE `zh_project` as a, `zh_manager` as b SET a.`creator`= b.`id` WHERE a.`creator` LIKE '%周洪波%' AND b.`username` = '周洪波';
+UPDATE `zh_project` as a, `zh_manager` as b SET a.`creator`= b.`id` WHERE a.`creator` LIKE '%王星植%' AND b.`username` = '王星植';
+
+INSERT INTO `zh_permission`(`id`, `name`, `controller`, `action`, `pid`, `icon_class`, `create_time`, `isshow`) VALUES (70, '办事处共享', 'project', 'office', 38, '', null, 1);
+
+-- 2020-05-27 更新uat/prod