Browse Source

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

TonyKang 4 years ago
parent
commit
d345d3c780
54 changed files with 974 additions and 574 deletions
  1. 0 1
      app/const/tender_info.js
  2. 42 13
      app/controller/advance_controller.js
  3. 35 3
      app/controller/change_controller.js
  4. 2 5
      app/controller/ledger_audit_controller.js
  5. 2 5
      app/controller/revise_controller.js
  6. 12 1
      app/controller/tender_controller.js
  7. 0 3
      app/middleware/session_auth.js
  8. 35 41
      app/middleware/tender_check.js
  9. 65 0
      app/middleware/uncheck_tender_check.js
  10. 18 18
      app/public/js/advance.js
  11. 8 7
      app/public/js/advance_audit.js
  12. 10 2
      app/public/js/change_detail.js
  13. 39 29
      app/public/js/change_set.js
  14. 102 38
      app/public/js/ledger.js
  15. 2 0
      app/public/js/ledger_audit.js
  16. 7 0
      app/public/js/local-forage/localforage.min.js
  17. 2 0
      app/public/js/measure_compare.js
  18. 20 0
      app/public/js/measure_stage.js
  19. 69 24
      app/public/js/path_tree.js
  20. 29 0
      app/public/js/revise.js
  21. 12 0
      app/public/js/spreadjs_rela/spreadjs_zh.js
  22. 77 14
      app/public/js/stage.js
  23. 1 3
      app/public/js/stage_pay.js
  24. 1 0
      app/public/js/tender_list.js
  25. 2 0
      app/public/js/tender_list_info.js
  26. 2 0
      app/public/js/tender_list_manage.js
  27. 2 0
      app/public/js/tender_list_progress.js
  28. 135 133
      app/router.js
  29. 24 5
      app/service/advance.js
  30. 3 1
      app/service/change.js
  31. 1 1
      app/service/login_logging.js
  32. 10 2
      app/service/stage_bonus.js
  33. 14 6
      app/service/stage_jgcl.js
  34. 12 4
      app/service/stage_other.js
  35. 26 2
      app/service/tender_info.js
  36. 9 9
      app/view/advance/detail.ejs
  37. 8 8
      app/view/advance/index.ejs
  38. 1 1
      app/view/advance/modal.ejs
  39. 2 2
      app/view/change/info.ejs
  40. 3 0
      app/view/layout/menu.ejs
  41. 5 2
      app/view/ledger/bwtz.ejs
  42. 2 11
      app/view/ledger/explode_modal.ejs
  43. 0 5
      app/view/material/info.ejs
  44. 0 5
      app/view/material/list.ejs
  45. 1 0
      app/view/revise/info.ejs
  46. 2 10
      app/view/revise/info_modal.ejs
  47. 68 30
      app/view/shares/ledger_check_modal.ejs
  48. 30 93
      app/view/stage/audit_modal.ejs
  49. 5 2
      app/view/stage/bwtz.ejs
  50. 8 0
      app/view/stage/index.ejs
  51. 1 0
      app/view/stage/modal.ejs
  52. 3 33
      app/view/tender/detail_modal.ejs
  53. 3 2
      builder_report_index_define.js
  54. 2 0
      config/config.default.js

+ 0 - 1
app/const/tender_info.js

