Browse Source

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

TonyKang 5 years ago
parent
commit
3c7c27c0a8

+ 51 - 18
app/controller/revise_controller.js

@@ -61,6 +61,17 @@ module.exports = app => {
                 // 分页相关
                 const count = await ctx.service.ledgerRevise.count({tid: ctx.tender.id});
                 const ledgerRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
+                if (ledgerRevise.length > 0) {
+                    const revise = ledgerRevise[0];
+                    if (revise.status === audit.revise.status.checked || !revise.valid) {
+                        revise.lastest = true;
+                    } else {
+                        if (ledgerRevise.length > 1) ledgerRevise[1].lastest = true;
+                        if (revise.status === audit.revise.status.checking) {
+                            revise.curAuditor = await ctx.service.reviseAudit.getCurAuditor(revise.id, revise.times);
+                        }
+                    }
+                }
                 const addValid = await this._getAddReviseValid(ctx);
                 const [stdBills, stdChapters] = await this.ctx.service.valuation.getValuationStdList(ctx.tender.data.valuation);
                 const renderData = {
@@ -219,7 +230,7 @@ module.exports = app => {
                 reviseBills, revisePos, ledgerSpread, posSpread, tenderMenu, measureType,
                 preUrl: '/tender/' + ctx.tender.id,
                 audit: audit.revise,
-                jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.ledger.revise),
+                jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.info),
                 stdBills,
                 stdChapters,
                 curAuditor,
@@ -328,11 +339,44 @@ module.exports = app => {
             }
         }
 