@@ -64,7 +64,6 @@ const defaultInfo = {
         pay: false,
         payTp: 0,
         extra: false,
-        extraQty: 3,
         extraTp: 0,
     },
     precision: {

+ 42 - 13
app/controller/advance_controller.js

@@ -1,7 +1,6 @@
 'use strict';
 const accountGroup = require('../const/account_group').group;
 const auditConst = require('../const/audit').advance;
-const ledgerAuditConst = require('../const/audit').ledger.status;
 const sendToWormhole = require('stream-wormhole');
 const path = require('path');
 const fs = require('fs');
@@ -19,11 +18,10 @@ module.exports = app => {
          */
         async index(ctx) {
             const type = auditConst.type.start;
-            const advanceList = await ctx.service.advance.getAdvanceList(ctx.tender.id, type);
-            const latestOrder = await ctx.service.advance.getLastestAdvance(ctx.tender.id, type, true);
             const advancePayTotal = ctx.tender.info.deal_param.startAdvance;
+            const advanceList = await ctx.service.advance.getAdvanceList(ctx.tender.id, type, this.decimal, advancePayTotal);
+            const latestOrder = await ctx.service.advance.getLastestAdvance(ctx.tender.id, type, true);
             const progress = await ctx.service.advance.calcProgress(latestOrder, advancePayTotal);
-            // const showAddBtn = ctx.tender.data.ledger_status !== ledgerAuditConst.uncheck && ctx.tender.data.user_id === ctx.session.sessionUser.accountId ? !latestOrder || (latestOrder.status === auditConst.status.checked && latestOrder.prev_total_amount < advancePayTotal) : false;
             const showAddBtn = ctx.tender.data.user_id === ctx.session.sessionUser.accountId ? (!latestOrder || (latestOrder.status === auditConst.status.checked && latestOrder.prev_total_amount < advancePayTotal)) : false;
             const renderData = {
                 type,
@@ -46,9 +44,9 @@ module.exports = app => {
          */
         async materialList(ctx) {
             const type = auditConst.type.material;
-            const advanceList = await ctx.service.advance.getAdvanceList(ctx.tender.id, type);
-            const latestOrder = await ctx.service.advance.getLastestAdvance(ctx.tender.id, type, true);
             const advancePayTotal = ctx.tender.info.deal_param.materialAdvance;
+            const advanceList = await ctx.service.advance.getAdvanceList(ctx.tender.id, type, this.decimal, advancePayTotal);
+            const latestOrder = await ctx.service.advance.getLastestAdvance(ctx.tender.id, type, true);
             const progress = await ctx.service.advance.calcProgress(latestOrder, advancePayTotal);
             const showAddBtn = ctx.tender.data.user_id === ctx.session.sessionUser.accountId ? !latestOrder || (latestOrder.status === auditConst.status.checked && latestOrder.prev_total_amount < advancePayTotal) : false;
             const renderData = {
@@ -109,9 +107,21 @@ module.exports = app => {
             return data;
         }
 
-        _checkCanEntry(ctx) {
-            if (ctx.session.sessionUser.accountId !== ctx.advance.uid) {
-                if (ctx.advance.status === auditConst.status.uncheck) {
+        /**
+         * 权限判断-进入详情页
+         * @param {Object} ctx - 全局上下文
+         * @return {void}
+         * @private
+         */
+        async _checkCanEntry(ctx) {
+            if (ctx.advance.status === auditConst.status.uncheck) {
+                if (ctx.session.sessionUser.accountId !== ctx.advance.uid) {
+                    throw '无权访问';
+                }
+            } else {
+                const auditors = await ctx.service.advanceAudit.getAuditorsWithOwner(ctx.advance.id, ctx.advance.times);
+                const cur_uid = ctx.session.sessionUser.accountId;
+                if (auditors.findIndex(item => item.audit_id === cur_uid) === -1) {
                     throw '无权访问';
                 }
             }
@@ -124,18 +134,37 @@ module.exports = app => {
         async detail(ctx) {
             const advancePayTotal = ctx.advance.type === 0 ? ctx.tender.info.deal_param.startAdvance : ctx.tender.info.deal_param.materialAdvance;
             try {
-                this._checkCanEntry(ctx);
-                const renderData = await this._getDefaultRenderData(ctx);
+                await this._checkCanEntry(ctx);
                 const { uncheck, checkNo } = auditConst.status;
                 const { status } = ctx.advance;
+                const isEdited = ctx.session.sessionUser.accountId === ctx.advance.uid && (status === uncheck || status === checkNo);
+                const renderData = await this._getDefaultRenderData(ctx);
                 // 获取上一期预付款记录
                 const prevAdvance = await ctx.service.advance.getPreviousRecord(ctx.tender.id, ctx.advance.type);
                 // 最大支付比例
                 const max_pr = ctx.helper.mul(ctx.helper.div(ctx.helper.sub(advancePayTotal, (prevAdvance && prevAdvance.prev_total_amount || 0)), advancePayTotal, 10), 100);
-                renderData.isEdited = status === uncheck || status === checkNo;
+                // 特殊处理金额的显示(formatMoney)
+                let cur_amount,
+                    prev_total_amount;
+                const s1 = parseFloat(ctx.advance.prev_amount).toString().split('.')[1];
+                const prev_amount = ctx.helper.formatMoney(ctx.advance.prev_amount, ',', s1 && s1.length || 0);
+                if (status === uncheck || status === checkNo) {
+                    cur_amount = parseFloat(ctx.helper.round(ctx.advance.cur_amount, this.decimal)) || 0;
+                    const s2 = parseFloat(ctx.helper.add(cur_amount, ctx.advance.prev_amount)).toString().split('.')[1];
+                    prev_total_amount = ctx.helper.formatMoney(ctx.helper.add(cur_amount, ctx.advance.prev_amount), ',', s2 && s2.length || 0);
+                } else {
+                    cur_amount = ctx.advance.cur_amount;
+                    const s2 = parseFloat(ctx.advance.prev_total_amount).toString().split('.')[1];
+                    prev_total_amount = ctx.helper.formatMoney(ctx.advance.prev_total_amount, ',', s2 && s2.length || 0);
+                }
+
+                renderData.isEdited = isEdited;
                 renderData.advance = ctx.advance;
-                renderData.decimal = this.decimal;
+                renderData.cur_amount = cur_amount;
+                renderData.prev_amount = prev_amount;
+                renderData.prev_total_amount = prev_total_amount;
                 renderData.max_pr = max_pr;
+                renderData.decimal = this.decimal;
                 renderData.advancePayTotal = advancePayTotal;
                 renderData.prevAdvance = prevAdvance;
                 await this.layout('advance/detail.ejs', renderData, 'advance/modal_audit.ejs');

+ 35 - 3
app/controller/change_controller.js

@@ -266,7 +266,7 @@ module.exports = app => {
                 const auditStatus = await ctx.service.changeAudit.getStatusByChange(change);
 
                 // 获取附件列表
-                const attList = await ctx.service.changeAtt.getAllChangeFiles(ctx.params.cid);
+                const attList = await ctx.service.changeAtt.getChangeAttachment(ctx.params.cid);
 
                 // 根据auditStatus获取审批人列表
                 const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
@@ -343,13 +343,15 @@ module.exports = app => {
                             cl.camount,
                             cl.detail,
                             cl.lid,
+                            cl.xmj_code,
+                            cl.xmj_jldy,
                         ];
                         ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, ctx.tender.info.decimal.tp);
                         ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, ctx.tender.info.decimal.tp);
                         if (cl.lid !== '0') {
-                            changeListData.push(cLArray.join(';'));
+                            changeListData.push(cLArray.join('*;*'));
                         } else {
-                            changeWhiteListData.push(cLArray.join(';'));
+                            changeWhiteListData.push(cLArray.join('*;*'));
                         }
                     }
                     renderData.changeListData = changeListData.join('^_^');
@@ -749,6 +751,36 @@ module.exports = app => {
         }
 
         /**
+         * 查看附件
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async checkFile(ctx) {
+            const responseData = { err: 0, msg: '' };
+            const id = parseInt(ctx.params.id);
+            if (id) {
+                try {
+                    const fileInfo = await ctx.service.changeAtt.getDataById(id);
+                    if (fileInfo && Object.keys(fileInfo).length) {
+                        let filepath = fileInfo.filepath;
+                        if (!ctx.helper.canPreview(fileInfo.fileext)) {
+                            filepath = `/change/download/file/${fileInfo.id}`;
+                        } else {
+                            filepath = filepath.replace(/^app|\/app/, '');
+                        }
+                        fileInfo.filepath && (responseData.data = { filepath });
+                    }
+                } catch (error) {
+                    this.log(error);
+                    this.setMessage(error.toString(), this.messageType.ERROR);
+                    responseData.err = 1;
+                    responseData.msg = error.toString();
+                }
+            }
+            ctx.body = responseData;
+        }
+
+        /**
          * 删除变更令
          * @param {Object} ctx - egg全局变量
          * @return {void}

+ 2 - 5
app/controller/ledger_audit_controller.js

@@ -203,13 +203,10 @@ module.exports = app => {
 
                 await ctx.service.ledgerAudit.start(ctx.tender.id, ctx.tender.data.ledger_times);
 
-                // ctx.body = { err: 0, msg: '', data: { url: '/tender/' + ctx.tender.id + '/ledger' } };
-                ctx.redirect('/tender/' + ctx.tender.id + '/ledger');
+                ctx.body = { err: 0, msg: '', data: { url: '/tender/' + ctx.tender.id + '/ledger' } };
             } catch (err) {
                 this.log(err);
-                // ctx.body = this.ajaxErrorBody(err, '上报失败,请刷新页面重试');
-                ctx.session.postError = err.toString();
-                ctx.redirect(ctx.request.header.referer);
+                ctx.body = this.ajaxErrorBody(err, '上报失败,请刷新页面重试');
             }
         }
 

+ 2 - 5
app/controller/revise_controller.js

@@ -843,13 +843,10 @@ module.exports = app => {
                 if (revise.uid !== ctx.session.sessionUser.accountId) throw '上报失败';
 
                 await ctx.service.reviseAudit.start(revise, revise.times);
-                ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
-                // ctx.body = { err: 0, msg: '', data: {} };
+                ctx.body = { err: 0, msg: '', data: {} };
             } catch (err) {
                 this.log(err);
-                // ctx.body = this.ajaxErrorBody(err, '上报失败');
-                this.postError(err, '审批失败');
-                ctx.redirect('/tender/' + ctx.tender.id + '/revise/info');
+                ctx.body = this.ajaxErrorBody(err, '上报失败');
             }
         }
         /**

+ 12 - 1
app/controller/tender_controller.js

@@ -75,10 +75,21 @@ module.exports = app => {
                 //     }
                 // }
                 tenderList.forEach(async t => {
+                    if (t.user_id === this.ctx.session.sessionUser.accountId && (
+                            t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck)) {
+                        const sum = await this.ctx.service.ledger.addUp({ tender_id: t.id/* , is_leaf: true*/ });
+                        t.total_price = sum.total_price;
+                        t.deal_tp = sum.deal_tp;
+                    }
                     t.advance_tp = await this.ctx.service.advance.getSumAdvance(t.id);
 
                     if (t.ledger_status === auditConst.ledger.status.checked) {
                         t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, true);
+                        if (t.lastStage && t.lastStage.status === auditConst.stage.status.uncheck &&
+                            t.lastStage.user_id !== this.ctx.session.sessionUser.accountId) {
+                            t.lastStage = await this.ctx.service.stage.getLastestStage(t.id);
+                        }
+                        if (t.lastStage) await this.ctx.service.stage.checkStageGatherData(t.lastStage);
                         t.completeStage = await this.ctx.service.stage.getLastestCompleteStage(t.id);
                     }
                     if (t.lastStage) {
@@ -447,7 +458,7 @@ module.exports = app => {
                 ctx.body = { err: 0, msg: '', data: JSON.parse(ctx.request.body.data) };
             } catch (err) {
                 this.log(err);
-                ctx.body = { err: 1, msg: err.toString(), data: null };
+                ctx.body = this.ajaxErrorBody(err, '保存标段设置失败');
             }
         }
 

+ 0 - 3
app/middleware/session_auth.js

@@ -47,7 +47,6 @@ module.exports = options => {
             path && (this.curListUrl = path);
 
         } catch (error) {
-            console.log(error);
             if (this.helper.isAjax(this.request)) {
                 return this.body = {
                     err: 2,
@@ -71,8 +70,6 @@ module.exports = options => {
                 message: '登录信息异常,请重新登录',
             };
             return this.redirect('/login?referer=' + this.url);
-
-
         }
         yield next;
     };

+ 35 - 41
app/middleware/tender_check.js

@@ -43,51 +43,38 @@ module.exports = options => {
                 tender.data.ledger_times = 1;
             }
             if (tender.data.project_id !== this.session.sessionProject.id) {
-
                 throw '您无权查看该项目';
-            } else {
-                const accountId = this.session.sessionUser.accountId;
-                const advanceAuditors = yield this.service.advanceAudit.getAllAuditors(tender.id);
-                const advanceAuditorsId = this.helper._.map(advanceAuditors, 'audit_id');
-                if (tender.data.ledger_status === auditConst.status.uncheck) {
-                    if (tender.data.user_id !== accountId && advanceAuditorsId.indexOf(accountId) === -1) {
-                        throw '您无权查看该项目';
-                    } else if (advanceAuditorsId.indexOf(accountId) !== -1) {
-                        if (!(this.url === '/tender/' + this.params.id || this.url.indexOf('/advance') !== -1)) {
-                            throw '您无权查看该内容';
-                        }
-                    }
-                } else {
-                    const times = tender.data.ledger_status === auditConst.status.checkNo ? tender.data.ledger_times - 1 : tender.data.ledger_times;
-                    const auditors = yield this.service.ledgerAudit.getAuditors(tender.id, times);
-                    const auditorsId = this.helper._.map(auditors, 'audit_id');
-                    const stageAuditors = yield this.service.stageAudit.getAllAuditors(tender.id);
-                    const stageAuditorsId = this.helper._.map(stageAuditors, 'aid');
-                    const changeAuditors = yield this.service.changeAudit.getAllAuditors(tender.id);
-                    const changeAuditorsId = this.helper._.map(changeAuditors, 'uid');
-                    const reviseAuditors = yield this.service.reviseAudit.getAllAuditors(tender.id);
-                    const reviseAuditorsId = this.helper._.map(reviseAuditors, 'audit_id');
-                    const materialAuditors = yield this.service.materialAudit.getAllAuditors(tender.id);
-                    const materialAuditorsId = this.helper._.map(materialAuditors, 'aid');
-                    // const advanceAuditors = yield this.service.advanceAudit.getAllAuditors(tender.id);
-                    // const advanceAuditorsId = this.helper._.map(advanceAuditors, 'audit_id');
-                    const tenderPermission = this.session.sessionUser.permission ? this.session.sessionUser.permission.tender : null;
-                    if (auditorsId.indexOf(accountId) === -1 && tender.data.user_id !== accountId &&
-                        (tenderPermission === null || tenderPermission === undefined || tenderPermission.indexOf('2') === -1) &&
-                        stageAuditorsId.indexOf(accountId) === -1 && changeAuditorsId.indexOf(accountId) === -1 &&
-                        reviseAuditorsId.indexOf(accountId) === -1 && materialAuditorsId.indexOf(accountId) === -1 &&
-                        advanceAuditorsId.indexOf(accountId) === -1) {
-                        throw '您无权查看该项目';
-                    }
-                }
             }
+            const accountId = this.session.sessionUser.accountId;
+            const advanceAuditors = yield this.service.advanceAudit.getAllAuditors(tender.id);
+            const advanceAuditorsId = this.helper._.map(advanceAuditors, 'audit_id');
+            const times = tender.data.ledger_status === auditConst.status.checkNo ? tender.data.ledger_times - 1 : tender.data.ledger_times;
+            const auditors = yield this.service.ledgerAudit.getAuditors(tender.id, times);
+            const auditorsId = this.helper._.map(auditors, 'audit_id');
+            const stageAuditors = yield this.service.stageAudit.getAllAuditors(tender.id);
+            const stageAuditorsId = this.helper._.map(stageAuditors, 'aid');
+            const changeAuditors = yield this.service.changeAudit.getAllAuditors(tender.id);
+            const changeAuditorsId = this.helper._.map(changeAuditors, 'uid');
+            const reviseAuditors = yield this.service.reviseAudit.getAllAuditors(tender.id);
+            const reviseAuditorsId = this.helper._.map(reviseAuditors, 'audit_id');
+            const materialAuditors = yield this.service.materialAudit.getAllAuditors(tender.id);
+            const materialAuditorsId = this.helper._.map(materialAuditors, 'aid');
+            const tenderPermission = this.session.sessionUser.permission ? this.session.sessionUser.permission.tender : null;
+            if (auditorsId.indexOf(accountId) === -1 && tender.data.user_id !== accountId &&
+                (tenderPermission === null || tenderPermission === undefined || tenderPermission.indexOf('2') === -1) &&
+                stageAuditorsId.indexOf(accountId) === -1 && changeAuditorsId.indexOf(accountId) === -1 &&
+                reviseAuditorsId.indexOf(accountId) === -1 && materialAuditorsId.indexOf(accountId) === -1 &&
+                advanceAuditorsId.indexOf(accountId) === -1) {
+                throw '您无权查看该项目';
+            }
+
             tender.ledgerReadOnly = this.session.sessionUser.accountId !== tender.data.user_id ||
                 tender.data.ledger_status === auditConst.status.checking || tender.data.ledger_status === auditConst.status.checked;
+            tender.advanceAuditorsId = advanceAuditorsId;
             this.tender = tender;
             this.session.sessionProject.page_show = yield this.service.project.getPageshow(this.session.sessionProject.id);
             yield next;
         } catch (err) {
-            console.log(err);
             // 输出错误到日志
             if (err.stack) {
                 this.logger.error(err);
@@ -104,11 +91,18 @@ module.exports = options => {
                     body: this.session.body,
                 }));
             }
-            // 重定向值标段管理
-            if (this.helper.isWap(this.request)) {
-                this.redirect('/wap/list');
+            if (this.helper.isAjax(this.request)) {
+                if (err.stack) {
+                    this.body = {err: 2, msg: '标段数据未知错误', data: null};
+                } else {
+                    this.body = {err: 1, msg: err.toString(), data: null};
+                }
             } else {
-                err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect('/list');
+                if (this.helper.isWap(this.request)) {
+                    this.redirect('/wap/list');
+                } else {
+                    err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect('/list');
+                }
             }
         }
     };

+ 65 - 0
app/middleware/uncheck_tender_check.js

@@ -0,0 +1,65 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const auditConst = require('../const/audit').ledger;
+const messageType = require('../const/message_type');
+
+module.exports = options => {
+    /**
+     * 标段校验 中间件
+     * 1. 读取标段数据(包括属性)
+     * 2. 检验用户是否可见标段(不校验具体权限)
+     *
+     * @param {function} next - 中间件继续执行的方法
+     * @return {void}
+     */
+    return function* uncheckTenderCheck(next) {
+        try {
+            if (this.tender.data.ledger_status === auditConst.status.uncheck) {
+                if (this.tender.data.user_id !== this.session.sessionUser.accountId && this.tender.advanceAuditorsId.indexOf(this.session.sessionUser.accountId) === -1) {
+                    throw '您无权查看该项目';
+                } else if (this.tender.advanceAuditorsId.indexOf(this.session.sessionUser.accountId) !== -1) {
+                    throw '您无权查看该内容';
+                }
+            }
+            yield next;
+        } catch (err) {
+            // 输出错误到日志
+            if (err.stack) {
+                this.logger.error(err);
+            } else {
+                this.session.message = {
+                    type: messageType.ERROR,
+                    icon: 'exclamation-circle',
+                    message: err,
+                };
+                this.getLogger('fail').info(JSON.stringify({
+                    error: err,
+                    project: this.session.sessionProject,
+                    user: this.session.sessionUser,
+                    body: this.session.body,
+                }));
+            }
+            if (this.helper.isAjax(this.request)) {
+                if (err.stack) {
+                    this.body = {err: 2, msg: '标段数据未知错误', data: null};
+                } else {
+                    this.body = {err: 1, msg: err.toString(), data: null};
+                }
+            } else {
+                if (this.helper.isWap(this.request)) {
+                    this.redirect('/wap/list');
+                } else {
+                    err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect('/list');
+                }
+            }
+        }
+    };
+};

+ 18 - 18
app/public/js/advance.js

@@ -14,24 +14,24 @@ $(document).ready(function () {
         $('#erro').modal('show');
     }
 
-    $('#advance_add').click(function() {
-        postData(`${window.location.pathname}/${type}/create`, {}, res => {
-            const html = `<tr>
-                <td><a href="/tender/${res.tid}/advance/${res.id}/detail" data-id="${res.id}">第${res.order}期</a></td>
-                <td>${res.pay_ratio || 0}%</td>
-                <td class="text-right">${formatMoney((res.cur_amount || 0), ',', decimal)}</td>
-                <td class="text-right">${formatMoney((res.prev_amount || 0), ',', decimal)}</td>
-                <td class="text-right">${formatMoney((res.prev_total_amount || 0),',', decimal)}</td>
-                <td><a class="btn btn-sm" href="#file" data-toggle="modal" data-target="#file"><i class="fa fa-paperclip "></i> 3</a></td>
-                <td>${auditConst.statusString[res.status]}</td>
-                <td><a href="/tender/${res.tid}/advance/${res.id}/detail" class="btn btn-primary btn-sm">编辑</a></td>
-                </tr>`
-            $('#advanceList').prepend(html)
-            $('#advance_add').remove()
-            window.location.href = `${window.location.pathname}/${res.id}/detail`
-        })
-        return false
-    })
+    // $('#advance_add').click(function() {
+    //     postData(`${window.location.pathname}/${type}/create`, {}, res => {
+    //         const html = `<tr>
+    //             <td><a href="/tender/${res.tid}/advance/${res.id}/detail" data-id="${res.id}">第${res.order}期</a></td>
+    //             <td>${res.pay_ratio || 0}%</td>
+    //             <td class="text-right">${formatMoney((res.cur_amount || 0), ',', decimal)}</td>
+    //             <td class="text-right">${formatMoney((res.prev_amount || 0), ',', decimal)}</td>
+    //             <td class="text-right">${formatMoney((res.prev_total_amount || 0),',', decimal)}</td>
+    //             <td><a class="btn btn-sm" href="#file" data-toggle="modal" data-target="#file"><i class="fa fa-paperclip "></i> 3</a></td>
+    //             <td>${auditConst.statusString[res.status]}</td>
+    //             <td><a href="/tender/${res.tid}/advance/${res.id}/detail" class="btn btn-primary btn-sm">编辑</a></td>
+    //             </tr>`
+    //         $('#advanceList').prepend(html)
+    //         $('#advance_add').remove()
+    //         window.location.href = `${window.location.pathname}/${res.id}/detail`
+    //     })
+    //     return false
+    // })
 
     $('#advanceList').on('click', `a[href="#file"]`, function() {
         const { fileList = [] } = advanceList.find(item => item.id === parseInt($(this).data('id')))

+ 8 - 7
app/public/js/advance_audit.js

@@ -18,7 +18,6 @@ $(document).ready(function () {
 
     // 控制上报弹窗的文案
     function checkModal(isHide) {
-        console.log($('#start-modal'))
         $('#start-modal').empty()
         if (isHide) {
             // 隐藏上传按钮
@@ -156,7 +155,7 @@ $(document).ready(function () {
     // 上报审批
     $('#tm-submit').click(function() {
         const pay_ratio = parseFloat($(`.pay-input[data-type=0]`).val())
-        const cur_amount = parseFloat($(`.pay-input[data-type=1]`).val())
+        const cur_amount = parseFloat(parseFloat($(`.pay-input[data-type=1]`).val()).toFixed(decimal))
         if (!pay_ratio || !cur_amount) {
             return toastr.error('请填写本期金额!')
         }
@@ -208,10 +207,11 @@ $(document).ready(function () {
             $(this).val(fixedToSub(val, decimal)) // 重新赋值限制只有两位小数
             const pay_a_input = $(`.pay-input[data-type=${reverse(type)}]`)
             pay_ratio = parseFloat(ZhCalc.mul(ZhCalc.div(val, advancePayTotal), 100).toFixed(2))
-            cur_amount = val
+            cur_amount = ZhCalc.round(val, decimal)
             pay_a_input.val(pay_ratio)
+            const total = parseFloat(ZhCalc.add(cur_amount, p_amount)).toString().split('.')[1]
             // 截止本期金额文案更新
-            $('#p_total2').text(formatMoney(ZhCalc.add(val, p_amount), ',', decimal) + '元')
+            $('#p_total2').text(formatMoney(ZhCalc.add(cur_amount, p_amount), ',', total && total.length || 0) + '元')
         } else {
             if (val.toFixed(1) === max.toFixed(1)) {
                 val = max
@@ -219,11 +219,12 @@ $(document).ready(function () {
             // 支付比例转化
             $(this).val(fixedToSub(val)) // 重新赋值限制只有两位小数
             const cur_m_input = $(`.pay-input[data-type=${reverse(type)}]`)
-            cur_amount = ZhCalc.mul(advancePayTotal, ZhCalc.div(val, 100))
+            cur_amount = ZhCalc.round(ZhCalc.mul(advancePayTotal, ZhCalc.div(val, 100)), decimal)
             pay_ratio = val
-            cur_m_input.val(cur_amount.toFixed(decimal))
+            cur_m_input.val(parseFloat(cur_amount.toFixed(decimal)))
+            const total = parseFloat(ZhCalc.add(cur_amount, p_amount)).toString().split('.')[1]
             // 截止本期金额文案更新
-            $('#p_total2').text(formatMoney(ZhCalc.add(cur_amount, p_amount), ',', decimal) + '元')
+            $('#p_total2').text(formatMoney(ZhCalc.add(cur_amount, p_amount), ',', total && total.length || 0) + '元')
         }
         const data = {
             pay_ratio,

+ 10 - 2
app/public/js/change_detail.js

@@ -81,7 +81,7 @@ $(document).ready(() => {
             for (const fileInfo of data) {
                 html += '<tr> ' +
                     '<td>' + index + '</td> ' +
-                    '<td><a href="/change/download/file/' + fileInfo.id + '">' + fileInfo.filename + fileInfo.fileext + '</a></td> ' +
+                    `<td><a href="javascript: void(0);" class="file-atn" f-id="${fileInfo.id}">${fileInfo.filename}${fileInfo.fileext}</a></td>`+
                     '<td>' + fileInfo.filesize + '</td> ' +
                     '<td>' + fileInfo.in_time + '</td> ' +
                     '<td> <a class="btn btn-light btn-sm delete-file" data-attid="' + fileInfo.id + '"  title="删除附件"><span class="fa fa-trash text-danger"></span></a> </td> ' +
@@ -112,7 +112,15 @@ $(document).ready(() => {
             });
         });
     });
-
+    // /change/download/file/
+    $('#attList').on('click', '.file-atn', function() {
+        const id = $(this).attr('f-id')
+        postData(`/change/download/file/${id}`, {}, (data) => {
+            const { filepath } = data
+            $('#file-upload').attr('href', filepath)
+            $('#file-upload')[0].click()
+        })
+    })
     //
     const cca = getLocalCache('change-checkbox-account-' + accountId);
     if (cca !== null && cca !== undefined) {

+ 39 - 29
app/public/js/change_set.js

@@ -167,7 +167,7 @@ $(document).ready(() => {
                 }
                 changeList.push.apply(changeList, changeWhiteList);
                 for (const [index, cl] of changeList.entries()) {
-                    const clInfo = cl.split(';');
+                    const clInfo = cl.split('*;*');
                     // if (clInfo[0] === '' || clInfo[1] === '' || clInfo[3] === '' || clInfo[4] === '' || clInfo[5] === '') {
                     if (clInfo[0] === '' || clInfo[1] === '' || clInfo[5] === '') {
                         toastr.error('变更清单第' + (index+1) + '行未完整填写数据(变更部位、变更详情、单位、单价可空)');
@@ -363,7 +363,7 @@ $(document).ready(() => {
             for (const leaf of gcl.leafXmjs) {
                 const quantity = leaf.quantity !== undefined && leaf.quantity !== null ? leaf.quantity : 0;
                 const bwmx = leaf.bwmx !== undefined ? leaf.bwmx : '';
-                const isChecked = data_bwmx.indexOf(leaf.code + '_' + (bwmx !== '' ? bwmx : leaf.jldy ? leaf.jldy : '') + ';' + quantity) !== -1 && isCheck ? 'checked' : '';
+                const isChecked = data_bwmx.indexOf(leaf.code + '!_!' + (leaf.jldy ? leaf.jldy : '') + '!_!' + (bwmx !== '' ? bwmx : leaf.jldy ? leaf.jldy : '') + '*;*' + quantity) !== -1 && isCheck ? 'checked' : '';
                 codeHtml += '<tr quantity="' + quantity + '"><td>' + leaf.code + '</td>' +
                     '<td>' + (leaf.jldy ? leaf.jldy: '') + '</td>' +
                     '<td>' + (leaf.dwgc ? leaf.dwgc : '') + '</td>' +
@@ -397,9 +397,9 @@ $(document).ready(() => {
             $('#code-list input:checked').each(function () {
                 const tr = $(this).parents('tr');
                 const length = tr.children('td').length;
-                const bwmx = length === 8 ? tr.children('td').eq(0).text() + '_' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
+                const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!' + tr.children('td').eq(1).text() + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
                 const quantity = tr.attr('quantity');
-                const de_qu = bwmx + ';' + quantity;
+                const de_qu = bwmx + '*;*' + quantity;
                 data_bwmx.push(de_qu);
             });
             data_bwmx = data_bwmx.join('$#$');
@@ -412,9 +412,9 @@ $(document).ready(() => {
                 $('#code-list input:checked').each(function () {
                     const tr = $(this).parents('tr');
                     const length = tr.children('td').length;
-                    const bwmx = length === 8 ? tr.children('td').eq(0).text() + '_' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
+                    const bwmx = length === 8 ? tr.children('td').eq(0).text() + '!_!'+ tr.children('td').eq(1).text() + '!_!' + (tr.children('td').eq(5).text() !== '' ? tr.children('td').eq(5).text() : tr.children('td').eq(1).text()) : '0';
                     const quantity = tr.attr('quantity');
-                    const de_qu = bwmx + ';' + quantity;
+                    const de_qu = bwmx + '*;*' + quantity;
                     data_bwmx.push(de_qu);
                 });
                 data_bwmx = data_bwmx.join('$#$');
@@ -480,6 +480,8 @@ $(document).ready(() => {
     $('body').on('valuechange', '.clist input', function (e, previous) {
         const index = $(this).parents('tr').data('index');
         const lid = $(this).parents('tr').data('lid');
+        const xmj_code = $(this).parents('tr').data('xmjcode') || '';
+        const xmj_jldy = $(this).parents('tr').data('xmjjldy') || '';
         const isWhite = !isNaN(lid) ? true : false;
         const tr = $('#list tr[data-lid="' + lid + '"]').eq(0);
         const site = parseInt($(this).parents('td').data('site'));
@@ -508,12 +510,16 @@ $(document).ready(() => {
         if (isWhite) {
             let changelist = $('#change-whitelist').val().split('^_^');
             trlist.push(0);
-            changelist.splice(index, 1, trlist.join(';'));
+            trlist.push(xmj_code);
+            trlist.push(xmj_jldy);
+            changelist.splice(index, 1, trlist.join('*;*'));
             $('#change-whitelist').val(changelist.join('^_^'));
         } else {
             let changelist = $('#change-list').val().split('^_^');
             trlist.push(lid.split('_')[0]);
-            changelist.splice(index, 1, trlist.join(';'));
+            trlist.push(xmj_code);
+            trlist.push(xmj_jldy);
+            changelist.splice(index, 1, trlist.join('*;*'));
             $('#change-list').val(changelist.join('^_^'));
         }
         tr.children('td[data-site="7"]').text(price != '' && oamount != '' ? roundnum(parseFloat(price).mul(parseFloat(oamount)),totalPriceUnit) : '');
@@ -543,9 +549,9 @@ $(document).ready(() => {
         tr.children('td[data-site="6"]').children('input').attr('onkeyup','RegNum(this,event,'+ numdecimal +')');
         tr.children('td[data-site="8"]').children('input').val(scnum);
         tr.children('td[data-site="8"]').children('input').attr('onkeyup','RegNum(this,event,'+ numdecimal +')');
-        const trlist = [code,name,bwmx,unit,price,oamount,scnum,detail,0];
+        const trlist = [code,name,bwmx,unit,price,oamount,scnum,detail,0,'',''];
         let changelist = $('#change-whitelist').val().split('^_^');
-        changelist.splice(index, 1, trlist.join(';'));
+        changelist.splice(index, 1, trlist.join('*;*'));
         $('#change-whitelist').val(changelist.join('^_^'));
         tr.children('td[data-site="7"]').text(price != '' && oamount != '' ? roundnum(parseFloat(price).mul(parseFloat(oamount)),totalPriceUnit) : '');
         tr.children('td[data-site="9"]').text(price != '' && scnum != '' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),totalPriceUnit) : '');
@@ -635,7 +641,7 @@ function tableDataRemake(changeListData) {
     const changeList = $('#change-list').val().split('^_^');
     if (changeList.length > 0 && changeList[0]) {
         for (const [index,cl] of changeList.entries()) {
-            const clinfo = cl.split(';');
+            const clinfo = cl.split('*;*');
             // const listinfo = changeListData[clinfo[8] - 1];
             let listinfo = changeListData.find(function (item) {
                 return (item.id !== undefined && item.id == clinfo[8]) || (item.id === undefined && item.leafXmjs !== undefined && item.leafXmjs.length !== 0 && item.leafXmjs[0].gcl_id == clinfo[8]);
@@ -653,21 +659,21 @@ function tableDataRemake(changeListData) {
                     continue;
                 }
                 $('#table-list-select tr[data-index="'+ clinfo[8] +'"]').addClass('table-success');
-                let pushbwmx = '0;0';
+                let pushbwmx = '0*;*0';
                 if (listinfo.leafXmjs !== undefined) {
                     const leafInfo = listinfo.leafXmjs.find(function (item) {
                         return (item.bwmx === undefined || item.bwmx === clinfo[2]) && (item.quantity !== null ? item.quantity === parseFloat(clinfo[5]) : 0 === parseFloat(clinfo[5]));
                     });
                     console.log(leafInfo);
                     if (leafInfo) {
-                        pushbwmx = leafInfo.code + '_' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : '') + ';' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                        pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : '') + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                     } else {
                         toastr.warning('台账清单列表已不存在'+ clinfo[0] +',已更新变更清单列表');
                         changeList.splice(index, 1);
                         continue;
                     }
                 } else {
-                    pushbwmx = '0;' + (listinfo.quantity !== null ? listinfo.quantity : 0);
+                    pushbwmx = '0*;*' + (listinfo.quantity !== null ? listinfo.quantity : 0);
                 }
                 const bwmx = $('#table-list-select tr[data-index="'+ clinfo[8] +'"]').attr('data-bwmx');
                 if (bwmx) {
@@ -679,20 +685,20 @@ function tableDataRemake(changeListData) {
                 }
             } else {
                 $('#table-list-select tr[data-lid="'+ clinfo[8] +'"]').addClass('table-success');
-                let pushbwmx = '0;0';
+                let pushbwmx = '0*;*0';
                 if (listinfo.leafXmjs !== undefined) {
                     const leafInfo = listinfo.leafXmjs.find(function (item) {
                         return (item.bwmx === undefined || item.bwmx === clinfo[2] || item.jldy === clinfo[2]) && (item.quantity !== null ? item.quantity === parseFloat(clinfo[5]) : 0 === parseFloat(clinfo[5]));
                     });
                     if (leafInfo) {
-                        pushbwmx = leafInfo.code + '_' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy ? leafInfo.jldy : '')) + ';' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
+                        pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' + (leafInfo.bwmx !== undefined ? leafInfo.bwmx : (leafInfo.jldy ? leafInfo.jldy : '')) + '*;*' + (leafInfo.quantity !== null ? leafInfo.quantity : 0);
                     } else {
                         toastr.warning('台账清单列表已不存在'+ clinfo[0] +',已更新变更清单列表');
                         changeList.splice(index, 1);
                         continue;
                     }
                 } else {
-                    pushbwmx = '0;' + (listinfo.quantity !== null ? listinfo.quantity : 0);
+                    pushbwmx = '0*;*' + (listinfo.quantity !== null ? listinfo.quantity : 0);
                 }
                 const bwmx = $('#table-list-select tr[data-lid="'+ clinfo[8] +'"]').attr('data-bwmx');
                 if (bwmx) {
@@ -834,18 +840,20 @@ function maketablelist(status){
         // 原清单和数量改变
         let data_bwmx = $(this).attr('data-bwmx').split('$#$');
         for (const b of data_bwmx) {
-            const oamount = b.split(';')[1] != '' ? b.split(';')[1] : 0;
-            let bwmx = b.split(';')[0] != 0 ? b.split(';')[0].split('_')[1] : '';
-            let trlist = [code, name, bwmx, unit, price, oamount, scnum, '', lid];
+            const oamount = b.split('*;*')[1] != '' ? b.split('*;*')[1] : 0;
+            let bwmx = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[2] : '';
+            let xmj_code = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[0] : '';
+            let xmj_jldy = b.split('*;*')[0] != 0 ? b.split('*;*')[0].split('!_!')[1] : '';
+            let trlist = [code, name, bwmx, unit, price, oamount, scnum, '', lid, xmj_code, xmj_jldy];
             const radionInfo = radionList.find(function (item) {
-                const info = item.split(';');
+                const info = item.split('*;*');
                 return info[0] === code && (info[8] == lid || parseInt(info[8]) === parseInt(lindex)) && info[2] === bwmx;
             });
             if (radionInfo) {
-                trlist[6] = radionInfo.split(';')[6];
-                trlist[7] = radionInfo.split(';')[7];
+                trlist[6] = radionInfo.split('*;*')[6];
+                trlist[7] = radionInfo.split('*;*')[7];
             }
-            newTableList.push(trlist.join(';'));
+            newTableList.push(trlist.join('*;*'));
         }
     });
     // 排序
@@ -854,7 +862,7 @@ function maketablelist(status){
     let whiteIndex = 0;
     let deteletr = '<td><a class="text-danger">移除</a></td>';
     for (const radion of newTableList) {
-        const radionArray = radion.split(';');
+        const radionArray = radion.split('*;*');
         let code = radionArray[0];
         let name = radionArray[1];
         let bwmx = radionArray[2];
@@ -864,11 +872,13 @@ function maketablelist(status){
         let scnum = radionArray[6];
         let detail = radionArray[7];
         let lid = radionArray[8];
+        let xmj_code = radionArray[9];
+        let xmj_jldy = radionArray[10];
         let sctotal = scnum !== '' && scnum !== '-' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),decimal) : '';
 
         // 根据单位获取数量的位数,并得出
         let numdecimal = findDecimal(unit);
-        html += '<tr class="clist clid" data-lid="' + lid + '_' + index + '" data-index="' + index + '">' +
+        html += '<tr class="clist clid" data-lid="' + lid + '_' + index + '" data-index="' + index + '" data-xmjcode="'+ xmj_code +'" data-xmjjldy="'+ xmj_jldy +'">' +
             '<td data-site="0">'+ code +'</td>' +
             '<td data-site="1">'+ name +'</td>' +
             '<td data-site="2">'+ bwmx +'</td>' +
@@ -888,12 +898,12 @@ function maketablelist(status){
     let radionWhiteList = $('#change-whitelist').val() !== '' ? $('#change-whitelist').val().split('^_^') : [];
     //判断是否添加空白清单
     if(status == 'addwhite'){
-        let trlist = ['','','','','',makedecimalzero(findDecimal(3)),makedecimalzero(findDecimal(3)),'',0];
-        radionWhiteList.push(trlist.join(';'));
+        let trlist = ['','','','','',makedecimalzero(findDecimal(3)),makedecimalzero(findDecimal(3)),'',0, '', ''];
+        radionWhiteList.push(trlist.join('*;*'));
     }
 
     for (const rw of radionWhiteList) {
-        const radionArray = rw.split(';');
+        const radionArray = rw.split('*;*');
         let code = radionArray[0];
         let name = radionArray[1];
         let bwmx = radionArray[2];

+ 102 - 38
app/public/js/ledger.js

@@ -48,6 +48,9 @@ $(document).ready(function() {
         rootId: -1,
         keys: ['id', 'tender_id', 'ledger_id'],
         preUrl: '/tender/' + getTenderId() + '/ledger',
+        //treeCacheKey: 'ledger_bills_fold' + '_' + getTenderId(),
+        markFoldKey: 'bills-fold',
+        markFoldSubKey: window.location.pathname.split('/')[2],
     };
     if (checkTzMeasureType()) {
         treeSetting.calcFields = ['sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price'];
@@ -2190,14 +2193,14 @@ $(document).ready(function() {
                 if (!dealBills) {
                     dealBills = new DealBills('#deal-bills-spread', {
                         cols: [
-                            {title: '清单编号', field: 'code', hAlign: 0, width: 85, formatter: '@', readOnly: true},
-                            {title: '名称', field: 'name', hAlign: 0, width: 150, formatter: '@', readOnly: true},
-                            {title: '单位', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
-                            {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
-                            {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
-                            {title: '金额', field: 'total_price', hAlign: 2, width: 50, readOnly: true},
+                            {title: '清单编号', field: 'code', hAlign: 0, width: 85, formatter: '@'},
+                            {title: '名称', field: 'name', hAlign: 0, width: 150, formatter: '@'},
+                            {title: '单位', field: 'unit', hAlign: 1, width: 50, formatter: '@'},
+                            {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                            {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                            {title: '金额', field: 'total_price', hAlign: 2, width: 50},
                         ],
-                        emptyRows: 0,
+                        emptyRows: 3,
                         headRows: 1,
                         headRowHeight: [32],
                         defaultRowHeight: 21,
@@ -2205,6 +2208,7 @@ $(document).ready(function() {
                         font: '12px 微软雅黑',
                         headColWidth: [0],
                         selectedBackColor: '#fffacd',
+                        readOnly: true,
                     });
                     dealBills.loadData();
                 }
@@ -2260,44 +2264,47 @@ $(document).ready(function() {
             this.url = '/tender/' + getTenderId() + '/deal';
             this.spreadSetting = spreadSetting;
             this.spread = SpreadJsObj.createNewSpread(this.obj);
+            this.sheet = this.spread.getActiveSheet();
             SpreadJsObj.initSheet(this.spread.getActiveSheet(), this.spreadSetting);
             if (!readOnly) {
                 this.spread.bind(spreadNS.Events.CellDoubleClick, function (e, info) {
-                const dealSheet = info.sheet;
-                const mainSheet = ledgerSpread.getActiveSheet();
+                    const dealSheet = info.sheet;
+                    if (!dealSheet.zh_setting.readOnly) return;
 
-                const dealBills = SpreadJsObj.getSelectObject(dealSheet);
-                if (!dealBills) { return; }
-                const mainTree = mainSheet.zh_tree;
-                const mainNode = SpreadJsObj.getSelectObject(mainSheet);
-                if (!mainNode || !mainTree) { return; }
+                    const mainSheet = ledgerSpread.getActiveSheet();
 
-                if (mainNode.code && mainNode.code !== '' && !mainTree.isLeafXmj(mainNode)) {
-                    toastr.error('非最底层项目下,不应添加清单');
-                    return;
-                }
+                    const dealBills = SpreadJsObj.getSelectObject(dealSheet);
+                    if (!dealBills) { return; }
+                    const mainTree = mainSheet.zh_tree;
+                    const mainNode = SpreadJsObj.getSelectObject(mainSheet);
+                    if (!mainNode || !mainTree) { return; }
 
-                postData(window.location.pathname + '/update', {
-                    postType: 'add-deal',
-                    postData: {
-                        id: mainNode.ledger_id,
-                        type: mainNode.code ? 'child' : 'next',
-                        dealBills: {
-                            b_code: dealBills.code, name: dealBills.name, unit: dealBills.unit,
-                            unit_price: dealBills.unit_price,
-                        }
-                    },
-                }, function (result) {
-                    const refreshData = mainTree.loadPostData(result);
-                    treeOperationObj.refreshTree(mainSheet, refreshData);
-                    const sel = mainSheet.getSelections()[0];
-                    mainSheet.setSelection(refreshData.create[0].index, sel.col, sel.rowCount, sel.colCount);
-                    SpreadJsObj.reloadRowsBackColor(mainSheet, [sel.row, refreshData.create[0].index]);
-                    treeOperationObj.refreshOperationValid(mainSheet);
-                    ledgerSpread.focus();
-                    posOperationObj.loadCurPosData();
+                    if (mainNode.code && mainNode.code !== '' && !mainTree.isLeafXmj(mainNode)) {
+                        toastr.error('非最底层项目下,不应添加清单');
+                        return;
+                    }
+
+                    postData(window.location.pathname + '/update', {
+                        postType: 'add-deal',
+                        postData: {
+                            id: mainNode.ledger_id,
+                            type: mainNode.code ? 'child' : 'next',
+                            dealBills: {
+                                b_code: dealBills.code, name: dealBills.name, unit: dealBills.unit,
+                                unit_price: dealBills.unit_price,
+                            }
+                        },
+                    }, function (result) {
+                        const refreshData = mainTree.loadPostData(result);
+                        treeOperationObj.refreshTree(mainSheet, refreshData);
+                        const sel = mainSheet.getSelections()[0];
+                        mainSheet.setSelection(refreshData.create[0].index, sel.col, sel.rowCount, sel.colCount);
+                        SpreadJsObj.reloadRowsBackColor(mainSheet, [sel.row, refreshData.create[0].index]);
+                        treeOperationObj.refreshOperationValid(mainSheet);
+                        ledgerSpread.focus();
+                        posOperationObj.loadCurPosData();
+                    });
                 });
-            });
             }
             $('#upload-deal-bills').click(function () {
                     const file = $('#deal-bills-file')[0];
@@ -2319,6 +2326,43 @@ $(document).ready(function() {
                         return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
                     },
                     items: {
+                        edit: {
+                            name: '进入编辑模式',
+                            icon: 'fa-edit',
+                            visible: function (key, opt) {
+                                return self.sheet.zh_setting.readOnly;
+                            },
+                            callback: function (key, opt) {
+                                self.sheet.zh_setting.readOnly = false;
+                                SpreadJsObj.refreshSheetReadOnly(self.sheet);
+                            },
+                        },
+                        read: {
+                            name: '退出编辑模式',
+                            icon: 'fa-sign-out',
+                            visible: function (key, opt) {
+                                return !self.sheet.zh_setting.readOnly;
+                            },
+                            callback: function (key, opt) {
+                                self.sheet.zh_setting.readOnly = true;
+                                SpreadJsObj.refreshSheetReadOnly(self.sheet);
+                            },
+                        },
+                        del: {
+                            name: '删除',
+                            icon: 'fa-times',
+                            visible: function (key, opt) {
+                                return !self.sheet.zh_setting.readOnly;
+                            },
+                            disabled: function (key, opt) {
+                                const select = SpreadJsObj.getSelectObject(self.sheet);
+                                return !select;
+                            },
+                            callback: function (key, opt) {
+
+                            },
+                        },
+                        sprEdit: '---------',
                         apply: {
                             name: '应用全部清单单价至台账',
                             icon: 'fa-magic',
@@ -2948,6 +2992,26 @@ $(document).ready(function() {
         ledgerTree: ledgerTree,
         ledgerPos: pos,
         checkList: checkList,
+        decimal: tenderInfo.decimal,
+        checkOption: {
+            sibling: { enable: 1 },
+            empty_code: { enable: 1 },
+            calc: {
+                enable: 1,
+                fields: ['sgfh_qty', 'qtcl_qty', 'sjcl_qty', 'quantity'],
+            },
+            zero: { enable: 1 },
+            tp: {
+                enable: 1,
+                fields: [
+                    {qty: 'sgfh_qty', tp: 'sgfh_tp'},
+                    {qty: 'sjcl_qty', tp: 'sjcl_tp'},
+                    {qty: 'qtcl_qty', tp: 'qtcl_tp'},
+                    {qty: 'quantity', tp: 'total_price'},
+                    {qty: 'deal_qty', tp: 'deal_tp'},
+                ],
+            },
+        }
     });
 });
 

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

@@ -28,6 +28,8 @@ $(document).ready(() => {
         rootId: -1,
         keys: ['id', 'tender_id', 'ledger_id'],
         preUrl: '/ledger',
+        markFoldKey: 'bills-fold',
+        markFoldSubKey: window.location.pathname.split('/')[2],
     };
     if (checkTzMeasureType()) {
         treeSetting.calcFields = ['sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price'];

File diff suppressed because it is too large
+ 7 - 0
app/public/js/local-forage/localforage.min.js


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

@@ -144,6 +144,8 @@ $(document).ready(() => {
         masterId: 'id',
         minorId: 'lid',
         calcFields: [],
+        markFoldKey: 'bills-fold',
+        markFoldSubKey: window.location.pathname.split('/')[2],
     });
     const cPos = new MasterPosData({
         id: 'id', ledgerId: 'lid', masterId: 'id', minorId: 'pid',

+ 20 - 0
app/public/js/measure_stage.js

@@ -212,3 +212,23 @@ function checkValidForm() {
     $('#hide-all').show();
     return true;
 }
+$(window).resize(checkTableWidth);
+function checkTableWidth() {
+    if($('table th').eq(2).outerWidth() < 107) {
+        $('table th').eq(2).html('本期<br>合同计量');
+        $('table th').eq(3).html('本期数量<br>变更计量');
+        $('table th').eq(4).html('本期<br>完成计量');
+        $('table th').eq(5).html('截止上期<br>完成计量');
+        $('table th').eq(6).html('截止本期<br>完成计量');
+    } else {
+        $('table th').eq(2).html('本期合同计量');
+        $('table th').eq(3).html('本期数量变更计量');
+        $('table th').eq(4).html('本期完成计量');
+        $('table th').eq(5).html('截止上期完成计量');
+        $('table th').eq(6).html('截止本期完成计量');
+    }
+}
+
+$(function () {
+    checkTableWidth();
+});

+ 69 - 24
app/public/js/path_tree.js

@@ -263,9 +263,10 @@ const createNewPathTree = function (type, setting) {
          * 构造函数
          */
         constructor(setting) {
+            const self = this;
             // 无索引
             this.datas = [];
-            // 以key为索引
+            // 以key为索引indexedDB
             this.items = {};
             // 以排序为索引
             this.nodes = [];
@@ -273,6 +274,18 @@ const createNewPathTree = function (type, setting) {
             this.children = [];
             // 树设置
             this.setting = setting;
+
+            if (this.setting.markFoldKey) {
+                 const markStr = getLocalCache(this.setting.markFoldKey);
+                 const markData = markStr ? markStr.split('|') : ['', ''];
+                 this.markFold = markData[0] === this.setting.markFoldSubKey && markData[1]
+                     ? _.map(markData[1].split(','), _.toInteger) : [];
+            }
+            // if (this.setting.treeCacheKey) {
+            //     localforage.getItem(this.setting.treeCacheKey).then(function (v) {
+            //         self.markFold = v && v.markFold ? v.markFold : [];
+            //     });
+            // }
         }
         /**
          * 树结构根据显示排序
@@ -309,6 +322,7 @@ const createNewPathTree = function (type, setting) {
          * @param datas
          */
         loadDatas(datas) {
+            self = this;
             // 清空旧数据
             this.items = {};
             this.nodes = [];
@@ -342,6 +356,9 @@ const createNewPathTree = function (type, setting) {
             });
             this.sortTreeNode(true);
             if (this.setting.autoExpand >= 0) this.expandByLevel(this.setting.autoExpand);
+            if (this.setting.markFoldKey) this.expandByCustom(function (node) {
+                return self.markFold.indexOf(node[self.setting.id]) === -1;
+            });
         }
 
         getItemsByIndex(index) {
@@ -487,6 +504,49 @@ const createNewPathTree = function (type, setting) {
             const siblings = this.getChildren(this.getParent(node));
             return (siblings && siblings.length > 0) ? node.order === siblings[siblings.length - 1].order : false;
         };
+
+        /**
+         * 提取节点key和索引数据
+         * @param {Object} node - 节点
+         * @returns {key}
+         */
+        getNodeKeyData(node) {
+            const data = {};
+            for (const key of this.setting.keys) {
+                data[key] = node[key];
+            }
+            return data;
+        };
+        /**
+         * 得到树结构构成id
+         * @param node
+         * @returns {*}
+         */
+        getNodeKey(node) {
+            return node[this.setting.id];
+        };
+
+        _markFold(node) {
+            if (!this.setting.markFoldKey || !this.setting.markFoldSubKey) return;
+            // if (!this.setting.treeCacheKey) return;
+
+            if (!node.expanded) {
+                if (this.markFold.indexOf(node[this.setting.id]) === -1) this.markFold.push(node[this.setting.id]);
+            } else {
+                if (this.markFold.indexOf(node[this.setting.id]) >= 0) this.markFold.splice(this.markFold.indexOf(node[this.setting.id]), 1);
+            }
+        }
+        _saveMarkFold() {
+            if (this.setting.markFoldKey && this.setting.markFoldSubKey) {
+                setLocalCache(this.setting.markFoldKey, this.setting.markFoldSubKey + '|' + this.markFold.join(','));
+            }
+            // if (this.setting.treeCacheKey) {
+            //     localforage.setItem(this.setting.treeCacheKey, {
+            //         markFold: this.markFold,
+            //         time: new Date(),
+            //     });
+            // }
+        }
         /**
          * 刷新子节点是否可见
          * @param {Object} node
@@ -510,30 +570,10 @@ const createNewPathTree = function (type, setting) {
          */
         setExpanded(node, expanded) {
             node.expanded = expanded;
+            this._markFold(node);
             this._refreshChildrenVisible(node);
+            this._saveMarkFold();
         };
-
-        /**
-         * 提取节点key和索引数据
-         * @param {Object} node - 节点
-         * @returns {key}
-         */
-        getNodeKeyData(node) {
-            const data = {};
-            for (const key of this.setting.keys) {
-                data[key] = node[key];
-            }
-            return data;
-        };
-        /**
-         * 得到树结构构成id
-         * @param node
-         * @returns {*}
-         */
-        getNodeKey(node) {
-            return node[this.setting.id];
-        };
-
         /**
          * 递归 设置节点展开状态
          * @param {Array} nodes - 需要设置状态的节点
@@ -543,7 +583,11 @@ const createNewPathTree = function (type, setting) {
          */
         _recursiveExpand(nodes, parent, checkFun) {
             for (const node of nodes) {
-                node.expanded = checkFun(node);
+                const expanded = checkFun(node);
+                if (node.expanded !== expanded) {
+                    node.expanded = expanded;
+                    this._markFold(node);
+                }
                 node.visible = parent ? (parent.expanded && parent.visible) : true;
                 this._recursiveExpand(node.children, node, checkFun);
             }
@@ -554,6 +598,7 @@ const createNewPathTree = function (type, setting) {
          */
         expandByCustom(checkFun) {
             this._recursiveExpand(this.children, null, checkFun);
+            this._saveMarkFold();
         }
         /**
          * 展开到第几层

+ 29 - 0
app/public/js/revise.js

@@ -2231,6 +2231,12 @@ $(document).ready(() => {
             if (searchLedger) {
                 searchLedger.spread.refresh();
             }
+            if (errorList) {
+                errorList.spread.refresh();
+            }
+            if (checkList) {
+                checkList.spread.refresh();
+            }
         }
     });
     $.subMenu({
@@ -2266,6 +2272,9 @@ $(document).ready(() => {
             if (searchLedger) {
                 searchLedger.spread.refresh();
             }
+            if (errorList) {
+                errorList.spread.refresh();
+            }
             if (checkList) {
                 checkList.spread.refresh();
             }
@@ -2519,6 +2528,26 @@ $(document).ready(() => {
         ledgerTree: billsTree,
         ledgerPos: pos,
         checkList: checkList,
+        decimal: decimal,
+        checkOption: {
+            sibling: { enable: 1 },
+            empty_code: { enable: 1 },
+            calc: {
+                enable: 1,
+                fields: ['sgfh_qty', 'qtcl_qty', 'sjcl_qty', 'quantity'],
+            },
+            zero: { enable: 1 },
+            tp: {
+                enable: 1,
+                fields: [
+                    {qty: 'sgfh_qty', tp: 'sgfh_tp'},
+                    {qty: 'sjcl_qty', tp: 'sjcl_tp'},
+                    {qty: 'qtcl_qty', tp: 'qtcl_tp'},
+                    {qty: 'quantity', tp: 'total_price'},
+                    {qty: 'deal_qty', tp: 'deal_tp'},
+                ],
+            },
+        }
     });
 
     $('[name=revise-start]').submit(function (e) {

+ 12 - 0
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -981,6 +981,18 @@ const SpreadJsObj = {
             }
         }
     },
+    refreshSheetReadOnly: function (sheet) {
+        this.beginMassOperation(sheet);
+        if (sheet.zh_setting) {
+            sheet.zh_setting.cols.forEach(function (col, i) {
+                for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
+                    sheet.getCell(iRow, i).locked(col.readOnly || sheet.zh_setting.readOnly || false);
+                }
+                //sheet.getRange(-1, i, -1, 1, GC.Spread.Sheets.SheetArea.viewport).locked(col.readOnly || sheet.zh_setting.readOnly || false);
+            });
+        }
+        this.endMassOperation(sheet);
+    },
     /**
      * 刷新列是否只读
      * @param sheet

+ 77 - 14
app/public/js/stage.js

@@ -163,6 +163,8 @@ $(document).ready(() => {
         rootId: -1,
         keys: ['id', 'tender_id', 'ledger_id'],
         stageId: 'id',
+        markFoldKey: 'bills-fold',
+        markFoldSubKey: window.location.pathname.split('/')[2],
     };
     // 台账树结构计算相关设置
     stageTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr'];
@@ -593,6 +595,22 @@ $(document).ready(() => {
         },
     });
 
+    const checkList = $.ledger_checkList({
+        id: 'check-list',
+        tabSelector: '#check-list-tab',
+        selector: '#check-list',
+        relaSpread: slSpread,
+        storeKey: 'stage-check-' + window.location.pathname.split('/')[2] + '-' + window.location.pathname.split('/')[4],
+        checkType: ledgerCheckType,
+        afterLocated:  function () {
+            stagePosSpreadObj.loadCurPosData();
+        },
+        afterShow: function () {
+            slSpread.refresh();
+            if (spSpread) spSpread.refresh();
+        },
+    });
+
     const stageTreeSpreadObj = {
         loadExprToInput(sheet) {
             const sel = sheet.getSelections()[0];
@@ -1577,6 +1595,7 @@ $(document).ready(() => {
         stageIm.init(stage, imType, tenderInfo.decimal);
         stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.changeData);
         errorList.loadHisErrorData();
+        checkList.loadHisCheckData();
     }, null, true);
     spSpread.bind(spreadNS.Events.EditEnded, stagePosSpreadObj.editEnded);
     spSpread.bind(spreadNS.Events.ClipboardPasting, stagePosSpreadObj.clipboardPasting);
@@ -1714,6 +1733,9 @@ $(document).ready(() => {
             if (errorList && errorList.spread) {
                 errorList.spread.refresh();
             }
+            if (checkList) {
+                checkList.spread.refresh();
+            }
         }
     });
 
@@ -1896,6 +1918,9 @@ $(document).ready(() => {
             if (errorList && errorList.spread) {
                 errorList.spread.refresh();
             }
+            if (checkList) {
+                checkList.spread.refresh();
+            }
             window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
         }
     });
@@ -3043,6 +3068,9 @@ $(document).ready(() => {
             if (tab.attr('content') === '#error-list') {
                 errorList.spread.refresh();
             }
+            if (tab.attr('content') === '#check-list') {
+                checkList.spread.refresh();
+            }
         } else {
             tab.removeClass('active');
             tabPanel.removeClass('active');
@@ -3119,8 +3147,8 @@ $(document).ready(() => {
             $('#show-att tr').eq(0).children('td').text(att.filename + att.fileext);
             const name = att.code !== null && att.code !== '' ? att.code : (att.b_code !== null ? att.b_code : '');
             $('#show-att tr').eq(1).children('td').text($.trim(name + ' ' + att.lname));
-            // $('#show-att tr').eq(2).find('a').attr('href', '/tender/' + tender.id + '/measure/stage/' + stage.order + '/download/file/' + att.id);
-            $('#show-att tr').eq(2).find('a').attr('href', att.filepath);
+            $('#show-att tr').eq(2).find('a').attr('href', '/tender/' + tender.id + '/measure/stage/' + stage.order + '/download/file/' + att.id);
+            // $('#show-att tr').eq(2).find('a').attr('href', att.filepath);
             $('#show-att tr').eq(3).children('td').eq(0).text(att.username);
             $('#show-att tr').eq(3).children('td').eq(1).text(att.in_time);
             $('#show-att tr').eq(4).children('td').text(att.remark);
@@ -3244,9 +3272,11 @@ $(document).ready(() => {
         } else if (content === 'view') {
             const data = {id: fid};
             postData('/tender/' + tender.id + '/measure/stage/' + stage.order + '/check/file', data, function (result) {
-              const { filepath } = result
-              $('#show-att tr').eq(2).find('a').attr('href', filepath)
-              $('#show-att tr').eq(2).find('a').children('span').eq(0).trigger('click')
+                const { filepath } = result
+                $('#load-file').attr('href', filepath);
+                $('#load-file')[0].click();
+                // $('#show-att tr').eq(2).find('a').attr('href', filepath)
+              // $('#show-att tr').eq(2).find('a').children('span').eq(0).trigger('click')
             });
         } else if (content === 'location') {
             const att = attData.find(item => item.id === parseInt(fid));
@@ -3329,6 +3359,32 @@ $(document).ready(() => {
         });
     })('a[name=showLevel]', slSpread.getActiveSheet());
 
+    LedgerChecker({
+        ledgerTree: stageTree,
+        ledgerPos: stagePos,
+        checkList: checkList,
+        decimal: tenderInfo.decimal,
+        checkOption: {
+            sibling: { enable: 0 },
+            empty_code: { enable: 0 },
+            calc: {
+                enable: 1,
+                fields: ['contract_qty', 'qc_qty'],
+            },
+            zero: { enable: 0 },
+            tp: {
+                enable: 1,
+                fields: [
+                    {qty: 'contract_qty', tp: 'contract_tp'},
+                    {qty: 'qc_qty', tp: 'qc_tp'},
+                ],
+                filter: function (node) {
+                    return node.is_tp;
+                }
+            },
+        }
+    });
+
     const dataChecker = DataChecker({
         checkUrl: window.location.pathname + '/check',
         completeData: function (data) {
@@ -3351,22 +3407,29 @@ $(document).ready(() => {
         return false;
     });
     $('#audit-check0').submit(function (e) {
-        $(this).parent().parent().modal('hide');
+        const checkType = parseInt($('[name=checkType]').val());
         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()),
+            opinion: $(`${'#sp-done'}`).find('[name=opinion]').val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType,
         };
-        dataChecker.checkAndPost(this.action, data);
+        $('#sp-done').modal('hide');
+        checkType && dataChecker.checkAndPost(this.action, data);
         $('#hide-all').hide();
         return false;
     });
-    $('#audit-check2').submit(function (e) {
-        $(this).parent().parent().modal('hide');
+    $('#audit-check1').submit(function (e) {
+        const checkType = parseInt($('[name=checkType]:checked').val());
         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()),
+            opinion: $(`${'#sp-back'}`).find('[name=opinion]').val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType,
         };
-        dataChecker.checkAndPost(this.action, data);
+        if ($('#warning-text').length) $('#warning-text').remove()
+        if (!checkType && !$('#warning-text').length) {
+            $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+            return false
+        }
+        $('#sp-back').modal('hide');
+        checkType && dataChecker.checkAndPost(this.action, data);
         $('#hide-all').hide();
         return false;
     });

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

@@ -470,14 +470,12 @@ $(document).ready(() => {
             if (text) {
                 const num = _.toNumber(text);
                 if (num) {
-                    data.tp = num;
-                    data.expr = null;
+                    data.expr = num;
                 } else {
                     const expr = $.trim(text).replace('\t', '').replace('=', '').toLowerCase();
                     const [valid, msg] = this._checkExprValid(expr);
                     if (!valid) return [valid, msg];
                     data.expr = expr;
-                    data.tp = null;
                 }
             } else {
                 data.tp = null;

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

@@ -342,6 +342,7 @@ function bindTenderUrl() {
             return t.id === tenderId;
         });
         if (!tender) return;
+        if (!tender.measure_type && tender.user_id !== userID) return;
         if (tender.measure_type) {
             // window.location.href = '/tender/' + tenderId;
             window.open('/tender/' + tenderId, '_blank');

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

@@ -403,6 +403,8 @@ function bindTenderUrl() {
         const tender = _.find(tenders, function (t) {
             return t.id === tenderId;
         });
+        if (!tender) return;
+        if (!tender.measure_type && tender.user_id !== userID) return;
         if (tender.measure_type) {
             // window.location.href = '/tender/' + tenderId;
             window.open('/tender/' + tenderId, '_blank');

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

@@ -333,6 +333,8 @@ function bindTenderUrl() {
         const tender = _.find(tenders, function (t) {
             return t.id === tenderId;
         });
+        if (!tender) return;
+        if (!tender.measure_type && tender.user_id !== userID) return;
         if (tender.measure_type) {
             // window.location.href = '/tender/' + tenderId;
             window.open('/tender/' + tenderId, '_blank');

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

@@ -381,6 +381,8 @@ function bindTenderUrl() {
         const tender = _.find(tenders, function (t) {
             return t.id === tenderId;
         });
+        if (!tender) return;
+        if (!tender.measure_type && tender.user_id !== userID) return;
         if (tender.measure_type) {
             // window.location.href = '/tender/' + tenderId;
             window.open('/tender/' + tenderId, '_blank');

+ 135 - 133
app/router.js

@@ -9,6 +9,7 @@ module.exports = app => {
     const projectManagerCheck = app.middlewares.projectManagerCheck();
     // 标段读取中间件
     const tenderCheck = app.middlewares.tenderCheck();
+    const uncheckTenderCheck = app.middlewares.uncheckTenderCheck();
     // 期读取中间件
     const stageCheck = app.middlewares.stageCheck();
     // 材料调差读取中间件
@@ -127,156 +128,156 @@ module.exports = app => {
     app.get('/tender/:id/cooperation', sessionAuth, tenderCheck, 'tenderController.tenderCooperation');
 
     // 台账管理相关
-    app.get('/tender/:id/ledger', sessionAuth, tenderCheck, 'ledgerController.explode');
-    app.post('/tender/:id/ledger/load', sessionAuth, tenderCheck, 'ledgerController.loadExplodeData');
-    app.post('/tender/:id/ledger/get-children', sessionAuth, tenderCheck, 'ledgerController.getChildren');
-    app.post('/tender/:id/ledger/update', sessionAuth, tenderCheck, 'ledgerController.update');
-    app.post('/tender/:id/ledger/upload-excel/:ueType', sessionAuth, tenderCheck, 'ledgerController.uploadExcel');
-    app.get('/tender/:id/ledger/download/:file', sessionAuth, tenderCheck, 'ledgerController.download');
-    app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, 'ledgerController.posUpdate');
-    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/check', sessionAuth, tenderCheck, 'ledgerController.check');
+    app.get('/tender/:id/ledger', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.explode');
+    app.post('/tender/:id/ledger/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.loadExplodeData');
+    app.post('/tender/:id/ledger/get-children', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.getChildren');
+    app.post('/tender/:id/ledger/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.update');
+    app.post('/tender/:id/ledger/upload-excel/:ueType', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.uploadExcel');
+    app.get('/tender/:id/ledger/download/:file', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.download');
+    app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.posUpdate');
+    app.post('/tender/:id/pos/paste', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.posPaste');
+    app.post('/tender/:id/ledger/deal2sgfh', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.deal2sgfh');
+    app.post('/tender/:id/ledger/check', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.check');
 
     // 台账审批相关
-    app.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/delete', sessionAuth, tenderCheck, 'ledgerAuditController.remove');
-    app.post('/tender/:id/ledger/audit/start', sessionAuth, tenderCheck, 'ledgerAuditController.start');
-    app.post('/tender/:id/ledger/audit/check', sessionAuth, tenderCheck, 'ledgerAuditController.check');
+    app.get('/tender/:id/ledger/audit', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.index');
+    app.post('/tender/:id/ledger/audit/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.add');
+    app.post('/tender/:id/ledger/audit/delete', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.remove');
+    app.post('/tender/:id/ledger/audit/start', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.start');
+    app.post('/tender/:id/ledger/audit/check', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.check');
 
     // 部位台账
-    app.get('/tender/:id/ledger/bwtz', sessionAuth, tenderCheck, 'ledgerController.bwtz');
-    app.post('/tender/:id/ledger/bwtz/load', sessionAuth, tenderCheck, 'ledgerController.loadBwtz');
+    app.get('/tender/:id/ledger/bwtz', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.bwtz');
+    app.post('/tender/:id/ledger/bwtz/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.loadBwtz');
 
     // 台账对比
-    app.get('/tender/:id/ledger/gather', sessionAuth, tenderCheck, 'ledgerController.gather');
-    app.post('/tender/:id/ledger/gather/load', sessionAuth, tenderCheck, 'ledgerController.loadGatherData');
+    app.get('/tender/:id/ledger/gather', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.gather');
+    app.post('/tender/:id/ledger/gather/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerController.loadGatherData');
 
     // 台账修订
-    app.get('/tender/:id/revise', sessionAuth, tenderCheck, 'reviseController.index');
-    app.post('/tender/:id/revise/add', sessionAuth, tenderCheck, 'reviseController.add');
-    app.post('/tender/:id/revise/cancel', sessionAuth, tenderCheck, 'reviseController.cancel');
-    app.post('/tender/:id/revise/save', sessionAuth, tenderCheck, 'reviseController.save');
-    // app.post('/tender/:id/revise/deal2sgfh', sessionAuth, tenderCheck, 'reviseController.deal2sgfh');
+    app.get('/tender/:id/revise', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.index');
+    app.post('/tender/:id/revise/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.add');
+    app.post('/tender/:id/revise/cancel', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.cancel');
+    app.post('/tender/:id/revise/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.save');
+    // app.post('/tender/:id/revise/deal2sgfh', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.deal2sgfh');
 
     // 台账修订页面
-    app.get('/tender/:id/revise/info', sessionAuth, tenderCheck, 'reviseController.info');
-    app.post('/tender/:id/revise/auditors', sessionAuth, tenderCheck, 'reviseController.reviseAuditors');
-    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/upload-excel/:ueType', sessionAuth, tenderCheck, 'reviseController.uploadExcel');
-    app.post('/tender/:id/revise/info/check', sessionAuth, tenderCheck, 'reviseController.checkData');
+    app.get('/tender/:id/revise/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.info');
+    app.post('/tender/:id/revise/auditors', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.reviseAuditors');
+    app.post('/tender/:id/revise/info/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.loadInfoData');
+    app.post('/tender/:id/revise/info/update', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.update');
+    app.post('/tender/:id/revise/info/upload-excel/:ueType', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.uploadExcel');
+    app.post('/tender/:id/revise/info/check', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.checkData');
 
     // 查看修订数据
-    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/info', sessionAuth, tenderCheck, 'reviseController.historyInfo');
+    app.get('/tender/:id/revise/history', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.history');
+    app.post('/tender/:id/revise/history/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.loadHistoryData');
+    app.post('/tender/:id/revise/history/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.historyInfo');
 
     // 修订审批
-    app.post('/tender/:id/revise/audit/add', sessionAuth, tenderCheck, 'reviseController.addAuditor');
-    app.post('/tender/:id/revise/audit/remove', sessionAuth, tenderCheck, 'reviseController.removeAuditor');
-    app.post('/tender/:id/revise/audit/start', sessionAuth, tenderCheck, 'reviseController.start');
-    app.post('/tender/:id/revise/audit/check', sessionAuth, tenderCheck, 'reviseController.check');
+    app.post('/tender/:id/revise/audit/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.addAuditor');
+    app.post('/tender/:id/revise/audit/remove', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.removeAuditor');
+    app.post('/tender/:id/revise/audit/start', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.start');
+    app.post('/tender/:id/revise/audit/check', sessionAuth, tenderCheck, uncheckTenderCheck, 'reviseController.check');
 
     // 签约清单
-    app.post('/tender/:id/deal/get-data', sessionAuth, tenderCheck, 'dealBillsController.getData');
-    app.post('/tender/:id/deal/upload-excel', sessionAuth, tenderCheck, 'dealBillsController.loadExcel');
-    app.get('/tender/:id/deal/download/:file', sessionAuth, tenderCheck, 'dealBillsController.download');
+    app.post('/tender/:id/deal/get-data', sessionAuth, tenderCheck, uncheckTenderCheck, 'dealBillsController.getData');
+    app.post('/tender/:id/deal/upload-excel', sessionAuth, tenderCheck, uncheckTenderCheck, 'dealBillsController.loadExcel');
+    app.get('/tender/:id/deal/download/:file', sessionAuth, tenderCheck, uncheckTenderCheck, 'dealBillsController.download');
 
     // 计量台账
     // 期计量
-    app.get('/tender/:id/measure/stage', sessionAuth, tenderCheck, 'measureController.stage');
-    app.post('/tender/:id/measure/stage/auditors', sessionAuth, tenderCheck, 'measureController.stageAuditors');
-    app.post('/tender/:id/measure/add', sessionAuth, tenderCheck, 'measureController.add');
-    app.post('/tender/:id/measure/save', sessionAuth, tenderCheck, 'measureController.save');
-    app.post('/tender/:id/measure/stage/delete', sessionAuth, tenderCheck, 'measureController.delete');
+    app.get('/tender/:id/measure/stage', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.stage');
+    app.post('/tender/:id/measure/stage/auditors', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.stageAuditors');
+    app.post('/tender/:id/measure/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.add');
+    app.post('/tender/:id/measure/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.save');
+    app.post('/tender/:id/measure/stage/delete', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.delete');
 
     // 计量台账 -- 清单汇总
-    app.get('/tender/:id/measure/gather', sessionAuth, tenderCheck, 'measureController.gather');
+    app.get('/tender/:id/measure/gather', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.gather');
 
     // 计量台账 -- 审核比较
-    app.get('/tender/:id/measure/compare', sessionAuth, tenderCheck, 'measureController.compare');
-    app.post('/tender/:id/measure/compare/load', sessionAuth, tenderCheck, 'measureController.loadCompareData');
+    app.get('/tender/:id/measure/compare', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.compare');
+    app.post('/tender/:id/measure/compare/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'measureController.loadCompareData');
 
     // 期计量详细
     // 本期计量台账
-    app.get('/tender/:id/measure/stage/:order', sessionAuth, tenderCheck, stageCheck, 'stageController.index');
-    app.post('/tender/:id/measure/stage/:order/load', sessionAuth, tenderCheck, stageCheck, 'stageController.getStageData');
-    app.post('/tender/:id/measure/stage/:order/pos', sessionAuth, tenderCheck, stageCheck, 'stageController.getStagePosData');
-    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/use-change', sessionAuth, tenderCheck, stageCheck, 'stageController.useChange');
-    app.post('/tender/:id/measure/stage/:order/check', sessionAuth, tenderCheck, stageCheck, 'stageController.check');
+    app.get('/tender/:id/measure/stage/:order', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.index');
+    app.post('/tender/:id/measure/stage/:order/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.getStageData');
+    app.post('/tender/:id/measure/stage/:order/pos', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.getStagePosData');
+    app.post('/tender/:id/measure/stage/:order/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.updateStageData');
+    app.post('/tender/:id/measure/stage/:order/valid-change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.searchValidChange');
+    app.post('/tender/:id/measure/stage/:order/use-change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.useChange');
+    app.post('/tender/:id/measure/stage/:order/check', sessionAuth, tenderCheck, uncheckTenderCheck, 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, uncheckTenderCheck, stageCheck, 'stageController.uploadFile');
     app.get('/tender/:id/measure/stage/:order/download/file/:fid', sessionAuth, 'stageController.downloadFile');
-    app.post('/tender/:id/measure/stage/:order/delete/file', sessionAuth, tenderCheck, stageCheck, 'stageController.deleteFile');
-    app.post('/tender/:id/measure/stage/:order/save/file', sessionAuth, tenderCheck, stageCheck, 'stageController.saveFile');
-    app.post('/tender/:id/measure/stage/:order/check/file', sessionAuth, tenderCheck, stageCheck, 'stageController.checkFile');
+    app.post('/tender/:id/measure/stage/:order/delete/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.deleteFile');
+    app.post('/tender/:id/measure/stage/:order/save/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.saveFile');
+    app.post('/tender/:id/measure/stage/:order/check/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.checkFile');
 
     // 中间计量
-    app.get('/tender/:id/measure/stage/:order/detail', sessionAuth, tenderCheck, stageCheck, 'stageController.detail');
-    app.post('/tender/:id/measure/stage/:order/detail/build', sessionAuth, tenderCheck, stageCheck, 'stageController.buildDetailData');
-    app.post('/tender/:id/measure/stage/:order/detail/adv', sessionAuth, tenderCheck, stageCheck, 'stageController.setAdvancedConfig');
-    app.post('/tender/:id/measure/stage/:order/detail/load', sessionAuth, tenderCheck, stageCheck, 'stageController.loadDetailRelaData');
-    app.post('/tender/:id/measure/stage/:order/detail/save', sessionAuth, tenderCheck, stageCheck, 'stageController.saveDetailData');
-    app.post('/tender/:id/measure/stage/:order/detail/add-img', sessionAuth, tenderCheck, stageCheck, 'stageController.addCalcImage');
-    app.post('/tender/:id/measure/stage/:order/detail/merge-img', sessionAuth, tenderCheck, stageCheck, 'stageController.mergeCalcImage');
+    app.get('/tender/:id/measure/stage/:order/detail', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.detail');
+    app.post('/tender/:id/measure/stage/:order/detail/build', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.buildDetailData');
+    app.post('/tender/:id/measure/stage/:order/detail/adv', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.setAdvancedConfig');
+    app.post('/tender/:id/measure/stage/:order/detail/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.loadDetailRelaData');
+    app.post('/tender/:id/measure/stage/:order/detail/save', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.saveDetailData');
+    app.post('/tender/:id/measure/stage/:order/detail/add-img', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.addCalcImage');
+    app.post('/tender/:id/measure/stage/:order/detail/merge-img', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.mergeCalcImage');
 
     // 合同支付
-    app.get('/tender/:id/measure/stage/:order/pay', sessionAuth, tenderCheck, stageCheck, 'stageController.pay');
-    app.post('/tender/:id/measure/stage/:order/pay/detail', sessionAuth, tenderCheck, stageCheck, 'stageController.chapterDetail');
-    app.post('/tender/:id/measure/stage/:order/pay/save', sessionAuth, tenderCheck, stageCheck, 'stageController.savePayData');
-    app.post('/tender/:id/measure/stage/:order/pay/upload/file', sessionAuth, tenderCheck, stageCheck, 'stageController.payUploadFile');
+    app.get('/tender/:id/measure/stage/:order/pay', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.pay');
+    app.post('/tender/:id/measure/stage/:order/pay/detail', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.chapterDetail');
+    app.post('/tender/:id/measure/stage/:order/pay/save', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.savePayData');
+    app.post('/tender/:id/measure/stage/:order/pay/upload/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.payUploadFile');
     app.get('/tender/:id/measure/stage/:order/pay/download/file/:pid/:index', sessionAuth, 'stageController.payDownloadFile');
-    app.post('/tender/:id/measure/stage/:order/pay/delete/file', sessionAuth, tenderCheck, stageCheck, 'stageController.payDeleteFile');
+    app.post('/tender/:id/measure/stage/:order/pay/delete/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.payDeleteFile');
 
     // 变更概况
-    app.get('/tender/:id/measure/stage/:order/change', sessionAuth, tenderCheck, stageCheck, 'stageController.change');
-    app.post('/tender/:id/measure/stage/:order/change/data', sessionAuth, tenderCheck, stageCheck, 'stageController.getChangeData');
-    app.post('/tender/:id/measure/stage/:order/change/detail', sessionAuth, tenderCheck, stageCheck, 'stageController.changeDetail');
+    app.get('/tender/:id/measure/stage/:order/change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.change');
+    app.post('/tender/:id/measure/stage/:order/change/data', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.getChangeData');
+    app.post('/tender/:id/measure/stage/:order/change/detail', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.changeDetail');
 
     // 审批
-    app.post('/tender/:id/measure/stage/:order/audit/add', sessionAuth, tenderCheck, stageCheck, 'stageController.addAudit');
-    app.post('/tender/:id/measure/stage/:order/audit/delete', sessionAuth, tenderCheck, stageCheck, 'stageController.deleteAudit');
-    app.post('/tender/:id/measure/stage/:order/audit/start', sessionAuth, tenderCheck, stageCheck, 'stageController.startAudit');
-    app.post('/tender/:id/measure/stage/:order/audit/check', sessionAuth, tenderCheck, stageCheck, 'stageController.checkAudit');
-    app.get('/tender/:id/measure/stage/:order/audit/check/again', sessionAuth, tenderCheck, stageCheck, 'stageController.checkAuditAgain');
+    app.post('/tender/:id/measure/stage/:order/audit/add', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.addAudit');
+    app.post('/tender/:id/measure/stage/:order/audit/delete', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.deleteAudit');
+    app.post('/tender/:id/measure/stage/:order/audit/start', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.startAudit');
+    app.post('/tender/:id/measure/stage/:order/audit/check', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.checkAudit');
+    app.get('/tender/:id/measure/stage/:order/audit/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.checkAuditAgain');
 
     // 部位台账
-    app.get('/tender/:id/measure/stage/:order/bwtz', sessionAuth, tenderCheck, stageCheck, 'stageController.bwtz');
-    app.post('/tender/:id/measure/stage/:order/bwtz/load', sessionAuth, tenderCheck, stageCheck, 'stageController.loadBwtz');
+    app.get('/tender/:id/measure/stage/:order/bwtz', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.bwtz');
+    app.post('/tender/:id/measure/stage/:order/bwtz/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.loadBwtz');
 
     // 清单汇总
-    app.get('/tender/:id/measure/stage/:order/gather', sessionAuth, tenderCheck, stageCheck, 'stageController.gather');
+    app.get('/tender/:id/measure/stage/:order/gather', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.gather');
 
     // 审核比较
-    app.get('/tender/:id/measure/stage/:order/compare', sessionAuth, tenderCheck, stageCheck, 'stageController.compare');
-    app.post('/tender/:id/measure/stage/:order/compare/load', sessionAuth, tenderCheck, stageCheck, 'stageController.compareAuditor');
+    app.get('/tender/:id/measure/stage/:order/compare', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.compare');
+    app.post('/tender/:id/measure/stage/:order/compare/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.compareAuditor');
 
     // 附加功能
-    app.get('/tender/:id/measure/stage/:order/extra/jgcl', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.jgcl');
-    app.post('/tender/:id/measure/stage/:order/extra/jgcl/load', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.loadJgcl');
-    app.post('/tender/:id/measure/stage/:order/extra/jgcl/update', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.updateJgcl');
-    app.get('/tender/:id/measure/stage/:order/extra/bonus', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.bonus');
-    app.post('/tender/:id/measure/stage/:order/extra/bonus/load', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.loadBonus');
-    app.post('/tender/:id/measure/stage/:order/extra/bonus/update', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.updateBonus');
-    app.get('/tender/:id/measure/stage/:order/extra/other', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.other');
-    app.post('/tender/:id/measure/stage/:order/extra/other/load', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.loadOther');
-    app.post('/tender/:id/measure/stage/:order/extra/other/update', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.updateOther');
-    app.post('/tender/:id/measure/stage/:order/extra/upload/file', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.uploadFile');
-    app.get('/tender/:id/measure/stage/:order/extra/download/file', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.downloadFile');
-    app.post('/tender/:id/measure/stage/:order/extra/delete/file', sessionAuth, tenderCheck, stageCheck, 'stageExtraController.deleteFile');
+    app.get('/tender/:id/measure/stage/:order/extra/jgcl', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.jgcl');
+    app.post('/tender/:id/measure/stage/:order/extra/jgcl/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadJgcl');
+    app.post('/tender/:id/measure/stage/:order/extra/jgcl/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateJgcl');
+    app.get('/tender/:id/measure/stage/:order/extra/bonus', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.bonus');
+    app.post('/tender/:id/measure/stage/:order/extra/bonus/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadBonus');
+    app.post('/tender/:id/measure/stage/:order/extra/bonus/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateBonus');
+    app.get('/tender/:id/measure/stage/:order/extra/other', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.other');
+    app.post('/tender/:id/measure/stage/:order/extra/other/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadOther');
+    app.post('/tender/:id/measure/stage/:order/extra/other/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateOther');
+    app.post('/tender/:id/measure/stage/:order/extra/upload/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.uploadFile');
+    app.get('/tender/:id/measure/stage/:order/extra/download/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.downloadFile');
+    app.post('/tender/:id/measure/stage/:order/extra/delete/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.deleteFile');
 
     // 期审批管理
-    app.get('/tender/:id/measure/stage/:order/manager', sessionAuth, tenderCheck, stageCheck, 'stageController.manager');
-    app.post('/tender/:id/measure/stage/:order/manager/audit/delete', sessionAuth, tenderCheck, stageCheck, 'stageController.managerAuditDelete');
+    app.get('/tender/:id/measure/stage/:order/manager', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.manager');
+    app.post('/tender/:id/measure/stage/:order/manager/audit/delete', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.managerAuditDelete');
 
     // 报表
-    app.get('/tender/:id/report', sessionAuth, tenderCheck, 'reportController.index');
-    app.get('/tender/:id/measure/stage/:order/report', sessionAuth, tenderCheck, stageCheck, 'reportController.index');
+    app.get('/tender/:id/report', sessionAuth, tenderCheck, uncheckTenderCheck, 'reportController.index');
+    app.get('/tender/:id/measure/stage/:order/report', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'reportController.index');
     app.get('/printReport/:size', sessionAuth, 'reportController.showPrintPage');
     app.post('/tender/report_api/getReport', sessionAuth, 'reportController.getReport');
     app.post('/tender/report_api/getMultiReports', sessionAuth, 'reportController.getMultiReportsEx');
@@ -292,52 +293,53 @@ module.exports = app => {
     app.post('/report/cDefine', sessionAuth, 'reportController.setCustomDefine');
 
     // 变更管理
-    app.get('/tender/:id/change', sessionAuth, tenderCheck, 'changeController.index');
-    app.get('/tender/:id/change/status/:status', sessionAuth, tenderCheck, 'changeController.status');
-    app.post('/tender/:id/change/newCode', sessionAuth, tenderCheck, 'changeController.newCode');
-    app.post('/tender/:id/change/add', sessionAuth, tenderCheck, 'changeController.add');
-    app.post('/tender/:id/change/defaultBills', sessionAuth, tenderCheck, 'changeController.defaultBills');
-    app.get('/tender/:id/change/:cid/info', sessionAuth, tenderCheck, 'changeController.info');
+    app.get('/tender/:id/change', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.index');
+    app.get('/tender/:id/change/status/:status', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.status');
+    app.post('/tender/:id/change/newCode', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.newCode');
+    app.post('/tender/:id/change/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.add');
+    app.post('/tender/:id/change/defaultBills', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.defaultBills');
+    app.get('/tender/:id/change/:cid/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.info');
     app.post('/change/upload/file', sessionAuth, 'changeController.uploadFile');
     app.get('/change/download/file/:id', sessionAuth, 'changeController.downloadFile');
+    app.post('/change/download/file/:id', sessionAuth, 'changeController.checkFile');
     app.post('/change/delete/file', sessionAuth, 'changeController.deleteFile');
-    app.post('/tender/:id/change/delete', sessionAuth, tenderCheck, 'changeController.delete');
-    app.post('/tender/:id/change/bills', sessionAuth, tenderCheck, 'changeController.bills');
+    app.post('/tender/:id/change/delete', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.delete');
+    app.post('/tender/:id/change/bills', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.bills');
 
-    app.post('/tender/:id/change/save', sessionAuth, tenderCheck, 'changeController.save');
+    app.post('/tender/:id/change/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.save');
 
-    app.post('/tender/:id/change/approval', sessionAuth, tenderCheck, 'changeController.approval');
-    app.post('/tender/:id/change/check/again', sessionAuth, tenderCheck, 'changeController.checkAgain');
+    app.post('/tender/:id/change/approval', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.approval');
+    app.post('/tender/:id/change/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.checkAgain');
 
-    app.post('/tender/:id/change/:cid/check/codeRepeat', sessionAuth, tenderCheck, 'changeController.checkCodeRepeat');
+    app.post('/tender/:id/change/:cid/check/codeRepeat', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.checkCodeRepeat');
 
     // 变更单位管理
     app.post('/change/update/company', sessionAuth, 'changeController.updateCompany');
 
     // 材料调差
-    app.get('/tender/:id/measure/material', sessionAuth, tenderCheck, 'materialController.index');
-    app.post('/tender/:id/measure/material/add', sessionAuth, tenderCheck, 'materialController.add');
-    app.post('/tender/:id/measure/material/delete', sessionAuth, tenderCheck, 'materialController.delete');
-    app.post('/tender/:id/measure/material/auditors', sessionAuth, tenderCheck, 'materialController.materialAuditors');
+    app.get('/tender/:id/measure/material', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.index');
+    app.post('/tender/:id/measure/material/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.add');
+    app.post('/tender/:id/measure/material/delete', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.delete');
+    app.post('/tender/:id/measure/material/auditors', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.materialAuditors');
     // 审批
-    app.post('/tender/:id/measure/material/:order/audit/add', sessionAuth, tenderCheck, materialCheck, 'materialController.addAudit');
-    app.post('/tender/:id/measure/material/:order/audit/delete', sessionAuth, tenderCheck, materialCheck, 'materialController.deleteAudit');
-    app.post('/tender/:id/measure/material/:order/audit/start', sessionAuth, tenderCheck, materialCheck, 'materialController.startAudit');
-    app.post('/tender/:id/measure/material/:order/audit/check', sessionAuth, tenderCheck, materialCheck, 'materialController.checkAudit');
+    app.post('/tender/:id/measure/material/:order/audit/add', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.addAudit');
+    app.post('/tender/:id/measure/material/:order/audit/delete', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.deleteAudit');
+    app.post('/tender/:id/measure/material/:order/audit/start', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.startAudit');
+    app.post('/tender/:id/measure/material/:order/audit/check', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.checkAudit');
     // 调差工料
-    app.get('/tender/:id/measure/material/:order', sessionAuth, tenderCheck, materialCheck, 'materialController.info');
-    app.post('/tender/:id/measure/material/:order/save', sessionAuth, tenderCheck, materialCheck, 'materialController.saveBillsData');
+    app.get('/tender/:id/measure/material/:order', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.info');
+    app.post('/tender/:id/measure/material/:order/save', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.saveBillsData');
     // 月信息价
-    app.post('/tender/:id/measure/material/:order/month/save', sessionAuth, tenderCheck, materialCheck, 'materialController.saveMonth');
+    app.post('/tender/:id/measure/material/:order/month/save', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.saveMonth');
     // 调差清单
-    app.get('/tender/:id/measure/material/:order/list', sessionAuth, tenderCheck, materialCheck, 'materialController.list');
-    app.post('/tender/:id/measure/material/:order/list/save', sessionAuth, tenderCheck, materialCheck, 'materialController.saveListsData');
+    app.get('/tender/:id/measure/material/:order/list', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.list');
+    app.post('/tender/:id/measure/material/:order/list/save', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.saveListsData');
 
     // 附件
-    app.get('/tender/:id/measure/material/:order/file', sessionAuth, tenderCheck, materialCheck, 'materialController.file');
-    app.post('/tender/:id/measure/material/:order/file/upload', sessionAuth, tenderCheck, materialCheck, 'materialController.upload');
-    app.get('/tender/:id/measure/material/:order/file/:fid/download', sessionAuth, tenderCheck, 'materialController.downloadFile');
-    app.post('/tender/:id/measure/material/:order/file/find', sessionAuth, tenderCheck, materialCheck, 'materialController.getCurMatericalFiles');
+    app.get('/tender/:id/measure/material/:order/file', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.file');
+    app.post('/tender/:id/measure/material/:order/file/upload', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.upload');
+    app.get('/tender/:id/measure/material/:order/file/:fid/download', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.downloadFile');
+    app.post('/tender/:id/measure/material/:order/file/find', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.getCurMatericalFiles');
     app.post('/tender/measure/material/file/delete', sessionAuth, 'materialController.deleteFile');
 
     // 个人账号相关
@@ -384,10 +386,10 @@ module.exports = app => {
     app.get('/wap/logout', 'wapController.logout');
     app.get('/wap/dashboard', sessionAuth, 'wapController.dashboard');
     app.get('/wap/list', sessionAuth, 'wapController.list');
-    app.get('/wap/tender/:id', sessionAuth, tenderCheck, 'wapController.tender');
-    app.get('/wap/tender/:id/stage/:order', sessionAuth, tenderCheck, 'wapController.stage');
-    app.get('/wap/tender/:id/change/:cid/info', sessionAuth, tenderCheck, 'wapController.change');
-    app.post('/wap/tender/:id/change/approval', sessionAuth, tenderCheck, 'wapController.changeApproval');
+    app.get('/wap/tender/:id', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.tender');
+    app.get('/wap/tender/:id/stage/:order', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.stage');
+    app.get('/wap/tender/:id/change/:cid/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.change');
+    app.post('/wap/tender/:id/change/approval', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.changeApproval');
 
     // 微信
     app.get('/wx', 'wechatController.index');

+ 24 - 5
app/service/advance.js

@@ -10,10 +10,12 @@ module.exports = app => {
         }
         /**
          * 获取预付款列表
-         * @param {Number} tid 标段id
-         * @param {Number} type 预付款类型
+         * @param {Number} tid - 标段id
+         * @param {Number} type - 预付款类型
+         * @param {Number} decimal - 小数位数
+         * @param {Number} advancePayTotal - 预付款总额
          */
-        async getAdvanceList(tid, type) {
+        async getAdvanceList(tid, type, decimal, advancePayTotal) {
             this.initSqlBuilder();
             this.sqlBuilder.setAndWhere('tid', {
                 value: tid,
@@ -33,6 +35,23 @@ module.exports = app => {
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
             const advance = await this.db.query(sql, sqlParam);
             for (const item of advance) {
+                let s1,
+                    s3;
+                const s2 = item.prev_amount.toString().split('.')[1];
+                item.pay_ratio = this.ctx.helper.mul(this.ctx.helper.div(item.cur_amount, advancePayTotal), 100, 2) || 0;
+                if (item.status === auditConst.status.uncheck || item.status === auditConst.status.checkNo) {
+                    const cur_amount = item.cur_amount && this.ctx.helper.round(item.cur_amount, decimal) || 0;
+                    s1 = parseFloat(cur_amount).toString().split('.')[1];
+                    s3 = parseFloat(this.ctx.helper.add(cur_amount, item.prev_amount)).toString().split('.')[1];
+                    item.cur_amount = this.ctx.helper.formatMoney(cur_amount, ',', s1 && s1.length || 0);
+                    item.prev_total_amount = this.ctx.helper.formatMoney(this.ctx.helper.add(cur_amount, item.prev_amount), ',', s3 && s3.length || 0);
+                } else {
+                    s1 = item.cur_amount && item.cur_amount.toString().split('.')[1];
+                    s3 = item.prev_total_amount.toString().split('.')[1];
+                    item.cur_amount = this.ctx.helper.formatMoney(item.cur_amount, ',', s1 && s1.length || 0);
+                    item.prev_total_amount = this.ctx.helper.formatMoney(item.prev_total_amount, ',', s3 && s3.length || 0);
+                }
+                item.prev_amount = this.ctx.helper.formatMoney(item.prev_amount, ',', s2 && s2.length || 0);
                 item.curAuditor = await this.ctx.service.advanceAudit.getAuditorByStatus(item.id, item.status, item.times);
                 if (item.status === auditConst.status.checkNoPre) {
                     item.curAuditor2 = await this.ctx.service.advanceAudit.getAuditorByStatus(item.id, auditConst.status.checking);
@@ -90,8 +109,8 @@ module.exports = app => {
             if (!latestOrder) {
                 latestOrder = {
                     order: 1,
-                    prev_amount: 0.00,
-                    prev_total_amount: 0.00,
+                    prev_amount: 0,
+                    prev_total_amount: 0,
                 };
             } else {
                 latestOrder.order = latestOrder.order + 1;

+ 3 - 1
app/service/change.js

@@ -441,7 +441,7 @@ module.exports = app => {
                 let total_price = 0;
                 if (changeList.length > 0) {
                     for (const cl of changeList) {
-                        const clInfo = cl.split(';');
+                        const clInfo = cl.split('*;*');
                         const clArray = {
                             tid: tenderId,
                             cid: changeInfo.cid,
@@ -456,6 +456,8 @@ module.exports = app => {
                             samount: '',
                             detail: clInfo[7],
                             spamount: clInfo[6],
+                            xmj_code: clInfo[9] !== '' ? clInfo[9] : null,
+                            xmj_jldy: clInfo[10] !== '' ? clInfo[10] : null,
                         };
                         if (clInfo[4] === '') {
                             delete clArray.unit_price;

+ 1 - 1
app/service/login_logging.js

@@ -37,7 +37,7 @@ module.exports = app => {
          */
         async addLoginLog() {
             const { ctx } = this;
-            const ip = ctx.header['x-real-ip'] ? ctx.header['x-real-ip'] : '';
+            const ip = ctx.request.ip ? ctx.request.ip : '';
             const ipInfo = await this.getIpInfoFromApi(ip);
             const parser = new UAParser(ctx.header['user-agent']);
             const osInfo = parser.getOS();

+ 10 - 2
app/service/stage_bonus.js

@@ -72,6 +72,10 @@ module.exports = app => {
         }
 
         async _addDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
             const datas = data instanceof Array ? data : [data];
             const insertData = [];
             for (const d of datas) {
@@ -87,7 +91,7 @@ module.exports = app => {
                     order: d.order,
                 };
                 nd.b_type = d.b_type ? d.b_type : null;
-                nd.tp = d.tp ? this.ctx.helper.round(d.to, this.ctx.tender.info.decimal.tp) : 0;
+                nd.tp = d.tp ? this.ctx.helper.round(d.tp, tpDecimal) : 0;
                 nd.code = d.code ? d.code: null;
                 nd.proof = d.proof ? d.proof : null;
                 nd.real_time = d.real_time ? d.real_time : null;
@@ -112,6 +116,10 @@ module.exports = app => {
         }
 
         async _updateDatas (data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
             const datas = data instanceof Array ? data : [data];
             const orgDatas = await this.getAllDataByCondition({sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id')});
 
@@ -123,7 +131,7 @@ module.exports = app => {
                 const nd = {id: od.id};
                 if (d.name !== undefined) nd.name = d.name;
                 if (d.b_type !== undefined) nd.b_type = d.b_type;
-                if (d.tp !== undefined) nd.tp = this.ctx.helper.round(d.tp, this.ctx.tender.info.decimal.tp);
+                if (d.tp !== undefined) nd.tp = this.ctx.helper.round(d.tp, tpDecimal);
                 if (d.code !== undefined) nd.code = d.code;
                 if (d.proof !== undefined) nd.proof = d.proof;
                 if (d.proof_file !== undefined) nd.proof_file = JSON.stringify(d.proof_file);

+ 14 - 6
app/service/stage_jgcl.js

@@ -71,6 +71,10 @@ module.exports = app => {
         }
 
         async _addDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
             const datas = data instanceof Array ? data : [data];
             const insertData = [];
             for (const d of datas) {
@@ -88,11 +92,11 @@ module.exports = app => {
                 const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, d.unit_price);
                 if (d.arrive_qty) {
                     nd.arrive_qty = this.ctx.helper.round(d.arrive_qty, precision.value);
-                    nd.arrive_tp = this.ctx.helper.mul(nd.unit_price, nd.arrive_qty, this.ctx.tender.info.decimal.tp);
+                    nd.arrive_tp = this.ctx.helper.mul(nd.unit_price, nd.arrive_qty, tpDecimal);
                 }
                 if (d.deduct_qty) {
                     nd.deduct_qty = this.ctx.helper.round(d.deduct_qty, precision.value);
-                    nd.deduct_tp = this.ctx.helper.mul(nd.unit_price, nd.deduct_qty, this.ctx.tender.info.decimal.tp);
+                    nd.deduct_tp = this.ctx.helper.mul(nd.unit_price, nd.deduct_qty, tpDecimal);
                 }
                 if (d.source) nd.source = d.source;
                 if (d.bills_code) nd.bills_code = d.bills_code;
@@ -117,6 +121,10 @@ module.exports = app => {
         }
 
         async _updateDatas (data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
             const datas = data instanceof Array ? data : [data];
             const orgDatas = await this.getAllDataByCondition({sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id')});
             const info = this.ctx.tender.info;
@@ -137,15 +145,15 @@ module.exports = app => {
                 const precision = this.ctx.helper.findPrecision(info.precision, d.unit_price);
                 if (d.arrive_qty !== undefined) {
                     nd.arrive_qty = this.ctx.helper.round(d.arrive_qty, precision.value);
-                    nd.arrive_tp = this.ctx.helper.mul(nd.unit_price, nd.arrive_qty, info.decimal.tp);
+                    nd.arrive_tp = this.ctx.helper.mul(nd.unit_price, nd.arrive_qty, tpDecimal);
                 } else if (d.unit_price !== undefined) {
-                    nd.arrive_tp = this.ctx.helper.mul(nd.unit_price, od.arrive_qty, info.decimal.tp);
+                    nd.arrive_tp = this.ctx.helper.mul(nd.unit_price, od.arrive_qty, tpDecimal);
                 }
                 if (d.deduct_qty !== undefined) {
                     nd.deduct_qty = this.ctx.helper.round(d.deduct_qty, precision.value);
-                    nd.deduct_tp = this.ctx.helper.mul(nd.unit_price, nd.deduct_qty, info.decimal.tp);
+                    nd.deduct_tp = this.ctx.helper.mul(nd.unit_price, nd.deduct_qty, tpDecimal);
                 } else if (d.unit_price !== undefined) {
-                    nd.deduct_tp = this.ctx.helper.mul(nd.unit_price, od.deduct_qty, info.decimal.tp);
+                    nd.deduct_tp = this.ctx.helper.mul(nd.unit_price, od.deduct_qty, tpDecimal);
                 }
                 if (d.source !== undefined) nd.source = d.source;
                 if (d.bills_code !== undefined) nd.bills_code = d.bills_code;

+ 12 - 4
app/service/stage_other.js

@@ -59,6 +59,10 @@ module.exports = app => {
         }
 
         async _addDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
             const datas = data instanceof Array ? data : [data];
             const insertData = [];
             for (const d of datas) {
@@ -76,8 +80,8 @@ module.exports = app => {
                 nd.order = d.order;
 
                 if (d.o_type) nd.o_type = d.o_type;
-                if (d.total_price) nd.total_price = this.ctx.helper.round(d.total_price, this.ctx.tender.info.decimal.tp);
-                if (d.tp) nd.tp = this.ctx.helper.round(d.tp, this.ctx.tender.info.decimal.tp);
+                if (d.total_price) nd.total_price = this.ctx.helper.round(d.total_price, tpDecimal);
+                if (d.tp) nd.tp = this.ctx.helper.round(d.tp, tpDecimal);
                 if (d.real_time) nd.real_time = d.real_time;
                 if (d.memo) nd.memo = d.memo;
                 insertData.push(nd);
@@ -99,6 +103,10 @@ module.exports = app => {
         }
 
         async _updateDatas (data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
             const datas = data instanceof Array ? data : [data];
             const orgDatas = await this.getAllDataByCondition({sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id')});
 
@@ -116,9 +124,9 @@ module.exports = app => {
                 if (d.o_type !== undefined) nd.o_type = d.o_type;
                 if (d.total_price !== undefined) {
                     if (od.pre_used) throw '往期已使用,不可修改金额';
-                    nd.total_price = this.ctx.helper.round(d.total_price, this.ctx.tender.info.decimal.tp);
+                    nd.total_price = this.ctx.helper.round(d.total_price, tpDecimal);
                 }
-                if (d.tp !== undefined) nd.tp = this.ctx.helper.round(d.tp, this.ctx.tender.info.decimal.tp);
+                if (d.tp !== undefined) nd.tp = this.ctx.helper.round(d.tp, tpDecimal);
                 if (d.real_time !== undefined) nd.real_time = new Date(d.real_time);
                 if (d.memo !== undefined) nd.memo = d.memo;
                 uDatas.push(nd);

+ 26 - 2
app/service/tender_info.js

@@ -12,7 +12,7 @@ const infoConst = require('../const/tender_info');
 const parseInfo = infoConst.parseInfo;
 const arrayInfo = infoConst.arrayInfo;
 const defaultInfo = infoConst.defaultInfo;
-
+const advanceConst = require('../const/audit').advance;
 module.exports = app => {
 
     class TenderInfo extends app.BaseService {
@@ -202,8 +202,10 @@ module.exports = app => {
 
         async saveDecimal(tenderId, newDecimal, oldDecimal) {
             const changeBills = [],
+                changeAdvanceBills = [],
                 calcUp = newDecimal.up < oldDecimal.up,
-                calcTp = newDecimal.tp !== oldDecimal.tp;
+                calcTp = newDecimal.tp !== oldDecimal.tp,
+                caclPayTp = (newDecimal.pay ? newDecimal.payTp : newDecimal.tp) < (oldDecimal.pay ? oldDecimal.payTp : oldDecimal.tp);
             if (calcUp || calcTp) {
                 const bills = await this.ctx.service.ledger.getAllDataByCondition({
                     columns: ['id', 'unit_price', 'sgfh_qty', 'sjcl_qty', 'qtcl_qty', 'deal_qty', 'quantity'],
@@ -220,12 +222,30 @@ module.exports = app => {
                     changeBills.push(cb);
                 }
             }
+            if (caclPayTp) {
+                // 获取预付款需要修改的相关记录
+                const ad_bills = await this.ctx.service.advance.getAllDataByCondition({
+                    columns: ['id', 'cur_amount', 'prev_amount', 'prev_total_amount'],
+                    where: { status: [advanceConst.status.uncheck, advanceConst.status.checkNo], tid: tenderId },
+                });
+                const decimal = newDecimal.pay ? newDecimal.payTp : newDecimal.tp;
+                // 根据精度重新计算相关金额
+                for (const ad of ad_bills) {
+                    const cb = { id: ad.id };
+                    const cur_amount = this.ctx.helper.round(ad.cur_amount, decimal);
+                    cb.cur_amount = cur_amount;
+                    cb.prev_total_amount = this.ctx.helper.add(cur_amount, ad.prev_amount);
+                    changeAdvanceBills.push(cb);
+                }
+            }
             if (changeBills.length > 0) {
                 const transaction = await this.db.beginTransaction();
                 try {
                     await transaction.update(this.tableName,
                         { decimal: JSON.stringify(newDecimal) }, { where: { tid: tenderId } });
                     await transaction.updateRows(this.ctx.service.ledger.tableName, changeBills);
+
+                    // await transaction.updateRows(this.ctx.service.advance.tableName, changeAdvanceBills);
                     await transaction.commit();
                 } catch (error) {
                     await transaction.rollback();
@@ -235,6 +255,10 @@ module.exports = app => {
                 await this.db.update(this.tableName,
                     { decimal: JSON.stringify(newDecimal) }, { where: { tid: tenderId } });
             }
+            // 更新预付款记录
+            if (changeAdvanceBills.length) {
+                await this.db.updateRows(this.ctx.service.advance.tableName, changeAdvanceBills);
+            }
         }
     }
 

+ 9 - 9
app/view/advance/detail.ejs

@@ -22,7 +22,7 @@
                         <thead>
                             <tr>
                                 <th colspan="4" class="text-center">
-                                    签约<%- advance.type === auditConst.type.start ? '开工' : '材料' %>预付款:<%- ctx.helper.formatMoney(advancePayTotal) %>
+                                    签约<%- advance.type === auditConst.type.start ? '开工' : '材料' %>预付款:<%- ctx.helper.formatMoney(advancePayTotal, ',', parseFloat(advancePayTotal.toFixed(decimal)).toString().split('.')[1] && parseFloat(advancePayTotal.toFixed(decimal)).toString().split('.')[1].length || 0) %>
                                 </th>
                             </tr>
@@ -33,17 +33,17 @@
                                 <td class="text-right" width="405">
                                     <div class="input-group input-group-sm">
                                         <input type="number" class="pay-input form-control nospin text-right"
-                                            max="<%- max_pr %>" min="1" step="0.01" placeholder="请填写支付比例,将自动计算本期金额" data-type="0" <%- isEdited && ctx.session.sessionUser.accountId === ctx.advance.uid ? '' : 'disabled' %>
-                                            value="<%- advance.cur_amount && ctx.helper.mul(ctx.helper.div(advance.cur_amount, advancePayTotal), 100, 2) || 0 %>">
+                                            max="<%- max_pr %>" min="1" step="0.01" placeholder="请填写支付比例,将自动计算本期金额" data-type="0" <%- isEdited ? '' : 'disabled' %>
+                                            value="<%- advance.pay_ratio && ctx.helper.mul(ctx.helper.div(advance.cur_amount, advancePayTotal), 100, 2) || 0 %>">
                                         <div class="input-group-append"><span class="input-group-text">%</span></div>
                                     </div>
                                 </td>
                                 <th width="150" class="text-center">本期金额</th>
                                 <td class="text-right" width="405">
                                     <div class="input-group input-group-sm">
-                                        <input type="number" class="pay-input form-control nospin text-right" min="1" <%- isEdited && ctx.session.sessionUser.accountId === ctx.advance.uid ? '' : 'disabled' %>
+                                        <input type="number" class="pay-input form-control nospin text-right" min="1" <%- isEdited  ? '' : 'disabled' %>
                                             placeholder="请填写本期金额,将自动计算支付比例" data-type="1"
-                                            value="<%- advance.cur_amount && advance.cur_amount.toFixed(decimal) %>">
+                                            value="<%- cur_amount %>">
                                         <div class="input-group-append"><span class="input-group-text">元</span></div>
                                     </div>
                                 </td>
@@ -51,18 +51,18 @@
                             <tr>
                                 <th class="text-center">截止上期</th>
                                 <td class="text-right" id="p_total1" width="405">
-                                    <%- ctx.helper.formatMoney((prevAdvance && prevAdvance.prev_total_amount || 0), ',', decimal) %>元
+                                    <%- prev_amount %>元
                                 </td>
                                 <th class="text-center">截止本期金额</th>
                                 <td class="text-right" id="p_total2" width="405">
-                                    <%- ctx.helper.formatMoney((prevAdvance && prevAdvance.prev_total_amount + advance.cur_amount || (advance.cur_amount || 0)), ',', decimal) %>元
+                                    <%- prev_total_amount %>元
                                 </td>
                             </tr>
                             <tr>
                                 <th class="text-center" >备注</th>
                                 <td colspan="3">
                                     <textarea id="ad-remark" class="form-control form-control-sm" rows="2"
-                                        <%- isEdited && ctx.session.sessionUser.accountId === ctx.advance.uid ? '' : 'disabled' %>></textarea>
+                                        <%- isEdited ? '' : 'disabled' %>></textarea>
                                 </td>
                             </tr>
                         </tbody>
@@ -76,7 +76,7 @@
                         <tbody id="file-content">
                         </tbody>
                     </table>
-                    <% if(isEdited && ctx.session.sessionUser.accountId === ctx.advance.uid) { %>
+                    <% if(isEdited) { %>
                     <table class="table table-bordered mt-3">
                         <thead>
                             <tr>

+ 8 - 8
app/view/advance/index.ejs

@@ -15,16 +15,16 @@
                 </div>
                 <div class="d-inline-block ml-2">
                     签约<%- type === 0 ? '开工' : '材料' %>预付款
-                    <b><%- ctx.helper.formatMoney(advancePayTotal) %></b> 元
+                    <b><%- ctx.helper.formatMoney(advancePayTotal, ',', parseFloat(advancePayTotal.toFixed(decimal)).toString().split('.')[1] && parseFloat(advancePayTotal.toFixed(decimal)).toString().split('.')[1].length || 0) %></b> 元
                 </div>
                 <div class="d-inline-block ml-4" style="width:300px">
                     <div class="progress">
                         <div class="progress-bar bg-success" style="width: <%- progress.p_ratio%>%;" data-placement="bottom"
-                            data-toggle="tooltip" data-original-title="截止上期金额:¥<%- ctx.helper.formatMoney(progress.p_amount, ',', decimal) %>"><%- progress.p_ratio.toFixed() %>%</div>
+                            data-toggle="tooltip" data-original-title="截止上期金额:¥<%- ctx.helper.formatMoney(progress.p_amount, ',', parseFloat(progress.p_amount.toFixed(decimal)).toString().split('.')[1] && parseFloat(progress.p_amount.toFixed(decimal)).toString().split('.')[1].length || 0) %>"><%- progress.p_ratio.toFixed() %>%</div>
                         <div class="progress-bar bg-info" style="width:<%- progress.c_ratio%>%;" data-placement="bottom"
-                            data-toggle="tooltip" data-original-title="本期金额:¥<%- ctx.helper.formatMoney(progress.c_amount, ',', decimal) %>"><%- progress.c_ratio.toFixed() %>%</div>
+                            data-toggle="tooltip" data-original-title="本期金额:¥<%- ctx.helper.formatMoney(progress.c_amount, ',', progress.c_amount && parseFloat(progress.c_amount.toFixed(decimal)).toString().split('.')[1] && parseFloat(progress.c_amount.toFixed(decimal)).toString().split('.')[1].length || 0) %>"><%- progress.c_ratio.toFixed() %>%</div>
                         <div class="progress-bar bg-gray" style="width:<%- progress.s_ratio%>%;" data-placement="bottom"
-                            data-toggle="tooltip" data-original-title="未完成:¥<%- ctx.helper.formatMoney(progress.s_amount, ',', decimal) %>"><%- progress.s_ratio.toFixed() %>%</div>
+                            data-toggle="tooltip" data-original-title="未完成:¥<%- ctx.helper.formatMoney(progress.s_amount, ',', parseFloat(progress.s_amount.toFixed(decimal)).toString().split('.')[1] && parseFloat(progress.s_amount.toFixed(decimal)).toString().split('.')[1].length || 0) %>"><%- progress.s_ratio.toFixed() %>%</div>
                     </div>
                 </div>
             </div>
@@ -59,10 +59,10 @@
                         <% advanceList.forEach(item => { %>
                             <tr>
                                 <td><a href="/tender/<%- ctx.tender.id %>/advance/<%- item.id %>/detail" data-id="<%- item.id %>">第<%- item.order %>期</a></td>
-                                <td><%- item.cur_amount && ctx.helper.mul(ctx.helper.div(item.cur_amount, advancePayTotal), 100, 2) || 0 %>%</td>
-                                <td class="text-right"><%- ctx.helper.formatMoney(item.cur_amount, ',', decimal)%></td>
-                                <td class="text-right"><%- ctx.helper.formatMoney(item.prev_amount, ',', decimal)%></td>
-                                <td class="text-right"><%- ctx.helper.formatMoney(item.prev_total_amount, ',', decimal)%></td>
+                                <td><%- item.pay_ratio %>%</td>
+                                <td class="text-right"><%- item.cur_amount %></td>
+                                <td class="text-right"><%- item.prev_amount %></td>
+                                <td class="text-right"><%- item.prev_total_amount %></td>
                                 <td><a class="btn btn-sm" href="#file" data-toggle="modal" data-target="#file" data-id="<%- item.id %>"><i
                                             class="fa fa-paperclip"></i> <%- item.fileList.length %></a></td>
                                 <td>

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

@@ -23,7 +23,7 @@
                 <h5 class="modal-title">附件</h5>
             </div>
             <div class="modal-body">
-                <div class="modal-height-500">
+                <div class="modal-height-500" style="overflow: auto;">
                     <table class="table table-sm table-bordered" id="file-content">
                     </table>
                 </div>

+ 2 - 2
app/view/change/info.ejs

@@ -699,7 +699,7 @@
             <% } %>
             </div>
         </div>
-
+        <a href="" id="file-upload" target="_blank" style="display: none;"></a>
         <div class="c-body tab-pane" role="tabpanel" id="files">
             <div class="sjs-height-0">
             <table class="table table-bordered">
@@ -717,7 +717,7 @@
                 <% for (const [index,att] of attList.entries()) { %>
                 <tr>
                     <td><%- index+1 %></td>
-                    <td><a href="<%- att.filepath %>" target="_black"><%- att.filename %><%- att.fileext %></a></td>
+                    <td><a href="javascript: void(0);" class="file-atn" f-id="<%- att.id %>"><%- att.filename %><%- att.fileext %></a></td>
                     <td><%- ctx.helper.bytesToSize(att.filesize) %></td>
                     <td><%- moment(att.in_time * 1000).format('YYYY-MM-DD') %></td>
                     <td>

+ 3 - 0
app/view/layout/menu.ejs

@@ -24,6 +24,9 @@
     </div>
     <div class="nav-bottom mt-auto">
         <ul class="nav nav-pills nav-stacked bg-nav">
+            <li><a href="http://doc.zhzdwd.com/docs/yunjiliangAPI/yunjiliangAPI-1ccjk7h426enp" target="_blank" data-toggle="tooltip" data-placement="right" title="" data-original-title="数据接口">API</a></li>
+        </ul>
+        <ul class="nav nav-pills nav-stacked bg-nav">
             <li <% if (ctx.controllerName === 'setting') { %>class="active"<% } %>><a href="/setting/info" data-toggle="tooltip" data-placement="right" title="" data-original-title="项目信息"><i class="fa fa-cogs"></i><span>项目信息</span></a></li>
         </ul>
         <div class="dropup mb-1 ml-1">

+ 5 - 2
app/view/ledger/bwtz.ejs

@@ -19,9 +19,12 @@
                         </div>
                     </div>
                 </div>
-                <div class="d-inline-block ml-3">
+                <div class="d-inline-block">
                     <a id="exportBwtz" class="btn btn-primary btn-sm" href="javascript: void(0)">导出部位台账Excel</a>
                 </div>
+                <div class="d-inline-block ml-2">
+                    <div class="alert alert-warning p-1"><i class="fa Example of exclamation-circle fa-exclamation-circle "></i> 台账分解与部位台账金额,会存在数学误差,属正常现象。软件以台账分解金额为准。</div>
+                </div>
             </div>
             <div class="ml-auto">
             </div>
@@ -125,4 +128,4 @@
     };
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
     const decimal = <%- ctx.tender.info.decimal.tp %>;
-</script>
+</script>

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

@@ -136,7 +136,7 @@
                     </div>
                 </div>
             </div>
-            <form class="modal-footer" method="post" action="<%- preUrl %>/ledger/audit/start" onsubmit="return checkAuditorFrom()">
+            <form class="modal-footer" method="post" action="<%- preUrl %>/ledger/audit/start" name="audit-start">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <button class="btn btn-primary btn-sm" type="submit" >确认上报</button>
@@ -320,7 +320,7 @@
                     </div>
                 </div>
             </div>
-            <form class="modal-footer" method="post" action="<%- preUrl %>/ledger/audit/start" onsubmit="return checkAuditorFrom()">
+            <form class="modal-footer" method="post" action="<%- preUrl %>/ledger/audit/start" name="audit-start">
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <% if(tender.ledger_status === auditConst.status.checkNo && ctx.session.sessionUser.accountId === tender.user_id) { %>
@@ -349,15 +349,6 @@
         return false;
     }
 
-    // 检查上报情况
-    function checkAuditorFrom () {
-        if ($('#auditors li').length === 0) {
-            toast('请先选择审批人,再上报数据', 'error', 'exclamation-circle');
-            return false;
-        }
-        $('#hide-all').show();
-    }
-
     $('#hideSp').click(function () {
         $('#sp-list').modal('hide');
     });

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

@@ -95,11 +95,6 @@
 <!--<link rel="stylesheet" href="/public/css/jquery-ui/datepicker.css">-->
 <!--<script src="/public/js/jquery-ui/datepicker.js"></script>-->
 <!--<script src="/public/js/jquery-ui/datepicker-zh-CN.js"></script>-->
-<% if ((material.status === auditConst.status.uncheck || material.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === material.user_id) {%>
-    <script>
-        const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
-    </script>
-<% } %>
 <script>
     const materialType = JSON.parse('<%- materialType %>');
     let materialBillsData = JSON.parse('<%- JSON.stringify(materialBillsData) %>');

+ 0 - 5
app/view/material/list.ejs

@@ -61,11 +61,6 @@
         </div>
     </div>
 </div>
-<% if ((ctx.material.status === auditConst.status.uncheck || ctx.material.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === ctx.material.user_id) {%>
-<script>
-    const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
-</script>
-<% } %>
 <script>
     const materialType = JSON.parse('<%- materialType %>');
     const materialBillsData = JSON.parse('<%- JSON.stringify(materialBillsData) %>');

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

@@ -225,6 +225,7 @@
     const billsSpreadSetting = JSON.parse('<%- JSON.stringify(ledgerSpread) %>');
     const posSpreadSetting = JSON.parse('<%- JSON.stringify(posSpread) %>');
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
+    const decimal = JSON.parse('<%- JSON.stringify(ctx.tender.info.decimal) %>');
     $('.sp-list-btn').click(function () {
         const type = $(this).data('type')
         if (type === 'hide') {

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

@@ -88,7 +88,7 @@
                 </div>
             </div>
             <form class="modal-footer" method="post" action="/tender/<%- ctx.tender.id %>/revise/audit/start"
-                onsubmit="return checkAuditorFrom()">
+                name="revise-start">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                 <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
@@ -701,7 +701,7 @@
                     </div>
                 </div>
                 <form class="modal-footer" method="post" action="<%- preUrl %>/revise/audit/start"
-                    onsubmit="return checkAuditorFrom()">
+                    name="revise-start">
                     <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                     <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                     <% if(revise.status === auditConst.status.checkNo && ctx.session.sessionUser.accountId === revise.uid) { %>
@@ -963,12 +963,4 @@
                 })
             }
         });
-        // 检查上报情况
-        function checkAuditorFrom() {
-            if ($('#auditors li').length === 0) {
-                toast('请先选择审批人,再上报数据', 'error', 'exclamation-circle');
-                return false;
-            }
-            $('#hide-all').show();
-        }
     </script>

+ 68 - 30
app/view/shares/ledger_check_modal.ejs

@@ -17,24 +17,24 @@
                 <div class="card mb-2 p-2 border-success" id="check-empty-code">
                     <div class="d-flex justify-content-between">
                         项目节、清单编号同时为空
-                        <!-- <span class="text-muted">待检查</span> -->
-                        <!-- <span class="text-muted" title="检查中"><i class="fa fa-spinner fa-spin"></i></span> -->
                         <span class="text-success" title="完成" name="check-status"><i class="fa fa-check"></i></span>
                     </div>
                 </div>
                 <div class="card mb-2 p-2 border-success" id="check-calc">
                     <div class="d-flex justify-content-between">
                         清单数量不等于计量单元之和
-                        <!-- <span class="text-muted">待检查</span> -->
-                        <!-- <span class="text-muted" title="检查中"><i class="fa fa-spinner fa-spin"></i></span> -->
                         <span class="text-success" title="完成" name="check-status"><i class="fa fa-check"></i></span>
                     </div>
                 </div>
                 <div class="card mb-2 p-2 border-success" id="check-zero">
                     <div class="d-flex justify-content-between">
                         清单数量或单价为0
-                        <!-- <span class="text-muted">待检查</span> -->
-                        <!-- <span class="text-muted" title="检查中"><i class="fa fa-spinner fa-spin"></i></span> -->
+                        <span class="text-success" title="完成" name="check-status"><i class="fa fa-check"></i></span>
+                    </div>
+                </div>
+                <div class="card mb-2 p-2 border-success" id="check-tp">
+                    <div class="d-flex justify-content-between">
+                        清单金额≠数量×单价
                         <span class="text-success" title="完成" name="check-status"><i class="fa fa-check"></i></span>
                     </div>
                 </div>
@@ -56,23 +56,38 @@
         empty_code: {value: 2, text: '项目节、清单编号同时为空'},
         calc: {value: 3, text: '清单数量不等于计量单元之和'},
         zero: {value: 4, text: '清单数量或单价为0'},
+        tp: {value: 5, text: '清单金额≠数量×单价'},
     };
     const LedgerChecker = function (setting) {
-        const ledger = setting.ledgerTree, ledgerPos = setting.ledgerPos;
+        const ledger = setting.ledgerTree, ledgerPos = setting.ledgerPos, decimal = setting.decimal;
+        const checkOption = setting.checkOption;
+
+        const showCheckPart = function (obj, show) {
+            if (show) {
+                obj.show();
+            } else {
+                obj.hide();
+            }
+        }
 
         const initWaitingModal = function () {
             $('.card', '#ledger-check-modal').removeClass('border-success');
             $('[name=check-status]', '#ledger-check-modal').removeClass('text-success').addClass('text-muted').html('待检查');
+            showCheckPart($('#check-sibling'), checkOption.sibling.enable);
+            showCheckPart($('#check-empty-code'), checkOption.empty_code.enable);
+            showCheckPart($('#check-calc'), checkOption.calc.enable);
+            showCheckPart($('#check-zero'), checkOption.zero.enable);
+            showCheckPart($('#check-tp'), checkOption.tp.enable);
             $('#ledger-check-begin').show();
             $('#ledger-check-waiting').hide();
             $('#ledger-check-hint').removeClass('text-warning').addClass('text-success').html('检查完成,现在您可以查看结果。').hide();
             $('#ledger-check-show').hide();
         }
 
-        const doSomeCheck = function (selector, checkFun) {
+        const doSomeCheck = function (selector, checkFun, option) {
             const checkStatus = $('[name=check-status]', selector);
             checkStatus.html('<i class="fa fa-spinner fa-spin"></i>');
-            const result = checkFun(ledger);
+            const result = checkFun(ledger, option);
             checkStatus.removeClass('text-muted').addClass('text-success').html('<i class="fa fa-check"></i>');
             $(selector).addClass('border-success');
             return result;
@@ -109,7 +124,7 @@
                 }
                 return error;
             },
-            checkCalc: function (ledgerTree) {
+            checkCalc: function (ledgerTree, option) {
                 const error = [];
                 for (const node of ledgerTree.nodes) {
                     if (node.children && node.children.length > 0) continue;
@@ -117,19 +132,15 @@
                     const nodePos = ledgerPos.getLedgerPos(node.id);
                     if (!nodePos || nodePos.length === 0) continue;
 
-                    const checkData = {
-                        sgfh_qty: node.sgfh_qty || 0, qtcl_qty: node.qtcl_qty || 0, sjcl_qty: node.sjcl_qty || 0,
-                        quantity: node.quantity || 0
-                    };
-                    const calcData = {
-                        sgfh_qty: 0, qtcl_qty: 0, sjcl_qty: 0,
-                        quantity: 0
-                    };
+                    const checkData = {}, calcData = {};
+                    for (const f of option.fields) {
+                        checkData[f] = node[f] || 0;
+                        calcData[f] = 0;
+                    }
                     for (const np of nodePos) {
-                        calcData.sgfh_qty = ZhCalc.add(calcData.sgfh_qty, np.sgfh_qty) || 0;
-                        calcData.qtcl_qty = ZhCalc.add(calcData.qtcl_qty, np.qtcl_qty) || 0;
-                        calcData.sjcl_qty = ZhCalc.add(calcData.sjcl_qty, np.sjcl_qty) || 0;
-                        calcData.quantity = ZhCalc.add(calcData.quantity, np.quantity) || 0;
+                        for (const f of option.fields) {
+                            calcData[f] = ZhCalc.add(calcData[f], np[f]) || 0;
+                        }
                     }
                     if (!_.isMatch(checkData, calcData)) error.push(node);
                 }
@@ -147,6 +158,21 @@
                 }
                 return error;
             },
+            checkTp: function (ledgerTree, option) {
+                const error = [];
+                for (const node of ledgerTree.nodes) {
+                    if (node.children && node.children.length > 0) continue;
+                    if (option.filter && option.filter(node)) continue;
+
+                    const checkData = {}, calcData = {};
+                    for (const f of option.fields) {
+                        checkData[f.tp] = node[f.tp] || 0;
+                        calcData[f.tp] = ZhCalc.mul(node.unit_price, node[f.qty], decimal.tp) || 0;
+                    }
+                    if (!_.isMatch(checkData, calcData)) error.push(node);
+                }
+                return error;
+            }
         };
 
         const assignWarningData = function (nodes, checkType, warningData) {
@@ -169,14 +195,26 @@
                 check_time: new Date(),
                 warning_data: [],
             }
-            const sibling = doSomeCheck('#check-sibling', ledgerCheckUtil.checkSibling) || [];
-            assignWarningData(sibling, ledgerCheckType.sibling.value, checkData.warning_data);
-            const empty_code = doSomeCheck('#check-empty-code', ledgerCheckUtil.checkCodeEmpty) || [];
-            assignWarningData(empty_code, ledgerCheckType.empty_code.value, checkData.warning_data);
-            const calc = doSomeCheck('#check-calc', ledgerCheckUtil.checkCalc) || [];
-            assignWarningData(calc, ledgerCheckType.calc.value, checkData.warning_data);
-            const zero = doSomeCheck('#check-zero', ledgerCheckUtil.checkZero) || [];
-            assignWarningData(zero, ledgerCheckType.zero.value, checkData.warning_data);
+            if (checkOption.sibling.enable) {
+                const sibling = doSomeCheck('#check-sibling', ledgerCheckUtil.checkSibling, checkOption.sibling) || [];
+                assignWarningData(sibling, ledgerCheckType.sibling.value, checkData.warning_data);
+            }
+            if (checkOption.empty_code.enable) {
+                const empty_code = doSomeCheck('#check-empty-code', ledgerCheckUtil.checkCodeEmpty, checkOption.empty_code) || [];
+                assignWarningData(empty_code, ledgerCheckType.empty_code.value, checkData.warning_data);
+            }
+            if (checkOption.calc.enable) {
+                const calc = doSomeCheck('#check-calc', ledgerCheckUtil.checkCalc, checkOption.calc) || [];
+                assignWarningData(calc, ledgerCheckType.calc.value, checkData.warning_data);
+            }
+            if (checkOption.zero.enable) {
+                const zero = doSomeCheck('#check-zero', ledgerCheckUtil.checkZero, checkOption.zero) || [];
+                assignWarningData(zero, ledgerCheckType.zero.value, checkData.warning_data);
+            }
+            if (checkOption.tp.enable) {
+                const tp = doSomeCheck('#check-tp', ledgerCheckUtil.checkTp, checkOption.tp) || [];
+                assignWarningData(tp, ledgerCheckType.tp.value, checkData.warning_data);
+            }
 
             $('#ledger-check-waiting').hide();
             setting.checkList.clearCheckData();

+ 30 - 93
app/view/stage/audit_modal.ejs

@@ -52,8 +52,7 @@
                         </div>
                     </div>
                 </div>
-                <form class="modal-footer" method="post" action="<%- preUrl %>/audit/start" name="stage-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>
                     <input type="hidden" name="_csrf" value="<%= ctx.csrf %>">
                     <button class="btn btn-primary btn-sm" type="submit">确认上报</button>
@@ -241,8 +240,7 @@
                         </div>
                     </div>
                 </div>
-                <form class="modal-footer" method="post" action="<%- preUrl %>/audit/start" name="stage-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 %>">
                     <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                     <% if(ctx.stage.status === auditConst.status.checkNo && ctx.session.sessionUser.accountId === ctx.stage.user_id) { %>
@@ -258,7 +256,7 @@
     <!--审批通过-->
     <div class="modal fade sp-location-list" id="sp-done" data-backdrop="static">
         <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">
                     <h5 class="modal-title">审批通过</h5>
                 </div>
@@ -449,8 +447,7 @@
     <!--审批退回-->
     <div class="modal fade sp-location-list" id="sp-back" data-backdrop="static">
         <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">
                     <h5 class="modal-title">审批退回</h5>
                 </div>
@@ -819,94 +816,34 @@
             }
             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) {
-        //     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()),
-        //     };
-        //     postData(this.action, data, function () {
-        //         window.location.reload();
-        //     })
-        //     return false
-        // });
-        // 审批
-        function auditCheck(i) {
-            const checkType = parseInt($(i === 0 ? '[name=checkType]' : '[name=checkType]:checked').val())
-            const data = {
-                opinion: $(`${i === 0 ? '#sp-done' : '#sp-back'}`).find('[name=opinion]').val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
-                checkType,
-            }
-            if (i === 1) {
-                if ($('#warning-text').length) $('#warning-text').remove()
-                if (!checkType && !$('#warning-text').length) {
-                    $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
-                    return false
-                }
-            }
-            checkType && postData(preUrl + '/audit/check', data, function () {
-                window.location.reload();
-            })
+    $('#audit-check0').submit(function (e) {
+        const checkType = parseInt($('[name=checkType]').val());
+        const data = {
+            opinion: $(`${'#sp-done'}`).find('[name=opinion]').val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType,
+        };
+        $('#sp-done').modal('hide');
+        checkType && dataChecker.checkAndPost(this.action, data);
+        $('#hide-all').hide();
+        return false;
+    });
+    $('#audit-check1').submit(function (e) {
+        const checkType = parseInt($('[name=checkType]:checked').val());
+        const data = {
+            opinion: $(`${'#sp-back'}`).find('[name=opinion]').val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
+            checkType,
+        };
+        if ($('#warning-text').length) $('#warning-text').remove()
+        if (!checkType && !$('#warning-text').length) {
+            $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
             return false
         }
-    // $('#audit-check2').submit(function (e) {
-    //     debugger
-    //     // $(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()),
-    //     };
-    //     if (!$('[name=checkType]:checked', this).val()) {
-    //         if (!$('#warning-text').length) {
-    //             $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
-    //         }
-    //         return false
-    //     } else {
-    //         postData(this.action, data, function () {
-    //             window.location.reload();
-    //         })
-    //     }
-    //     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()),
-    //     };
-    //     if (!parseInt($('[name=checkType]:checked', this).val())) {
-    //         if (!$('#warning-text').length) {
-    //             $('.reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
-    //         }
-    //         return false;
-    //     } else {
-    //         postData(this.action, data, function () {
-    //         window.location.reload();
-    //     });
-    //     }
-    //     return false
-    // });
+        $('#sp-back').modal('hide');
+        checkType && dataChecker.checkAndPost(this.action, data);
+        $('#hide-all').hide();
+        return false;
+    });
+    <% } %>
 
     $('.sp-location-list').on('shown.bs.modal', function () {
         const scrollBox = $(this).find('div[class="col-8 modal-height-500"]');

+ 5 - 2
app/view/stage/bwtz.ejs

@@ -32,9 +32,12 @@
                         </div>
                     </div>
                 </div>
-                <div class="d-inline-block ml-3">
+                <div class="d-inline-block">
                     <a id="exportBwtz" class="btn btn-primary btn-sm" href="javascript: void(0)">导出部位台账Excel</a>
                 </div>
+                <div class="d-inline-block ml-2">
+                    <div class="alert alert-warning p-1"><i class="fa Example of exclamation-circle fa-exclamation-circle "></i> 计量台账与部位台账金额,会存在数学误差,属正常现象。软件以计量台账金额为准。</div>
+                </div>
             </div>
             <div class="ml-auto">
             </div>
@@ -195,4 +198,4 @@
     };
     const decimal = <%- ctx.tender.info.decimal.tp %>;
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
-</script>
+</script>

+ 8 - 0
app/view/stage/index.ejs

@@ -34,6 +34,7 @@
                 </div>
                 <div class="d-inline-block ml-3">
                     <a id="exportExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导出计量台账Excel</a>
+                    <a class="btn btn-sm btn-primary" href="#ledger-check-modal" data-toggle="modal" data-target="#ledger-check-modal">数据检查</a>
                 </div>
             </div>
             <div class="ml-auto">
@@ -295,6 +296,7 @@
                                 <br>
                                 <div class="tab-content" id="showAttachment" style="display: none" file-id="">
                                     <div class="sjs-bottom-2">
+                                        <a href="javascript:void(0);" target="_blank" style="display: none" id="load-file"></a>
                                         <div class="d-flex justify-content-end mb-1" id="btn-att">
                                             <a href="javascript:void(0);" content="location" class="btn btn-sm btn-outline-primary" style="margin-right: 5px">定位</a>
                                             <a href="javascript:void(0);" content="view" class="btn btn-sm btn-outline-primary" style="margin-right: 5px">查看</a>
@@ -531,6 +533,8 @@
                     </div>
                     <div id="error-list" class="tab-pane">
                     </div>
+                    <div id="check-list" class="tab-pane">
+                    </div>
                 </div>
             </div>
         </div>
@@ -553,6 +557,9 @@
                     <a class="nav-link" content="#checked-change" href="javascript: void(0);">变更令</a>
                 </li>
                 <li class="nav-item">
+                    <a class="nav-link" content="#check-list" id="check-list-tab" href="javascript: void(0);" style="display: none;">检查错误</a>
+                </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>
@@ -563,6 +570,7 @@
         <img src="/public/images/icon-ok.png" id="icon-ok" />
     </div>
 </div>
+<script src="/public/js/moment/moment.min.js"></script>
 <script>
     String.prototype.replaceAll = function (FindText, RepText) {
         regExp = new RegExp(FindText, 'g');

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

@@ -392,3 +392,4 @@
 </div>
 <% include ./audit_modal.ejs %>
 <% include ../shares/merge_peg_modal.ejs %>
+<% include ../shares/ledger_check_modal.ejs %>

+ 3 - 33
app/view/tender/detail_modal.ejs

@@ -350,19 +350,10 @@
                         <div class="col-4">
                             <div class="input-group input-group-sm">
                                 <div class="input-group-prepend">
-                                    <span class="input-group-text">数量</span>
-                                </div>
-                                <input type="number" class="form-control" value="2" id="decimal-extra-qty"
-                                       oninput="limitDecimal(this)" min="0" max="6">
-                            </div>
-                        </div>
-                        <div class="col-4">
-                            <div class="input-group input-group-sm">
-                                <div class="input-group-prepend">
                                     <span class="input-group-text">金额</span>
                                 </div>
                                 <input type="number" class="form-control" value="2" id="decimal-extra-tp"
-                                       oninput="limitDecimal(this)" min="0" max="4">
+                                       oninput="limitDecimal(this)" min="0" max="4" maxlength="1">
                             </div>
                         </div>
                     </div>
@@ -430,7 +421,7 @@
                         <div class="col-auto pr-0">
                             <div class="form-group form-check pl-0">
                                 <div class="custom-control custom-switch">
-                                    <input type="checkbox" class="custom-control-input" id="decimal-pay" readonly="">
+                                    <input type="checkbox" class="custom-control-input" id="decimal-pay" disabled>
                                     <label class="custom-control-label" for="decimal-pay">合同支付</label>
                                 </div>
                             </div>
@@ -448,7 +439,7 @@
                         <div class="col-auto pr-0">
                             <div class="form-group form-check pl-0">
                                 <div class="custom-control custom-switch">
-                                    <input type="checkbox" class="custom-control-input" id="decimal-extra" readonly="">
+                                    <input type="checkbox" class="custom-control-input" id="decimal-extra" disabled>
                                     <label class="custom-control-label" for="decimal-extra">其他台账</label>
                                 </div>
                             </div>
@@ -456,14 +447,6 @@
                         <div class="col-4">
                             <div class="input-group input-group-sm">
                                 <div class="input-group-prepend">
-                                    <span class="input-group-text">数量</span>
-                                </div>
-                                <input type="number" class="form-control" value="2" id="decimal-extra-qty" readonly="">
-                            </div>
-                        </div>
-                        <div class="col-4">
-                            <div class="input-group input-group-sm">
-                                <div class="input-group-prepend">
                                     <span class="input-group-text">金额</span>
                                 </div>
                                 <input type="number" class="form-control" value="2" id="decimal-extra-tp" readonly="">
@@ -778,20 +761,12 @@
         $('#decimal-extra')[0].checked = property.decimal.extra;
         $('#decimal-extra-tp').val(property.decimal.extraTp);
         $('#decimal-extra-tp')[0].disabled = !property.decimal.extra;
-        $('#decimal-extra-qty').val(property.decimal.extraQty);
-        $('#decimal-extra-qty')[0].disabled = !property.decimal.extra;
     }
     $('#decimal-pay').change(() => {
-        console.log(!$('#decimal-pay')[0].checked);
         $('#decimal-pay-tp')[0].disabled = !$('#decimal-pay')[0].checked;
-        console.log($('#decimal-pay-tp')[0].disabled);
     });
     $('#decimal-extra').change(() => {
-        console.log(!$('#decimal-extra')[0].checked);
-        $('#decimal-extra-qty')[0].disabled = !$('#decimal-extra')[0].checked;
         $('#decimal-extra-tp')[0].disabled = !$('#decimal-extra')[0].checked;
-        console.log($('#decimal-extra-qty')[0].disabled);
-        console.log($('#decimal-extra-tp')[0].disabled);
     });
     $('#bd-set-2').on('show.bs.modal', function () {
         loadCalculateProperty();
@@ -804,7 +779,6 @@
                 pay: $('#decimal-pay')[0].checked,
                 payTp: _.toNumber($('#decimal-pay-tp').val()),
                 extra: $('#decimal-extra')[0].checked,
-                extraQty: _.toNumber($('#decimal-extra-qty').val()),
                 extraTp: _.toNumber($('#decimal-extra-tp').val()),
             }
         };
@@ -839,10 +813,6 @@
                     toastr.warning('第一期已审批完成,不可取消其他台账单独设置');
                     return;
                 }
-                if (prop.decimal.extraQty < property.decimal.extraQty) {
-                    toastr.warning('第一期已审批完成,单独设置的其他台账小数位数,不可小于' + property.decimal.extraQty);
-                    return;
-                }
                 if (prop.decimal.extraTp < property.decimal.extraTp) {
                     toastr.warning('第一期已审批完成,单独设置的其他台账小数位数,不可小于' + property.decimal.extraTp);
                     return;

+ 3 - 2
builder_report_index_define.js

@@ -32,7 +32,7 @@ const advance_pay = {
     prefix: '预付款',
     cols: [
         { name: 'id', field: 'id', type: dataType.int },
-        { name: '创建者id', field: 'uuid', type: dataType.int },
+        { name: '创建者id', field: 'uid', type: dataType.int },
         { name: '审批次数', field: 'times', type: dataType.int },
         { name: '审批状态', field: 'status', type: dataType.int },
         { name: '期数索引', field: 'order', type: dataType.int },
@@ -212,7 +212,8 @@ const change_bills = {
         { name: '金额_8', field: 'tp_8', type: dataType.currency, tag: { type: 'tp' } },
         { name: '数量_9', field: 'qty_9', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
         { name: '金额_9', field: 'tp_9', type: dataType.currency, tag: { type: 'tp' } },
-
+        { name: '项目节编号', field: 'xmj_code', type: dataType.str },
+        { name: '细目', field: 'xmj_jldy', type: dataType.str },
     ],
 };
 // 期 - 清单

+ 2 - 0
config/config.default.js

@@ -183,5 +183,7 @@ module.exports = appInfo => {
         },
     };
 
+    config.proxy = true;
+
     return config;
 };