-        /**
-         * 增、删、上下移、升降级
-         * @param ctx
-         * @returns {Promise<void>}
-         */
+        async history(ctx) {
+            try {
+                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id, false);
+                if (!revise) throw '台账修订数据有误';
+
+                const reviseBills = await ctx.service.ledger.getData(ctx.tender.id);
+                const revisePos = await ctx.service.pos.getPosData({tid: ctx.tender.id});
+                const [ledgerSpread, posSpread] = this._getSpreadSetting(revise);
+                ledgerSpread.readOnly = true;
+                posSpread.readOnly = true;
+                const historyRevise = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
+                const renderData = {
+                    measureType, audit, revise,
+                    ledgerSpread, posSpread,
+                    reviseBills, revisePos,
+                    readOnly: true,
+                    historyRevise,
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.revise.history),
+                };
+                await this.layout('revise/history.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect(ctx.request.header.referer);
+            }
+        }
+
+        async historyInfo(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data || !data.rid || data.rid === '') throw '查询的台账修订有误';
+                const reviseInfo = await ctx.service.ledgerRevise.getRevise(ctx.tender.id, data.rid);
+                ctx.body = { err: 0, msg: '', data: reviseInfo };
+            } catch(err) {
+                this.log(err);
+                ctx.body = this.ajaxErrorBody(err, '获取台账修订历史数据错误');
+            }
+        }
+
         async _billsBase(revise, type, data) {
             if (isNaN(data.id) || data.id <= 0) throw '数据错误';
             if (type !== 'add') {
@@ -353,17 +397,6 @@ module.exports = app => {
                     return await this.ctx.service.reviseBills.downLevelNode(revise.tid, data.id, data.count);
             }
         }
-        /**
-         * 批量插入数据 (Ajax)
-         *
-         * data = {id, batchData, batchType}
-         * data.batchType = 'batchInsertChild'/'batchInsertNext'
-         * data.batchData = [{name, children}] -- 项目节列表
-         * data.batchData.children = [{code, name, unit, unit_price, quantity}] -- 工程量清单列表
-         *
-         * @param ctx
-         * @return {Promise<void>}
-         */
         async _batchInsert(revise, data) {
             if ((isNaN(data.id) || data.id <= 0) || !data.batchType) {
                 throw '参数错误';
@@ -469,7 +502,7 @@ module.exports = app => {
                         responseData.data = await this._billsBase(revise, data.postType, data.postData);
                         break;
                     case 'update':
-                        responseData.data = await this.ctx.service.reviseBills.updateCalc(revise, data.postData);
+                        responseData.data = await this.ctx.service.reviseBills.updateCalc(revise.tid, data.postData);
                         break;
                     case 'batch-insert':
                         responseData.data = await this._batchInsert(revise, data.postData);

+ 14 - 21
app/controller/stage_controller.js

@@ -137,6 +137,7 @@ module.exports = app => {
          */
         async index(ctx) {
             try {
+                console.log(ctx.stage);
                 await this._getStageAuditViewData(ctx);
                 const renderData = await this._getDefaultRenderData(ctx);
                 [renderData.ledgerSpread, renderData.posSpread] = this._getSpreadSetting();
@@ -251,7 +252,7 @@ module.exports = app => {
                         responseData.data.curStageData = await ctx.service.stageBills.updateStageData(data.bills.stage);
                     }
                 }
-                await this.ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);
@@ -304,7 +305,7 @@ module.exports = app => {
                 } else {
                     result = await ctx.service.stageChange.billsChange(data.target.bills, data.change);
                 }
-                await this.ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = {err: 0, msg: '', data: result};
             } catch(err) {
                 this.log(err);
@@ -337,6 +338,7 @@ module.exports = app => {
          */
         async detail(ctx) {
             try {
+                console.log(ctx.stage);
                 await this._getStageAuditViewData(ctx);
                 const renderData = await this._getDefaultRenderData(ctx);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.stage.detail);
@@ -362,6 +364,7 @@ module.exports = app => {
 
                 const data = JSON.parse(ctx.request.body.data);
                 await ctx.service.stage.buildDetailData(ctx.tender.id, ctx.stage.order, data);
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
 
                 ctx.body = {err: 0, msg: '', data: null};
             } catch (err) {
@@ -429,6 +432,7 @@ module.exports = app => {
 
                 const data = JSON.parse(ctx.request.body.data);
                 await ctx.service.stage.update(data, { id: ctx.stage.id });
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
 
                 ctx.body = {err: 0, msg: '', data: this.ctx.stage};
             } catch (err) {
@@ -456,6 +460,7 @@ module.exports = app => {
                 } else {
                     responseData.data = await ctx.service.stageDetail.saveDetailData(data);
                 }
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);
@@ -478,6 +483,7 @@ module.exports = app => {
                 const fileInfo = path.parse(stream.filename);
                 const fileName = path.join('public/upload', this.ctx.tender.id.toString(), 'im', 'calcImg_' + create_time + fileInfo.ext);
                 await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, 'app', fileName));
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = {err: 0, msg: '', data: fileName};
             } catch(err) {
                 this.log(err);
@@ -517,6 +523,7 @@ module.exports = app => {
                 await this.ctx.service.stageDetail.saveDetailData(data);
                 const imData = await ctx.service.stageDetail.getLastestImStageData(this.ctx.tender.id, this.ctx.stage.id, data.lid, data.uuid);
                 const responseData = {err: 0, msg: '', data: imData};
+                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);
@@ -533,24 +540,10 @@ module.exports = app => {
             try {
                 await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, false);
                 ctx.stage.check_detail = false;
-                ctx.redirect(ctx.request.header.referer);
-            } catch (err) {
-                ctx.redirect(ctx.request.header.referer);
-            }
-        }
-
-        /**
-         * 中间计量 -- 解锁编辑(Post)
-         * @param ctx
-         * @returns {Promise<void>}
-         */
-        async unlockDetail(ctx) {
-            try {
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
-                ctx.stage.check_detail = true;
-                ctx.redirect(ctx.request.header.referer);
+                ctx.body = {err: 0, msg: '', data: false}
             } catch (err) {
-                ctx.redirect(ctx.request.header.referer);
+                this.log(err);
+                ctx.body = this.ajaxErrorBody(err, '数据错误,刷新页面再试');
             }
         }
 
@@ -982,12 +975,12 @@ module.exports = app => {
                 const renderData = await this._getDefaultRenderData(ctx);
                 [renderData.gclSpread, renderData.leafXmjSpread] = this._getGatherSpreadSetting();
                 renderData.ledger = await ctx.service.ledger.getData(ctx.tender.id);
-                renderData.curLedgerData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.times, 0);
+                renderData.curLedgerData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
 
                 renderData.pos = await ctx.service.pos.getPosData({tid: ctx.tender.id});
                 // todo 根据当前人,或指定对象查询数据
                 renderData.curPosData = await ctx.service.stagePos.getAuditorStageData(ctx.tender.id,
-                    ctx.stage.id, ctx.stage.times, ctx.stage.curAuditor ? ctx.stage.curAuditor.order : 0);
+                    ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
                 //renderData.gcl = await this.ctx.service.ledger.getAllLeafGclBills(this.ctx.tender.id);
                 renderData.dealBills = await ctx.service.dealBills.getAllDataByCondition({ where: {tender_id: this.ctx.tender.id} });
 

+ 298 - 0
app/public/js/revise_history.js

@@ -0,0 +1,298 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+const ckBillsSpread = window.location.pathname + '-billsSelect';
+
+$(document).ready(() => {
+    toastr.options = {
+        "closeButton": false,
+        "debug": false,
+        "newestOnTop": false,
+        "progressBar": false,
+        "positionClass": "toast-top-center",
+        "preventDuplicates": false,
+        "onclick": null,
+        "showDuration": "300",
+        "hideDuration": "1000",
+        "timeOut": "5000",
+        "extendedTimeOut": "1000",
+        "showEasing": "swing",
+        "hideEasing": "linear",
+        "showMethod": "fadeIn",
+        "hideMethod": "fadeOut"
+    };
+    autoFlashHeight();
+    // 初始化spread
+    const billsSpread = SpreadJsObj.createNewSpread($('#bills-spread')[0]);
+    const billsSheet = billsSpread.getActiveSheet();
+    SpreadJsObj.initSheet(billsSheet, billsSpreadSetting);
+    const posSpread = isTz ? SpreadJsObj.createNewSpread($('#pos-spread')[0]) : null;
+    const posSheet = isTz ? posSpread.getActiveSheet() : null;
+    if (isTz) SpreadJsObj.initSheet(posSheet, posSpreadSetting);
+
+    const posSearch = isTz ? $.posSearch({selector: '#pos-search', searchSpread: posSpread}) : null;
+
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'revise.history.memu.1.0.0',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+            billsSpread.refresh();
+            if (isTz) posSpread.refresh();
+        }
+    });
+
+    // 初始化 清单树结构
+    const treeSetting = {
+        id: 'ledger_id',
+        pid: 'ledger_pid',
+        order: 'order',
+        level: 'level',
+        rootId: -1,
+        keys: ['id', 'tender_id', 'ledger_id'],
+        calcFields: ['sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price'],
+    };
+    if (!isTz) {
+        treeSetting.calcFields.push('deal_tp');
+    }
+    treeSetting.calcFun = function (node) {
+        node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+    };
+    const billsTree = createNewPathTree('revise', treeSetting);
+    billsTree.loadDatas(billsData);
+    treeCalc.calculateAll(billsTree);
+    // 加载至spread
+    SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, billsTree);
+    SpreadJsObj.loadTopAndSelect(billsSheet, ckBillsSpread);
+    // 初始化 部位明细
+    const pos = new PosData({ id: 'id', ledgerId: 'lid' });
+    pos.loadDatas(posData);
+
+    const billsTreeSpreadObj = {
+        /**
+         *
+         * @param sheet
+         * @param data
+         */
+        refreshTree: function (sheet, data) {
+            SpreadJsObj.massOperationSheet(sheet, function () {
+                const tree = sheet.zh_tree;
+                // 处理删除
+                if (data.delete) {
+                    data.delete.sort(function (a, b) {
+                        return b.deleteIndex - a.deleteIndex;
+                    });
+                    for (const d of data.delete) {
+                        sheet.deleteRows(d.deleteIndex, 1);
+                    }
+                }
+                // 处理新增
+                if (data.create) {
+                    const newNodes = data.create;
+                    if (newNodes) {
+                        newNodes.sort(function (a, b) {
+                            return a.index - b.index;
+                        });
+
+                        for (const node of newNodes) {
+                            sheet.addRows(node.index, 1);
+                            SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(node), 1);
+                        }
+                    }
+                }
+                // 处理更新
+                if (data.update) {
+                    const rows = [];
+                    for (const u of data.update) {
+                        rows.push(tree.nodes.indexOf(u));
+                    }
+                    SpreadJsObj.reLoadRowsData(sheet, rows);
+                }
+                // 处理展开
+                if (data.expand) {
+                    const expanded = [];
+                    for (const e of data.expand) {
+                        if (expanded.indexOf(e) === -1) {
+                            const posterity = tree.getPosterity(e);
+                            for (const p of posterity) {
+                                sheet.setRowVisible(tree.nodes.indexOf(p), p.visible);
+                                expanded.push(p);
+                            }
+                        }
+                    }
+                }
+            });
+        },
+        selectionChanged: function (e, info) {
+            if (info.newSelections[0].row !== info.oldSelections[0].row) {
+                SpreadJsObj.saveTopAndSelect(billsSheet, ckBillsSpread);
+                if (isTz) {
+                    posSpreadObj.loadCurPosData();
+                    posSearch.search($('#pos-keyword').val());
+                }
+            }
+        },
+        topRowChanged: function (e, info) {
+            SpreadJsObj.saveTopAndSelect(info.sheet, ckBillsSpread);
+        },
+    };
+    billsSpread.bind(spreadNS.Events.SelectionChanged, billsTreeSpreadObj.selectionChanged);
+    billsSpread.bind(spreadNS.Events.topRowChanged, billsTreeSpreadObj.topRowChanged);
+
+    const posSpreadObj = {
+        /**
+         * 加载部位明细 根据当前台账选择节点
+         */
+        loadCurPosData: function () {
+            const node = SpreadJsObj.getSelectObject(billsSheet);
+            if (node) {
+                const posData = pos.getLedgerPos(node.id) || [];
+                SpreadJsObj.loadSheetData(posSheet, 'data', posData);
+            } else {
+                SpreadJsObj.loadSheetData(posSheet, 'data', []);
+            }
+            SpreadJsObj.resetFieldReadOnly(posSheet);
+        },
+    };
+    posSpreadObj.loadCurPosData();
+    SpreadJsObj.resetTopAndSelect(posSheet);
+    $.divResizer({
+        select: '#revise-resize',
+        callback: function () {
+            billsSpread.refresh();
+            let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
+            $(".sp-wrap").height(bcontent-40);
+            posSpread.refresh();
+        }
+    });
+
+    let searchLedger;
+    $.divResizer({
+        select: '#revise-right-spr',
+        callback: function () {
+            billsSpread.refresh();
+            if (posSpread) {
+                posSpread.refresh();
+            }
+            if (searchLedger && searchLedger.spread) {
+                searchLedger.spread.refresh();
+            }
+        }
+    });
+    // 展开收起标准清单
+    $('a', '#side-menu').bind('click', function (e) {
+        e.preventDefault();
+        const tab = $(this), tabPanel = $(tab.attr('content'));
+        const showSideTools = function (show) {
+            const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
+            if (show) {
+                right.show();
+                autoFlashHeight();
+                /**
+                 * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
+                 * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
+                 * 故需要通过最终的parent.width再计算一次left.width
+                 *
+                 * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
+                 * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
+                 *
+                 */
+                    //left.css('width', parent.width() - right.outerWidth());
+                    //left.css('width', parent.width() - right.outerWidth());
+                const percent = 100 - right.outerWidth() /parent.width() * 100;
+                left.css('width', percent + '%');
+            } else {
+                left.width(parent.width());
+                right.hide();
+            }
+        };
+        // 展开工具栏、切换标签
+        if (!tab.hasClass('active')) {
+            const close = $('.active', '#side-menu').length === 0;
+            $('a', '#side-menu').removeClass('active');
+            tab.addClass('active');
+            $('.tab-content .tab-pane').removeClass('active');
+            tabPanel.addClass('active');
+            showSideTools(tab.hasClass('active'));
+            if (tab.attr('content') === '#search' && !searchLedger) {
+                if (!searchLedger) {
+                    searchLedger = $.billsSearch({
+                        selector: '#search',
+                        searchSpread: billsSpread,
+                        resultSpreadSetting: {
+                            cols: [
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                                {title: '名称', field: 'name', width: 230, hAlign: 0, formatter: '@', readOnly: true},
+                                {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
+                                {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},
+                                {title: '数量', field: 'quantity', hAlign: 2, width: 50, readOnly: true},
+                            ],
+                            emptyRows: 0,
+                            headRows: 1,
+                            headRowHeight: [40],
+                            defaultRowHeight: 21,
+                        },
+                        afterLocated: function () {
+                            posSpreadObj.loadCurPosData();
+                        }
+                    });
+                }
+                searchLedger.spread.refresh();
+            }
+        }
+        billsSpread.refresh();
+        if (posSpread) {
+            posSpread.refresh();
+        }
+    });
+
+    // 显示层次
+    (function (select, sheet) {
+        $(select).click(function () {
+            if (!sheet.zh_tree) return;
+            const tag = $(this).attr('tag');
+            const tree = sheet.zh_tree;
+            switch (tag) {
+                case "1":
+                case "2":
+                case "3":
+                case "4":
+                case "5":
+                    tree.expandByLevel(parseInt(tag));
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+                case "last":
+                    tree.expandByCustom(() => { return true; });
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+                case "leafXmj":
+                    tree.expandToLeafXmj();
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+            }
+        });
+    })('a[name=showLevel]', billsSheet);
+
+    $('#reviseHistory').change(function () {
+        postData(window.location.pathname + '/info', { rid: this.value }, function (result) {
+            $('#user-name').value(result.user_name);
+            $('#content')[0].textContent = result.content;
+            $('#end-time').value(result.end_time.toLocaleString());
+        });
+    });
+});

+ 3 - 3
app/public/js/stage_compare.js

@@ -56,13 +56,14 @@ function calculateStagePosData(datas) {
 $(document).ready(function () {
     autoFlashHeight();
     // 根据设置整理Spread设置
+    initSpreadSettingWithRoles(scRoles);
     ledgerSpreadSetting.getColor = function (sheet, data, col, defaultColor) {
         function checkDiffer(data) {
             const fieldSufs = sheet.zh_setting.fieldSufs;
             if (fieldSufs.length <= 1) return false;
             const field = data.quantity ? 'gather_qty' : 'gather_tp';
             const base = data[field + fieldSufs[0]];
-            for (let i = 1; i< scRoles.length; i++) {
+            for (let i = 1; i< fieldSufs.length; i++) {
                 if (data[field + fieldSufs[i]] !== base) return true;
             }
         }
@@ -73,13 +74,12 @@ $(document).ready(function () {
             const fieldSufs = sheet.zh_setting.fieldSufs;
             if (fieldSufs.length <= 1) return false;
             const base = data['gather_qty' + fieldSufs[0]];
-            for (let i = 1; i< scRoles.length; i++) {
+            for (let i = 1; i< fieldSufs.length; i++) {
                 if (data['gather_qty' + fieldSufs[i]] !== base) return true;
             }
         }
         return checkDiffer(data) ? '#F2DEDE' : defaultColor;
     };
-    initSpreadSettingWithRoles(scRoles);
     // 初始化台账
     const ledgerSpread = SpreadJsObj.createNewSpread($('#ledger-spread')[0]);
     SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), ledgerSpreadSetting);

+ 28 - 0
app/public/js/stage_detail.js

@@ -8,6 +8,18 @@
  * @version
  */
 
+function needCheckDetail(check = true) {
+    if (check) {
+        stage.check_detail = true;
+        $('#check_point').show();
+        $('#check-detail').show();
+    } else {
+        stage.check_detail = false;
+        $('#check_point').hide();
+        $('#check-detail').hide();
+    }
+}
+
 $(document).ready(() => {
     autoFlashHeight();
     const detailSpreadSetting = {
@@ -145,6 +157,7 @@ $(document).ready(() => {
                     postData(window.location.pathname + '/save', updateData, function (result) {
                         stageIm.loadUpdateDetailData(result);
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        needCheckDetail();
                     }, function () {
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     });
@@ -188,6 +201,7 @@ $(document).ready(() => {
                     postData(window.location.pathname + '/save', datas, function (result) {
                         stageIm.loadUpdateDetailData(result);
                         SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                        needCheckDetail();
                     }, function () {
                         SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
                     })
@@ -216,6 +230,7 @@ $(document).ready(() => {
                     postData(window.location.pathname + '/save', datas, function (result) {
                         stageIm.loadUpdateDetailData(result);
                         SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
+                        needCheckDetail();
                     }, function () {
                         SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
                     });
@@ -257,6 +272,7 @@ $(document).ready(() => {
                 postData(window.location.pathname + '/save', datas, function (result) {
                     stageIm.loadUpdateDetailData(result);
                     SpreadJsObj.reLoadRowData(info.sheet, info.fillRange.row, info.fillRange.rowCount);
+                    needCheckDetail();
                 }, function () {
                     SpreadJsObj.reLoadRowData(info.sheet, info.fillRange.row, info.fillRange.rowCount);
                 })
@@ -367,6 +383,7 @@ $(document).ready(() => {
         postData(window.location.pathname + '/build', data, function (result) {
             stage.im_type = data.im_type;
             stage.im_pre = data.im_pre;
+            needCheckDetail();
             // 加载生成数据
             reBuildImData();
             $('#choose').modal('hide');
@@ -503,6 +520,7 @@ $(document).ready(() => {
         postData(window.location.pathname + '/adv', data, function (result) {
             stage.im_gather = data.im_gather;
             stage.im_gather_node = data.im_gather_node;
+            needCheckDetail();
             $('#choose2').modal('hide');
         });
     });
@@ -568,6 +586,7 @@ $(document).ready(() => {
             $('#unit-name').attr('readonly', '');
             $('#drawing-code').attr('readonly', '');
             $('#calc-memo').attr('readonly', '');
+            needCheckDetail();
         });
     });
     // 取消
@@ -677,6 +696,7 @@ $(document).ready(() => {
                 // $('.img-item').mousedown(moveImageItem);
                 $('.img-bar').click(removeImageItem);
                 setdraggrable();
+                needCheckDetail();
             });
         }
     });
@@ -727,13 +747,21 @@ $(document).ready(() => {
                 _.assign(data, result);
                 $('#calc-img').html('<img src="/' + data.calc_img + '" class="d-100" width="100%">');
                 $('#edit-img').modal('hide');
+                needCheckDetail();
             });
         } else if (data.calc_img) {
             postData(window.location.pathname + '/merge-img', {updateType: 'clear', lid: data.lid, uuid: data.uuid}, function (result) {
                 _.assign(data, result);
                 $('#calc-img').html('');
                 $('#edit-img').modal('hide');
+                needCheckDetail();
             });
         }
     });
+    $('#done-detail').click(function () {
+        postData(window.location.pathname + '/done', {}, function () {
+            needCheckDetail(false);
+            $('#done').modal('hide');
+        })
+    })
 });

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

@@ -143,7 +143,7 @@ $(document).ready(() => {
                 return (stage.status === 1 || stage.status === 4);
             },
             isStarted: function (data) {
-                return ((payCol.readOnly.isNonZero(data.end_tp) || payCol.readOnly.isNonZero(data.tp)) && data.tp !== data.end_tp) || payCol.readOnly.isNonZero(data.pre_tp);
+                return ((payCol.readOnly.isNonZero(data.end_tp) || payCol.readOnly.isNonZero(data.tp)) && data.tp !== data.end_tp) || payCol.readOnly.isNonZero(data.pre_tp) || data.pre_used;
             },
             name: function (data) {
                 return payCol.readOnly.isSpecial(data); //所有人,轮到自己时,均可修改
@@ -211,7 +211,6 @@ $(document).ready(() => {
             setObjEnable($('#del'), !readOnly && select);
             setObjEnable($('#up-move'), !readOnly && select && select.ptype === 1 && dealPay.indexOf(select) > 3);
             setObjEnable($('#down-move'), !readOnly && select && select.ptype === 1 && dealPay.indexOf(select) < dealPay.length - 1);
-            setObjEnable($('#unlock'), !readOnly);
         },
         add: function () {
             const sheet = paySpread.getActiveSheet();

+ 6 - 2
app/router.js

@@ -104,8 +104,13 @@ module.exports = app => {
     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.get('/tender/:id/revise/info', sessionAuth, tenderCheck, 'reviseController.info');
     app.post('/tender/:id/revise/info/update', sessionAuth, tenderCheck, 'reviseController.update');
+
+    app.get('/tender/:id/revise/history', sessionAuth, tenderCheck, 'reviseController.history');
+    app.post('/tender/:id/revise/history/info', sessionAuth, tenderCheck, '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');
@@ -144,8 +149,7 @@ module.exports = app => {
     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/done', sessionAuth, tenderCheck, stageCheck, 'stageController.doneDetail');
-    app.get('/tender/:id/measure/stage/:order/detail/unlock', sessionAuth, tenderCheck, stageCheck, 'stageController.unlockDetail');
+    app.post('/tender/:id/measure/stage/:order/detail/done', sessionAuth, tenderCheck, stageCheck, 'stageController.doneDetail');
     // 合同支付
     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');

+ 6 - 6
app/service/change.js

@@ -327,7 +327,7 @@ module.exports = app => {
                         // 添加短信通知-需要审批提醒功能
                         if (change_status && index === 0) {
                             const smsUser = await this.ctx.service.projectAccount.getDataById(auditInfo[0]);
-                            if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                            if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                                 const smsType = JSON.parse(smsUser.sms_type);
                                 if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                                     const sms = new SMS(this.ctx);
@@ -469,7 +469,7 @@ module.exports = app => {
                     const auditList = await this.ctx.service.changeAudit.getListGroupByTimes(changeData.cid, changeData.times);
                     for (const user of auditList) {
                         const smsUser = await this.ctx.service.projectAccount.getDataById(user.uid);
-                        if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                        if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                             const smsType = JSON.parse(smsUser.sms_type);
                             if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
                                 mobile_array.push(smsUser.auth_mobile);
@@ -492,7 +492,7 @@ module.exports = app => {
                     // 添加短信通知-需要审批提醒功能
                     const nextAuditData = await this.ctx.service.changeAudit.getDataById(postData.audit_next_id);
                     const smsUser = await this.ctx.service.projectAccount.getDataById(nextAuditData.uid);
-                    if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                    if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                         const smsType = JSON.parse(smsUser.sms_type);
                         if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                             const sms = new SMS(this.ctx);
@@ -628,7 +628,7 @@ module.exports = app => {
                 const mobile_array = [];
                 for (const user of insert_audit_array) {
                     const smsUser = await this.ctx.service.projectAccount.getDataById(user.uid);
-                    if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                    if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                         const smsType = JSON.parse(smsUser.sms_type);
                         if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
                             mobile_array.push(smsUser.auth_mobile);
@@ -752,7 +752,7 @@ module.exports = app => {
 
                 // 添加短信通知-需要审批提醒功能
                 const smsUser = await this.ctx.service.projectAccount.getDataById(lastauditInfo.uid);
-                if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                     const smsType = JSON.parse(smsUser.sms_type);
                     if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const sms = new SMS(this.ctx);
@@ -970,7 +970,7 @@ module.exports = app => {
 
                 // 添加短信通知-需要审批提醒功能
                 const smsUser = await this.ctx.service.projectAccount.getDataById(auditInfo.uid);
-                if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                     const smsType = JSON.parse(smsUser.sms_type);
                     if (smsType[smsTypeConst.const.BG] !== undefined && smsType[smsTypeConst.const.BG].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const sms = new SMS(this.ctx);

+ 43 - 36
app/service/ledger_audit.js

@@ -188,7 +188,7 @@ module.exports = app => {
 
                 // 添加短信通知-需要审批提醒功能
                 const smsUser = await this.ctx.service.projectAccount.getDataById(audit.audit_id);
-                if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                     const smsType = JSON.parse(smsUser.sms_type);
                     if (smsType[smsTypeConst.const.TZ] !== undefined && smsType[smsTypeConst.const.TZ].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const tenderInfo = await this.ctx.service.tender.getDataById(tenderId);
@@ -208,22 +208,6 @@ module.exports = app => {
         }
 
         /**
-         * 拷贝一份台账备份(每一次审批结束时)
-         * @param {Number} tenderId - 标段Id
-         * @param transaction - 事务
-         * @param {Number} times - 次数
-         * @returns {Promise<void>}
-         * @private
-         */
-        async _copyHisytoryLedger(tenderId, transaction, times = 1) {
-            const sql = 'Insert Into ?? ' +
-                'Select *, ? As times From ?? ' +
-                'Where ?? = ?';
-            const sqlParam = [this.tableName + '_copy', times, this.ctx.service.ledger.tableName, 'tender_id', tenderId];
-            return await transaction.query(sql, sqlParam);
-        }
-
-        /**
          * 审批
          * @param {Number} tenderId - 标段id
          * @param {auditConst.status.checked|auditConst.status.checkNo} checkType - 审批结果
@@ -253,7 +237,7 @@ module.exports = app => {
 
                         // 添加短信通知-需要审批提醒功能
                         const smsUser = await this.ctx.service.projectAccount.getDataById(nextAudit.audit_id);
-                        if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                        if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                             const smsType = JSON.parse(smsUser.sms_type);
                             if (smsType[smsTypeConst.const.TZ] !== undefined && smsType[smsTypeConst.const.TZ].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                                 const tenderInfo = await this.ctx.service.tender.getDataById(tenderId);
@@ -266,21 +250,33 @@ module.exports = app => {
                     } else {
                         // 同步标段信息
                         await transaction.update(this.ctx.service.tender.tableName, {id: tenderId, ledger_status: checkType});
-                        // 拷贝备份台账数据
-                        await this._copyHisytoryLedger(tenderId, transaction, times);
 
                         // 添加短信通知-审批通过提醒功能
+                        const mobile_array = [];
                         const tenderInfo = await this.ctx.service.tender.getDataById(tenderId);
-                        const smsUser = await this.ctx.service.projectAccount.getDataById(tenderInfo.user_id);
-                        if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
-                            const smsType = JSON.parse(smsUser.sms_type);
+                        const smsUser1 = await this.ctx.service.projectAccount.getDataById(tenderInfo.user_id);
+                        if (smsUser1.auth_mobile !== '' && smsUser1.auth_mobile !== undefined && smsUser1.sms_type !== '') {
+                            const smsType = JSON.parse(smsUser1.sms_type);
                             if (smsType[smsTypeConst.const.TZ] !== undefined && smsType[smsTypeConst.const.TZ].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
-                                const sms = new SMS(this.ctx);
-                                const tenderName = await sms.contentChange(tenderInfo.name);
-                                const content = '【纵横计量支付】' + tenderName + '台账审批通过,请登录系统处理。';
-                                sms.send(smsUser.auth_mobile, content);
+                                mobile_array.push(smsUser1.auth_mobile);
+                            }
+                        }
+                        const auditList = await this.getAuditors(tenderId, times);
+                        for (const user of auditList) {
+                            const smsUser = await this.ctx.service.projectAccount.getDataById(user.audit_id);
+                            if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                                const smsType = JSON.parse(smsUser.sms_type);
+                                if (mobile_array.indexOf(smsUser.auth_mobile) === -1 && smsType[smsTypeConst.const.TZ] !== undefined && smsType[smsTypeConst.const.TZ].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
+                                    mobile_array.push(smsUser.auth_mobile);
+                                }
                             }
                         }
+                        if (mobile_array.length > 0) {
+                            const sms = new SMS(this.ctx);
+                            const tenderName = await sms.contentChange(tenderInfo.name);
+                            const content = '【纵横计量支付】' + tenderName + '台账审批通过,请登录系统处理。';
+                            sms.send(mobile_array, content);
+                        }
                     }
                 } else {
                     // 同步标段信息
@@ -295,21 +291,32 @@ module.exports = app => {
                         a.status = auditConst.status.uncheck;
                     }
                     await transaction.insert(this.tableName, auditors);
-                    // 拷贝备份台账数据
-                    await this._copyHisytoryLedger(tenderId, transaction, times);
 
                     // 添加短信通知-审批退回提醒功能
+                    const mobile_array = [];
                     const tenderInfo = await this.ctx.service.tender.getDataById(tenderId);
-                    const smsUser = await this.ctx.service.projectAccount.getDataById(tenderInfo.user_id);
-                    if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
-                        const smsType = JSON.parse(smsUser.sms_type);
+                    const smsUser1 = await this.ctx.service.projectAccount.getDataById(tenderInfo.user_id);
+                    if (smsUser1.auth_mobile !== '' && smsUser1.auth_mobile !== undefined && smsUser1.sms_type !== '') {
+                        const smsType = JSON.parse(smsUser1.sms_type);
                         if (smsType[smsTypeConst.const.TZ] !== undefined && smsType[smsTypeConst.const.TZ].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
-                            const sms = new SMS(this.ctx);
-                            const tenderName = await sms.contentChange(tenderInfo.name);
-                            const content = '【纵横计量支付】' + tenderName + '台账审批退回,请登录系统处理。';
-                            sms.send(smsUser.auth_mobile, content);
+                            mobile_array.push(smsUser1.auth_mobile);
+                        }
+                    }
+                    for (const user of auditors) {
+                        const smsUser = await this.ctx.service.projectAccount.getDataById(user.audit_id);
+                        if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                            const smsType = JSON.parse(smsUser.sms_type);
+                            if (mobile_array.indexOf(smsUser.auth_mobile) === -1 && smsType[smsTypeConst.const.TZ] !== undefined && smsType[smsTypeConst.const.TZ].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
+                                mobile_array.push(smsUser.auth_mobile);
+                            }
                         }
                     }
+                    if (mobile_array.length > 0) {
+                        const sms = new SMS(this.ctx);
+                        const tenderName = await sms.contentChange(tenderInfo.name);
+                        const content = '【纵横计量支付】' + tenderName + '台账审批退回,请登录系统处理。';
+                        sms.send(mobile_array, content);
+                    }
                 }
 
                 await transaction.commit();

+ 19 - 6
app/service/ledger_revise.js

@@ -30,7 +30,8 @@ module.exports = app => {
          * @returns {Promise<*>} - ledger_change下所有数据,并关联 project_account(读取提交人名称、单位、公司)
          */
         async getReviseList (tid) {
-            const sql = 'SELECT lc.*, pa.name As user_name, pa.role As user_role, pa.company As user_company' +
+            const sql = 'SELECT lc.id, lc.tid, lc.corder, lc.in_time, lc.uid, lc.begin_time, lc.end_time, lc.times, lc.status, lc.valid,' +
+                '    pa.name As user_name, pa.role As user_role, pa.company As user_company' +
                 '  FROM ' + this.tableName + ' As lc' +
                 '  INNER JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa ON lc.uid = pa.id' +
                 '  WHERE lc.tid = ?' +
@@ -41,17 +42,30 @@ module.exports = app => {
             return await this.db.query(sql, sqlParam);
         }
 
-        async getLastestRevise(tid) {
-            const sql = 'SELECT lc.*, pa.name As user_name, pa.role As user_role, pa.company As user_company' +
+        async getLastestRevise(tid, valid = true) {
+            const sql = 'SELECT lc.*,' +
+                '    pa.name As user_name, pa.role As user_role, pa.company As user_company' +
                 '  FROM ' + this.tableName + ' As lc' +
                 '  INNER JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa ON lc.uid = pa.id' +
-                '  WHERE lc.tid = ? And lc.valid' +
+                '  WHERE lc.tid = ? ' + (valid ? ' And lc.valid' : '') +
                 '  ORDER BY lc.in_time DESC' +
                 '  LIMIT 0, 1';
             const sqlParam = [tid];
             return await this.db.queryOne(sql, sqlParam);
         }
 
+        async getRevise(tid, rid) {
+            const sql = 'SELECT lc.*,' +
+                '    pa.name As user_name, pa.role As user_role, pa.company As user_company' +
+                '  FROM ' + this.tableName + ' As lc' +
+                '  INNER JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa ON lc.uid = pa.id' +
+                '  WHERE lc.tid = ? and lc.id = ? ' +
+                '  ORDER BY lc.in_time DESC' +
+                '  LIMIT 0, 1';
+            const sqlParam = [tid, rid];
+            return await this.db.queryOne(sql, sqlParam);
+        }
+
         /**
          * 获取新增修订的序号
          * @param {Number}tid - 标段id
@@ -156,8 +170,7 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async cancelRevise(revise) {
-            const [billsHis, posHis] = await this.ctx.service.reviseAudit.saveReviseHistoryFile(revise);
-            const result = await this.db.update(this.tableName, {id: revise.id, valid: false, bills_file: billsHis, pos_file: posHis});
+            const result = await this.db.update(this.tableName, {id: revise.id, valid: false, end_time: new Date()});
             return result.affectedRows === 1;
         }
 

+ 13 - 31
app/service/revise_audit.js

@@ -174,26 +174,6 @@ module.exports = app => {
         }
 
         /**
-         * 拷贝一份台账备份
-         * @param {Object} revise - 修订
-         * @returns {Promise<void>}
-         * @private
-         */
-        async saveReviseHistoryFile(revise) {
-            const timestamp = (new Date()).getTime();
-
-            const billsHis = '/file/revise/bills' + timestamp + '.json';
-            const bills = await this.ctx.service.reviseBills.getData(revise.tid);
-            await this.ctx.helper.saveBufferFile(JSON.stringify(bills), this.ctx.app.baseDir + billsHis);
-
-            const posHis = '/file/revise/pos' + timestamp + '.json';
-            const pos = await this.ctx.service.revisePos.getData(revise.tid);
-            await this.ctx.helper.saveBufferFile(JSON.stringify(pos), this.ctx.app.baseDir + posHis);
-
-            return [billsHis, posHis];
-        }
-
-        /**
          * 开始审批
          *
          * @param {Object} revise - 修订
@@ -203,16 +183,18 @@ module.exports = app => {
         async start(revise, times = 1) {
             const audit = await this.getDataByCondition({rid: revise.id, times: times, audit_order: 1});
             if (!audit) throw '审核人信息错误';
+            const time = new Date();
 
-            // 拷贝备份台账数据
-            const [billsHis, posHis] = await this.saveReviseHistoryFile(revise);
             const transaction = await this.db.beginTransaction();
             try {
-                await transaction.update(this.tableName, {id: audit.id, status: auditConst.status.checking, begin_time: new Date()});
-                await transaction.update(this.ctx.service.ledgerRevise.tableName, {
+                await transaction.update(this.tableName, {id: audit.id, status: auditConst.status.checking, begin_time: time});
+                const reviseData = {
                     id: revise.id, status: auditConst.status.checking,
-                    bills_file: billsHis, pos_file: posHis,
-                });
+                };
+                if (revise.times === 1) {
+                    reviseData.begin_time = time;
+                }
+                await transaction.update(this.ctx.service.ledgerRevise.tableName, reviseData);
 
                 // 添加短信通知-需要审批提醒功能
                 const smsUser = await this.ctx.service.projectAccount.getDataById(audit.audit_id);
@@ -248,12 +230,12 @@ module.exports = app => {
                 '  Where `tender_id` = ?';
             await transaction.query(bSql, sqlParam);
             await transaction.delete(this.ctx.service.pos.tableName, {tid: revise.tid});
-            const pSql = 'Insert Into ' + this.ctx.service.revisePos.tableName +
+            const pSql = 'Insert Into ' + this.ctx.service.pos.tableName +
                 '  (id, tid, lid, name, drawing_code, quantity, add_stage, add_times, add_user,' +
-                '     sgfh_qty, sjcl_qty, qtcl_qty, crid)' +
+                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder)' +
                 '  Select id, tid, lid, name, drawing_code, quantity, add_stage, add_times, add_user,' +
-                '     sgfh_qty, sjcl_qty, qtcl_qty, crid' +
-                '  From ' + this.ctx.service.pos.tableName +
+                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder' +
+                '  From ' + this.ctx.service.revisePos.tableName +
                 '  Where `tid` = ?';
             await transaction.query(pSql, sqlParam);
         }
@@ -299,7 +281,7 @@ module.exports = app => {
                         }
                     } else {
                         // 同步修订信息
-                        await transaction.update(this.ctx.service.ledgerRevise.tableName, {id: revise.id, status: checkType});
+                        await transaction.update(this.ctx.service.ledgerRevise.tableName, {id: revise.id, status: checkType, end_time: time});
                         // 拷贝修订数据至台账
                         await this._replaceLedgerByRevise(transaction, revise);
 

+ 1 - 0
app/service/stage.js

@@ -160,6 +160,7 @@ module.exports = app => {
                 times: 1,
                 status: auditConst.status.uncheck,
                 user_id: this.ctx.session.sessionUser.accountId,
+                check_detail: true,
             };
             if (preStage) {
                 newStage.im_type = preStage.im_type;

+ 48 - 20
app/service/stage_audit.js

@@ -198,7 +198,7 @@ module.exports = app => {
 
                 // 添加短信通知-需要审批提醒功能
                 const smsUser = await this.ctx.service.projectAccount.getDataById(audit.aid);
-                if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                     const smsType = JSON.parse(smsUser.sms_type);
                     if (smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const tenderInfo = await this.ctx.service.tender.getDataById(audit.tid);
@@ -249,7 +249,7 @@ module.exports = app => {
 
                     // 添加短信通知-需要审批提醒功能
                     const smsUser = await this.ctx.service.projectAccount.getDataById(nextAudit.aid);
-                    if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                    if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                         const smsType = JSON.parse(smsUser.sms_type);
                         if (smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                             const tenderInfo = await this.ctx.service.tender.getDataById(nextAudit.tid);
@@ -275,18 +275,32 @@ module.exports = app => {
                     });
 
                     // 添加短信通知-审批通过提醒功能
+                    const mobile_array = [];
                     const stageInfo = await this.ctx.service.stage.getDataById(stageId);
-                    const smsUser = await this.ctx.service.projectAccount.getDataById(stageInfo.user_id);
-                    if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
-                        const smsType = JSON.parse(smsUser.sms_type);
+                    const auditList = await this.getAuditors(stageId, stageInfo.times);
+                    const smsUser1 = await this.ctx.service.projectAccount.getDataById(stageInfo.user_id);
+                    if (smsUser1.auth_mobile !== undefined && smsUser1.sms_type !== '') {
+                        const smsType = JSON.parse(smsUser1.sms_type);
                         if (smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
-                            const tenderInfo = await this.ctx.service.tender.getDataById(stageInfo.tid);
-                            const sms = new SMS(this.ctx);
-                            const tenderName = await sms.contentChange(tenderInfo.name);
-                            const content = '【纵横计量支付】' + tenderName + '第' + stageInfo.order + '期,审批通过。';
-                            sms.send(smsUser.auth_mobile, content);
+                            mobile_array.push(smsUser1.auth_mobile);
+                        }
+                    }
+                    for (const user of auditList) {
+                        const smsUser = await this.ctx.service.projectAccount.getDataById(user.aid);
+                        if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                            const smsType = JSON.parse(smsUser.sms_type);
+                            if (mobile_array.indexOf(smsUser.auth_mobile) === -1 && smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
+                                mobile_array.push(smsUser.auth_mobile);
+                            }
                         }
                     }
+                    if (mobile_array.length > 0) {
+                        const tenderInfo = await this.ctx.service.tender.getDataById(stageInfo.tid);
+                        const sms = new SMS(this.ctx);
+                        const tenderName = await sms.contentChange(tenderInfo.name);
+                        const content = '【纵横计量支付】' + tenderName + '第' + stageInfo.order + '期,审批通过。';
+                        sms.send(mobile_array, content);
+                    }
                 }
                 await transaction.commit();
             } catch (err) {
@@ -298,7 +312,7 @@ module.exports = app => {
         async _checkNo(stageId, checkData, times) {
             const time = new Date();
             // 整理当前流程审核人状态更新
-            const audit = await this.getDataByCondition({sid: stageId, times: times, status: auditConst.status.checking, check_detail: false});
+            const audit = await this.getDataByCondition({sid: stageId, times: times, status: auditConst.status.checking});
             if (!audit) {
                 throw '审核数据错误';
             }
@@ -332,18 +346,32 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times + 1, 0, transaction);
 
                 // 添加短信通知-审批退回提醒功能
+                const mobile_array = [];
                 const stageInfo = await this.ctx.service.stage.getDataById(stageId);
-                const smsUser = await this.ctx.service.projectAccount.getDataById(stageInfo.user_id);
-                if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
-                    const smsType = JSON.parse(smsUser.sms_type);
+                const auditList = await this.getAuditors(stageId, stageInfo.times);
+                const smsUser1 = await this.ctx.service.projectAccount.getDataById(stageInfo.user_id);
+                if (smsUser1.auth_mobile !== '' && smsUser1.auth_mobile !== undefined && smsUser1.sms_type !== '') {
+                    const smsType = JSON.parse(smsUser1.sms_type);
                     if (smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
-                        const tenderInfo = await this.ctx.service.tender.getDataById(stageInfo.tid);
-                        const sms = new SMS(this.ctx);
-                        const tenderName = await sms.contentChange(tenderInfo.name);
-                        const content = '【纵横计量支付】' + tenderName + '第' + stageInfo.order + '期,审批退回。';
-                        sms.send(smsUser.auth_mobile, content);
+                        mobile_array.push(smsUser1.auth_mobile);
                     }
                 }
+                for (const user of auditList) {
+                    const smsUser = await this.ctx.service.projectAccount.getDataById(user.aid);
+                    if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                        const smsType = JSON.parse(smsUser.sms_type);
+                        if (mobile_array.indexOf(smsUser.auth_mobile) === -1 && smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.result.toString()) !== -1) {
+                            mobile_array.push(smsUser.auth_mobile);
+                        }
+                    }
+                }
+                if (mobile_array.length > 0) {
+                    const tenderInfo = await this.ctx.service.tender.getDataById(stageInfo.tid);
+                    const sms = new SMS(this.ctx);
+                    const tenderName = await sms.contentChange(tenderInfo.name);
+                    const content = '【纵横计量支付】' + tenderName + '第' + stageInfo.order + '期,审批退回。';
+                    sms.send(mobile_array, content);
+                }
 
                 await transaction.commit();
             } catch (err) {
@@ -396,7 +424,7 @@ module.exports = app => {
 
                 // 添加短信通知-需要审批提醒功能
                 const smsUser = await this.ctx.service.projectAccount.getDataById(preAuditor.aid);
-                if (smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
+                if (smsUser.auth_mobile !== '' && smsUser.auth_mobile !== undefined && smsUser.sms_type !== '') {
                     const smsType = JSON.parse(smsUser.sms_type);
                     if (smsType[smsTypeConst.const.JL] !== undefined && smsType[smsTypeConst.const.JL].indexOf(smsTypeConst.judge.approval.toString()) !== -1) {
                         const tenderInfo = await this.ctx.service.tender.getDataById(audit.tid);

+ 0 - 1
app/service/tender.js

@@ -255,7 +255,6 @@ module.exports = app => {
                 await transaction.delete(this.ctx.service.tenderInfo.tableName, {tid: id});
                 await transaction.delete(this.ctx.service.ledger.tableName, {tender_id: id});
                 await transaction.delete(this.ctx.service.ledgerAudit.tableName, {tender_id: id});
-                await transaction.delete(this.ctx.service.ledgerAudit.tableName + '_copy', {tender_id: id});
                 await transaction.delete(this.ctx.service.pos.tableName, {tid: id});
                 await transaction.delete(this.ctx.service.pay.tableName, {tid: id});
                 await transaction.delete(this.ctx.service.stage.tableName, {tid: id});

+ 6 - 0
app/service/valuation.js

@@ -45,10 +45,16 @@ module.exports = app => {
                 where: {id: billsId},
                 columns: ['id', 'name'],
             });
+            billsList.sort(function (a, b) {
+                return billsId.indexOf(a.id) - billsList.indexOf(b.id);
+            });
             const chapterList = await this.db.select('zh_std_xmj_list', {
                 where: {id: chaptersId},
                 columns: ['id', 'name'],
             });
+            chapterList.sort(function (a, b) {
+                return chaptersId.indexOf(a.id) - chapterList.indexOf(b.id);
+            });
             return [billsList, chapterList];
         }
 

+ 117 - 0
app/view/revise/history.ejs

@@ -0,0 +1,117 @@
+<% include ../tender/tender_sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex justify-content-between">
+            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <!--工具-->
+            <div>
+                <div class="d-inline-block">
+                    <div class="dropdown">
+                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                            <i class="fa fa-list-ol"></i> 显示层级
+                        </button>
+                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                            <a class="dropdown-item" name="showLevel" tag="1" href="javascirpt: void(0);">第一层</a>
+                            <a class="dropdown-item" name="showLevel" tag="2" href="javascirpt: void(0);">第二层</a>
+                            <a class="dropdown-item" name="showLevel" tag="3" href="javascirpt: void(0);">第三层</a>
+                            <a class="dropdown-item" name="showLevel" tag="4" href="javascirpt: void(0);">第四层</a>
+                            <a class="dropdown-item" name="showLevel" tag="5" href="javascirpt: void(0);">第五层</a>
+                            <a class="dropdown-item" name="showLevel" tag="last" href="javascirpt: void(0);">最底层</a>
+                            <a class="dropdown-item" name="showLevel" tag="leafXmj" href="javascirpt: void(0);">只显示项目节</a>
+                        </div>
+                    </div>
+                </div>
+                <div class="d-inline-flex">
+                    <%- (revise.in_time ? revise.in_time.toLocaleString() : '') %>
+                </div>
+            </div>
+            <div class="ml-auto">
+                <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm pull-right">审批完成</a>
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap row pr-46">
+        <div class="c-header p-0 col-12"></div>
+        <!--核心内容(两栏)-->
+        <div class="row w-100 sub-content">
+            <!--左栏-->
+            <div class="c-body" id="left-view" style="width: 100%">
+                <!--0号台帐模式-->
+                <div class="sjs-height-1" style="overflow: hidden" id="bills-spread">
+                </div>
+                <div class="bcontent-wrap">
+                    <div id="revise-resize" class="resize-y" id="top-spr" r-Type="height" div1=".sjs-height-1" div2=".bcontent-wrap" title="调整大小"><!--调整上下高度条--></div>
+                    <div class="bc-bar mb-1">
+                        <ul class="nav nav-tabs">
+                            <li class="nav-item">
+                                <a class="nav-link active" href="javascript:void(0)">部位明细</a>
+                            </li>
+                            <li class="nav-item" id="pos-search">
+                            </li>
+                        </ul>
+                    </div>
+                    <div class="sp-wrap" id="pos-spread">
+                    </div>
+                </div>
+            </div>
+            <!--右栏-->
+            <div class="c-body" id="right-view" style="display: none; width: 33%;">
+                <div class="resize-x" id="revise-right-spr" r-Type="width" div1="#left-view" div2="#right-view" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
+                <div class="tab-content">
+                    <div id="xd-content" class="tab-pane">
+                        <div class="sjs-bar-2">
+                            <div class="d-flex"><a href="javascirpt: void(0);" class="btn btn-sm btn-outline-success mb-1 ml-auto" id="save">保存</a></div>
+                        </div>
+                        <div class="sjs-sh-2" style="overflow:auto">
+                            <div class="form-group mt-2">
+                                <label >创建时间</label>
+                                <select class="form-control form-control-sm" id="reviseHistory">
+                                    <% for (const hr of historyRevise) { %>
+                                    <option value="<%- hr.id %>"><%- hr.corder + '#' + (hr.in_time ? hr.in_time.toLocaleDateString() : '') + (hr.valid ? '' : '(作废)')%></option>
+                                    <% } %>
+                                </select>
+                            </div>
+                            <div class="alert alert-warning">历史修订暂不支持查看历史台帐。</div>
+                            <div class="form-group mt-2">
+                                <label >提交人</label>
+                                <input id="user-name" type="" class="form-control" value="<%- revise.user_name %>" disabled>
+                            </div>
+                            <div class="form-group">
+                                <label >修订内容<b class="text-danger">*</b></label>
+                                <textarea id="content" class="form-control" value="编写错漏5" rows="12"><%- revise.content %></textarea>
+                            </div>
+                            <div class="form-group">
+                                <label >审批完成</label>
+                                <input id="end-time" type="" class="form-control" value="<%- (revise.end_time ? revise.end_time.toLocaleString() : '') %>" disabled>
+                            </div>
+                        </div>
+                    </div>
+                    <div id="search" class="tab-pane">
+                    </div>
+                </div>
+            </div>
+        </div>
+        <!--右侧菜单-->
+        <div class="side-menu">
+            <!--右侧菜单-->
+            <ul class="nav flex-column right-nav" id="side-menu">
+                <li class="nav-item">
+                    <a class="nav-link" content="#xd-content" href="javascript: void(0);">修订详情</a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" content="#search" href="javascript: void(0);">查找定位</a>
+                </li>
+            </ul>
+        </div>
+    </div>
+</div>
+<script>
+    <% if (ctx.tender.data.measure_type === measureType.tz.value) { %>
+    const posSpreadSetting = JSON.parse('<%- JSON.stringify(posSpread) %>');
+    const posData = JSON.parse('<%- JSON.stringify(revisePos) %>');
+    <% } %>
+    const readOnly = <%- readOnly %>;
+    const isTz = <%- ctx.tender.data.measure_type === measureType.tz.value %>;
+    const billsSpreadSetting = JSON.parse('<%- JSON.stringify(ledgerSpread) %>');
+    const billsData = JSON.parse('<%- JSON.stringify(reviseBills) %>');
+</script>

+ 6 - 5
app/view/revise/index.ejs

@@ -51,18 +51,19 @@
                     <td><%- lr.end_time ? lr.end_time.toLocaleDateString() : '' %></td>
                     <td>
                         <% if (lr.valid) { %>
-                        <% if (lr.status === auditConst.status.uncheck) { %>
+                        <% if (lr.status === auditConst.status.uncheck && lr.uid === ctx.session.sessionUser.accountId) { %>
                         <a href="<%- preUrl + '/revise/info' %>" class="btn btn-primary btn-sm">修订</a>
                         <a href="#remove" data-toggle="modal" data-target="#remove" class="btn btn-secondary btn-sm">作废</a>
-                        <% } else if (lr.status === auditConst.status.checking) { %>
+                        <% } else if (lr.status === auditConst.status.checking && lr.curAuditor.audit_id === ctx.session.sessionUser.accountId) { %>
                         <a href="<%- preUrl + '/revise/info' %>" class="btn btn-success btn-sm">审批</a>
-                        <% } else if (lr.status === auditConst.status.checkNo) { %>
+                        <% } else if (lr.status === auditConst.status.checkNo && lr.uid === ctx.session.sessionUser.accountId) { %>
                         <a href="<%- preUrl + '/revise/info' %>" class="btn btn-primary btn-sm">重新上报</a>
                         <a href="#remove" data-toggle="modal" data-target="#remove" class="btn btn-secondary btn-sm">作废</a>
-                        <% } else if (ledgerRevise.indexOf(lr) === ledgerRevise.length - 1) { %>
-                        <a href="<%- preUrl + '/revise/info' %>">查看修订内容</a>
                         <% } %>
                         <% } %>
+                        <% if (lr.lastest) { %>
+                        <a href="<%- preUrl + '/revise/history' %>">查看修订内容</a>
+                        <% } %>
                     </td>
                 </tr>
                 <% } %>

+ 4 - 12
app/view/stage/detail.ejs

@@ -13,15 +13,7 @@
             <div class="ml-auto">
                 <!--完成中间计量-->
                 <% if (!ctx.stage.readOnly) { %>
-                    <% if (ctx.stage.check_detail) { %>
-                        <a href="javascirpt: void(0);" data-toggle="modal" data-target="#done" class="btn btn-success btn-sm pull-right">完成本期中间计量</a>
-                    <% } else { %>
-                        <% if (ctx.stage.user_id = ctx.session.sessionUser.accountId) {%>
-                        <span class="text-success" id="locked-hint">请继续完成上报审批。如需修改计量,点击 <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>/detail/unlock">编辑</a></span>
-                        <% } else { %>
-                        <span class="text-success" id="locked-hint">已完成,请继续完成「上报审批」 <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>/detail/unlock">解锁编辑</a></span>
-                        <% } %>
-                    <% } %>
+                <a id="check-detail" href="javascirpt: void(0);" data-toggle="modal" data-target="#done" class="btn btn-success btn-sm pull-right" <% if (!ctx.stage.check_detail) { %>style="display: none"<% } %>>完成本期中间计量</a>
                 <% } %>
             </div>
         </div>
@@ -51,7 +43,7 @@
                 <div class="tab-content">
                     <div class="tab-pane active" id="zhongjian">
                         <div class="sjs-sh-1" style="overflow: auto;">
-                            <% if (!stage.readOnly && stage.check_detail) { %>
+                            <% if (!stage.readOnly) { %>
                             <div class="d-flex justify-content-end mt-1 mr-1">
                                 <a href="javascript: void(0);" class="btn btn-sm btn-outline-primary" id="edit-detail">编辑</a>
                                 <a href="javascript: void(0);" class="btn btn-sm btn-outline-success mr-1" id="save-detail" style="display: none;">保存</a>
@@ -89,7 +81,7 @@
                             <div class="form-group">
                                 <div class="d-flex justify-content-between my-3">
                                     <label>计算草图:</label>
-                                    <% if (!stage.readOnly && stage.check_detail) { %>
+                                    <% if (!stage.readOnly) { %>
                                     <a href="#edit-img" data-toggle="modal" data-target="#edit-img" id="modify-img">添加草图</a>
                                     <% } %>
                                 </div>
@@ -138,7 +130,7 @@
     </div>
 </div>
 <script>
-    const readOnly = <%- (stage.readOnly || !stage.check_detail) %>;
+    const readOnly = <%- (stage.readOnly) %>;
     const stage = JSON.parse('<%- JSON.stringify(ctx.stage) %>');
     const imType = JSON.parse('<%- JSON.stringify(imType) %>');
 </script>

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

@@ -139,7 +139,7 @@
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>/detail/done" class="btn btn-success" >确认完成</a>
+                <a id="done-detail" href="javascript: void(0);" class="btn btn-success" >确认完成</a>
             </div>
         </div>
     </div>

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

@@ -34,10 +34,6 @@
                 </div>
             </div>
             <div class="ml-auto">
-                <!--完成中间计量-->
-                <% if (!ctx.stage.check_detail && !ctx.stage.readOnly) { %>
-                <span class="text-success" id="locked-hint">已完成,请继续完成「上报审批」 <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>/detail/unlock">解锁编辑</a></span>
-                <% } %>
             </div>
         </div>
     </div>

+ 1 - 1
app/view/tender/tender_sub_menu.ejs

@@ -1,7 +1,7 @@
 <div class="panel-sidebar" id="sub-menu">
     <div class="panel-title">
         <div class="title-bar">
-            <h2 class="text-truncate" data-toggle="tooltip" data-placement="right" title=""  data-original-title="<%- tender.name %>"><%- tender.name %></h2>
+            <h2 class="text-truncate" data-toggle="tooltip" data-placement="right" title=""  data-original-title="<%- ctx.tender.data.name %>"><%- ctx.tender.data.name %></h2>
         </div>
     </div>
     <div class="scrollbar-auto">

+ 36 - 0
config/web.js

@@ -146,6 +146,42 @@ const JsFiles = {
                 mergeFile: 'revise',
             },
         },
+        revise: {
+            info: {
+                files: [
+                    "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
+                    "/public/js/toastr.min.js",
+                ],
+                mergeFiles: [
+                    "/public/js/sub_menu.js",
+                    "/public/js/div_resizer.js",
+                    "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/ledger_search.js",
+                    "/public/js/zh_calc.js",
+                    "/public/js/path_tree.js",
+                    "/public/js/revise.js",
+                ],
+                mergeFile: 'revise',
+            },
+            history: {
+                files: [
+                    "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
+                    "/public/js/toastr.min.js",
+                ],
+                mergeFiles: [
+                    "/public/js/sub_menu.js",
+                    "/public/js/div_resizer.js",
+                    "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/ledger_search.js",
+                    "/public/js/zh_calc.js",
+                    "/public/js/path_tree.js",
+                    "/public/js/revise_history.js",
+                ],
+                mergeFile: 'revise_history',
+            }
+        },
         stage: {
             // 本期计量台账
             index: {