Browse Source

1. 中间计量排序问题
2. 清单对比,相关变更令
3. 清单汇总,相关变更令

MaiXinRong 11 months ago
parent
commit
3df11e5ab9

+ 22 - 1
app/controller/ledger_controller.js

@@ -707,6 +707,26 @@ module.exports = app => {
             }
         }
 
+        async _getChangeData(ctx) {
+            const change = await ctx.service.change.getAllDataByCondition({
+                columns: [ 'cid', 'code', 'name', 'w_code' ],
+                where: { tid: ctx.tender.id, valid: 1, status: audit.flow.status.checked },
+                orders: [['code', 'asc']],
+            });
+            const changeBills = await ctx.service.changeAuditList.getAllDataByCondition({
+                columns: [ 'cid', 'code', 'name', 'unit', 'unit_price', 'oamount', 'checked_amount', 'checked_price' ],
+                where: { tid: ctx.tender.id }
+            });
+            const changeIndex = {};
+            change.forEach(x => { changeIndex[x.cid] = x; x.bills = [] });
+            changeBills.forEach(cb => {
+                const c = changeIndex[cb.cid];
+                if (!c) return;
+                c.bills.push(cb);
+            });
+            return change;
+        }
+
         /**
          * 获取 台账对比 数据 (Ajax)
          * @param ctx
@@ -720,10 +740,11 @@ module.exports = app => {
                 const dealBills = await ctx.service.dealBills.getAllDataByCondition({ where: { tender_id: this.ctx.tender.id } });
                 const ancGcl = this.ctx.tender.data.measure_type === measureType.tz.value
                     ? await ctx.service.ancillaryGcl.getAllDataByCondition({ where: { tid: ctx.tender.id } }) : [];
+                const change = await this._getChangeData(ctx);
                 const zlj = JSON.parse(JSON.stringify(stdConst.zlj));
                 zlj.deal_bills_tp = ctx.tender.info.deal_param.zanLiePrice;
                 ctx.body = { err: 0, msg: '', data: {
-                    bills: billsData, pos: posData, ancGcl, dealBills, spec: {zlj: zlj, jrg: stdConst.jrg},
+                    bills: billsData, pos: posData, ancGcl, dealBills, change, spec: {zlj: zlj, jrg: stdConst.jrg},
                 }};
             } catch (err) {
                 this.log(err);

+ 29 - 1
app/controller/stage_controller.js

@@ -334,6 +334,26 @@ module.exports = app => {
             return await ctx.service.stageChange.getLastestAllStageData(ctx.tender.id, ctx.stage.id);
         }
 
+        async _getChangeData(ctx) {
+            const change = await ctx.service.change.getAllDataByCondition({
+                columns: [ 'cid', 'code', 'name', 'w_code' ],
+                where: { tid: ctx.tender.id, valid: 1, status: changeAudit.status.checked },
+                orders: [['code', 'asc']],
+            });
+            const changeBills = await ctx.service.changeAuditList.getAllDataByCondition({
+                columns: [ 'id', 'cid', 'code', 'name', 'unit', 'unit_price', 'oamount', 'checked_amount', 'checked_price' ],
+                where: { tid: ctx.tender.id }
+            });
+            const changeIndex = {};
+            change.forEach(x => { changeIndex[x.cid] = x; x.bills = [] });
+            changeBills.forEach(cb => {
+                const c = changeIndex[cb.cid];
+                if (!c) return;
+                c.bills.push(cb);
+            });
+            return change;
+        }
+
         async getStageData(ctx) {
             try {
                 const data = JSON.parse(ctx.request.body.data);
@@ -365,8 +385,16 @@ module.exports = app => {
                             responseData.data.detailData = await this._getStageDetailData(ctx);
                             responseData.data.detailAtt = await this.ctx.service.stageDetailAtt.getStageData(ctx.stage.id, ctx.stage.im_type);
                             break;
+                        case 'stageChange':
+                            responseData.data.stageChange = await this._getStageChangeData(ctx);
+                            break;
                         case 'change':
-                            responseData.data.changeData = await this._getStageChangeData(ctx);
+                            responseData.data.change = await this._getChangeData(ctx);
+                            break;
+                        case 'preStageChange':
+                            responseData.data.preStageChange = ctx.stage.preCheckedStage
+                                ? await this.ctx.service.stageChangeFinal.getEndStageData(ctx.tender.id, ctx.stage.preCheckedStage.order)
+                                : [];
                             break;
                         case 'changeBills':
                             responseData.data.changeBills = await this.ctx.service.changeAuditList.checkedChangeBills(ctx.stage.tid);

+ 1 - 1
app/lib/stage_im.js

@@ -1037,7 +1037,7 @@ class StageIm {
     _sortImData() {
         const st = (['fj', 'sz'].indexOf(this.tender.s_type) > 0 && [imType.zl.value, imType.bw.value].indexOf(stage.im_type) >= 0)
             ? SortType.TZ
-            : (stage.im_type !== imType.tz.value && stage.im_type !== imType.bb.value ? SortType.TZ : SortType.GCL);
+            : (stage.im_type !== imType.tz.value && stage.im_type !== imType.bb.value ? SortType.GCL : SortType.TZ);
         if (st === SortType.GCL) {
             const helper = this.ctx.helper;
             this.ImData.sort(function(x, y) {

+ 49 - 12
app/public/js/gcl_gather.js

@@ -87,10 +87,26 @@ const gclGatherModel = (function () {
         deal = dealBills;
     }
 
-    function loadChangeBillsData(data) {
+    function loadChangeData(data) {
         change = data;
     }
 
+    function loadStageChangeData(cur, pre) {
+        const gatherDatas = function(datas, field) {
+            for (const d of datas) {
+                const c = change.find(x => { return x.cid === d.cid; });
+                if (!c) continue;
+
+                const cb = c.bills.find(x => { return x.id === d.cbid; });
+                if (!cb) continue;
+
+                cb[field] = ZhCalc.add(cb[field], d.qty);
+            }
+        };
+        gatherDatas(cur, 'cur_qty');
+        gatherDatas(pre, 'pre_qty');
+    }
+
     function gatherfields(obj, src, fields) {
         if (obj && src) {
             if (fields instanceof Array) {
@@ -121,6 +137,7 @@ const gclGatherModel = (function () {
             org_price: node.org_price,
             leafXmjs: [],
             ancGcl: [],
+            change: [],
         };
         gclList.push(gcl);
         return gcl;
@@ -375,15 +392,28 @@ const gclGatherModel = (function () {
         }
     }
 
-    function gatherChangeBillsData() {
-        if (change && change.length > 0) {
-            for (const node of change) {
-                node.b_code = node.code;
-                node.quantity = parseFloat(node.samount);
-                node.total_price = ZhCalc.mul(node.quantity, node.unit_price, node.tp_decimal || tpDecimal);
-                const gcl = getGclNode(node);
-                gcl.change_bills_qty = ZhCalc.add(gcl.change_bills_qty, node.quantity);
-                gcl.change_bills_tp = ZhCalc.add(gcl.change_bills_tp, node.total_price);
+    function gatherChangeData() {
+        if (!change || change.length === 0) return;
+        for (const c of change) {
+            const decimal = c.tp_decimal || tpDecimal;
+            for (const cb of c.bills) {
+                cb.b_code = cb.code;
+                const gcl = getGclNode(cb);
+                gcl.change_bills_qty = ZhCalc.add(gcl.change_bills_qty, cb.checked_amount);
+                gcl.change_bills_tp = ZhCalc.add(gcl.change_bills_tp, cb.checked_price);
+
+                let gcb = gcl.change.find(x => { return x.cid === cb.cid; });
+                if (!gcb) {
+                    gcb = { cid: c.cid, code: c.code, name: c.name };
+                    gcl.change.push(gcb);
+                }
+                gcb.org_qty = ZhCalc.add(gcb.org_qty, cb.oamount);
+                gcb.org_tp = ZhCalc.add(gcb.org_tp, ZhCalc.mul(cb.oamount, gcl.unit_price, decimal));
+                gcb.c_qty = ZhCalc.add(gcb.c_qty, cb.checked_amount);
+                gcb.c_tp = ZhCalc.add(gcb.c_tp, cb.checked_price);
+
+                gcb.cur_qty = ZhCalc.add(gcb.cur_qty, cb.cur_qty);
+                gcb.pre_qty = ZhCalc.add(gcb.pre_qty, cb.pre_qty);
             }
         }
     }
@@ -441,6 +471,12 @@ const gclGatherModel = (function () {
                 xmj.end_gather_percent = ZhCalc.mul(ZhCalc.div(xmj.end_gather_qty, xmj.end_final_qty), 100, 2);
                 xmj.end_final_1_percent = ZhCalc.mul(ZhCalc.div(xmj.end_gather_qty, xmj.end_final_1_qty), 100, 2);
             }
+            for (const c of gcl.change) {
+                c.cur_tp = ZhCalc.mul(c.cur_qty, gcl.unit_price, tpDecimal);
+                c.pre_tp = ZhCalc.mul(c.pre_qty, gcl.unit_price, tpDecimal);
+                c.end_qty = ZhCalc.add(c.cur_qty, c.end_qty);
+                c.end_tp = ZhCalc.add(c.cur_tp, c.end_tp);
+            }
             gcl.settle_status = settle_status.length === 1 ? settle_status[0] : 1;
         }
     }
@@ -488,7 +524,7 @@ const gclGatherModel = (function () {
         }
         recursiveGatherGclData(gsTree.children, null);
         gatherDealBillsData();
-        gatherChangeBillsData();
+        gatherChangeData();
         calculateGatherData();
         gclList.sort(function (a, b) {
             return compareCode(a.b_code, b.b_code) || ZhCalc.sub(a.unit_price, b.unit_price);
@@ -686,7 +722,8 @@ const gclGatherModel = (function () {
         loadPosData,
         loadAncillaryGclData,
         loadDealBillsData,
-        loadChangeBillsData,
+        loadChangeData,
+        loadStageChangeData,
         gatherGclData,
         checkDiffer,
         gatherChapterData,

+ 59 - 27
app/public/js/ledger_gather.js

@@ -160,6 +160,33 @@ $(document).ready(() => {
     const gatherAncGclSheet = gatherAncGclSpread.getActiveSheet();
     SpreadJsObj.initSheet(gatherAncGclSheet, gatherAncGclSpreadSetting);
 
+    const changeSpread = SpreadJsObj.createNewSpread($('#change-spread')[0]);
+    const changeSpreadSetting = {
+        cols: [
+            {title: '变更令号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 100, formatter: '@'},
+            {title: '变更名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 100, formatter: '@'},
+            {title: '原设计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'org_qty', hAlign: 2, width: 100, formatter: '@'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'org_tp', hAlign: 2, width: 100, formatter: '@'},
+            {title: '批复变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'c_qty', hAlign: 2, width: 100, formatter: '@'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'c_tp', hAlign: 2, width: 100, formatter: '@'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        headColWidth: [30],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+        localCache: {
+            key: 'ledger-gather-change',
+            colWidth: true,
+        },
+    };
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(changeSpreadSetting);
+    const changeSheet = changeSpread.getActiveSheet();
+    SpreadJsObj.initSheet(changeSheet, changeSpreadSetting);
+
     let gclGatherData;
     // 获取项目节数据
     function loadLeafXmjData(iGclRow) {
@@ -190,6 +217,28 @@ $(document).ready(() => {
             SpreadJsObj.loadSheetData(gatherAncGclSheet, SpreadJsObj.DataType.Data, []);
         }
     }
+    function loadChangeData(iGclRow) {
+        const gcl = iGclRow ? gclGatherData[iGclRow] : SpreadJsObj.getSelectObject(gclSheet);
+        SpreadJsObj.resetTopAndSelect(changeSheet);
+        if (gcl) {
+            console.log(gcl.change);
+            SpreadJsObj.loadSheetData(changeSheet, SpreadJsObj.DataType.Data, gcl.change);
+        } else {
+            SpreadJsObj.loadSheetData(changeSheet, SpreadJsObj.DataType.Data, []);
+        }
+    }
+    function loadGclGatherRelaData(iGclRow) {
+        loadLeafXmjData(iGclRow);
+        loadChangeData(iGclRow);
+        loadGatherLeafXmjData(iGclRow);
+        loadGatherAncGclData(iGclRow);
+    }
+    function refreshRelaSpread() {
+        leafXmjSpread.refresh();
+        gatherLeafXmjSpread.refresh();
+        gatherAncGclSpread.refresh();
+        changeSpread.refresh();
+    }
     // 标红显示 签约-台账≠0
     function checkCompareData() {
         const sheet = gclSheet;
@@ -204,14 +253,12 @@ $(document).ready(() => {
             }
         }
         SpreadJsObj.endMassOperation(gclSheet);
-    }    
+    }
     // 切换清单行,读取所属项目节数据
     gclSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
         const iNewRow = info.newSelections[0].row;
         if (!info.oldSelections || iNewRow !== info.oldSelections[0].row) {
-            loadLeafXmjData(iNewRow);
-            loadGatherLeafXmjData(iNewRow);
-            loadGatherAncGclData(iNewRow);
+            loadGclGatherRelaData(iNewRow);
         }
     });
 
@@ -245,6 +292,7 @@ $(document).ready(() => {
         gclGatherModel.loadPosData(data.pos);
         gclGatherModel.loadDealBillsData(data.dealBills);
         gclGatherModel.loadAncillaryGclData(data.ancGcl);
+        gclGatherModel.loadChangeData(data.change);
         gclGatherData = gclGatherModel.gatherGclData();
         gclGatherModel.checkDiffer(gclGatherData);
         gclGatherModel.reGatherLeafXmj();
@@ -256,9 +304,7 @@ $(document).ready(() => {
         }
         SpreadJsObj.loadSheetData(gclSheet, SpreadJsObj.DataType.Data, gclGatherData);
         checkCompareData();
-        loadLeafXmjData(0);
-        loadGatherLeafXmjData(0);
-        loadGatherAncGclData(0);
+        loadGclGatherRelaData(0);
 
         const chapterData = gclGatherModel.gatherChapterData(chapter, data.spec, ['total_price']);
         for (const c of chapterData) {
@@ -304,9 +350,7 @@ $(document).ready(() => {
                 (data.name && data.name.indexOf(keyword) > -1);
         },
         afterLocated: function () {
-            loadLeafXmjData();
-            loadGatherLeafXmjData();
-            loadGatherAncGclData();
+            loadGclGatherRelaData();
         },
         calcSum: function (result) {
             const sum = { name: '合计', searchIndex: -1 };
@@ -334,9 +378,7 @@ $(document).ready(() => {
             showTools(tab.hasClass('active'));
         }
         gclSpread.refresh();
-        leafXmjSpread.refresh();
-        gatherLeafXmjSpread.refresh();
-        gatherAncGclSpread.refresh();
+        refreshRelaSpread();
     });
 
     // 下部设置显示相关
@@ -350,11 +392,7 @@ $(document).ready(() => {
                 $(ot).hide();
             }
         }
-        setTimeout(function() {
-            leafXmjSpread.refresh();
-            gatherLeafXmjSpread.refresh();
-            gatherAncGclSpread.refresh();
-        }, 100);
+        setTimeout(refreshRelaSpread, 100);
     });
     $('[name=gather-xmj]').change(function() {
         const checkOption = $('[name=gather-xmj]:checked');
@@ -408,9 +446,7 @@ $(document).ready(() => {
             }
             autoFlashHeight();
             gclSpread.refresh();
-            leafXmjSpread.refresh();
-            gatherLeafXmjSpread.refresh();
-            gatherAncGclSpread.refresh();
+            refreshRelaSpread();
         }
     });
     $.divResizer({
@@ -419,18 +455,14 @@ $(document).ready(() => {
             gclSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
             $(".sp-wrap").height(bcontent-30);
-            leafXmjSpread.refresh();
-            gatherLeafXmjSpread.refresh();
-            gatherAncGclSpread.refresh();
+            refreshRelaSpread();
         }
     });
     $.divResizer({
         select: '#right-spr',
         callback: function () {
             gclSpread.refresh();
-            leafXmjSpread.refresh();
-            gatherLeafXmjSpread.refresh();
-            gatherAncGclSpread.refresh();
+            refreshRelaSpread();
         }
     });
     $('#exportExcel').click(function () {

+ 2 - 2
app/public/js/sr_detail.js

@@ -519,7 +519,7 @@ $(document).ready(() => {
     });
 
     // 加载计量单元数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
-    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;change;tag;sumDeal' }, function (result) {
+    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;stageChange;tag;sumDeal' }, function (result) {
         for (const l of result.ledgerData) {
             if (!l.is_leaf) continue;
             const sd = result.sumDeal.find(x => { return x.code === l.b_code && x.name === l.name && x.unit === l.unit; });
@@ -546,7 +546,7 @@ $(document).ready(() => {
         SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
         // 加载中间计量
         stageIm.init(relaStage, imType, tenderInfo.decimal);
-        stageIm.loadData4Rela(result.ledgerData, result.posData, result.detailData, result.changeData, result.detailAtt);
+        stageIm.loadData4Rela(result.ledgerData, result.posData, result.detailData, result.stageChange, result.detailAtt);
     }, null, true);
     spSpread.bind(spreadNS.Events.SelectionChanged, stagePosSpreadObj.selectionChanged);
 

+ 2 - 2
app/public/js/stage.js

@@ -2325,7 +2325,7 @@ $(document).ready(() => {
     });
 
     // 加载计量单元数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
-    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;change;import_change;tag' }, function (result) {
+    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;stageChange;import_change;tag' }, function (result) {
         // 加载树结构
         stageTree.loadDatas(result.ledgerData, result.locked);
         if (stage.assist) stageTree.loadFilter(stage.assist.ass_ledger_id);
@@ -2355,7 +2355,7 @@ $(document).ready(() => {
         });
         // 加载中间计量
         stageIm.init(tender, stage, imType, tenderInfo.decimal, stage.assist ? stage.assist.ass_ledger_id : '');
-        stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.changeData, result.import_change, result.detailAtt);
+        stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.stageChange, result.import_change, result.detailAtt);
 
         errorList.loadHisErrorData();
         checkList.loadHisCheckData();

+ 62 - 14
app/public/js/stage_gather.js

@@ -75,6 +75,39 @@ $(document).ready(function () {
     const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
     SpreadJsObj.initSheet(gatherLeafXmjSheet, gatherLeafXmjSpreadSetting);
 
+    const changeSpread = SpreadJsObj.createNewSpread($('#change-spread')[0]);
+    const changeSpreadSetting = {
+        cols: [
+            {title: '变更令号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 100, formatter: '@'},
+            {title: '变更名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 150, formatter: '@'},
+            {title: '原设计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'org_qty', hAlign: 2, width: 80, formatter: '@'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'org_tp', hAlign: 2, width: 80, formatter: '@'},
+            {title: '批复变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'c_qty', hAlign: 2, width: 80, formatter: '@'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'c_tp', hAlign: 2, width: 80, formatter: '@'},
+            {title: '本期变更数量', colSpan: '1', rowSpan: '2', field: 'cur_qty', hAlign: 2, width: 100, formatter: '@'},
+            {title: '截止本期变更数量', colSpan: '1', rowSpan: '2', field: 'end_qty', hAlign: 2, width: 100, formatter: '@'},
+            // {title: '本期计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'cur_qty', hAlign: 2, width: 80, formatter: '@'},
+            // {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'cur_tp', hAlign: 2, width: 80, formatter: '@'},
+            // {title: '截止本期计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qty', hAlign: 2, width: 80, formatter: '@'},
+            // {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_tp', hAlign: 2, width: 80, formatter: '@'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        headColWidth: [30],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+        localCache: {
+            key: 'ledger-gather-change',
+            colWidth: true,
+        },
+    };
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(changeSpreadSetting);
+    const changeSheet = changeSpread.getActiveSheet();
+    SpreadJsObj.initSheet(changeSheet, changeSpreadSetting);
+
     let gclGatherData;
     // 获取项目节数据
     function loadLeafXmjData(iGclRow) {
@@ -95,6 +128,25 @@ $(document).ready(function () {
             SpreadJsObj.loadSheetData(gatherLeafXmjSheet, SpreadJsObj.DataType.Data, []);
         }
     }
+    function loadChangeData(iGclRow) {
+        const gcl = iGclRow ? gclGatherData[iGclRow] : SpreadJsObj.getSelectObject(gclSheet);
+        SpreadJsObj.resetTopAndSelect(changeSheet);
+        if (gcl) {
+            SpreadJsObj.loadSheetData(changeSheet, SpreadJsObj.DataType.Data, gcl.change);
+        } else {
+            SpreadJsObj.loadSheetData(changeSheet, SpreadJsObj.DataType.Data, []);
+        }
+    }
+    function loadRelaData(iGclRow) {
+        loadLeafXmjData(iGclRow);
+        loadGatherLeafXmjData(iGclRow);
+        loadChangeData(iGclRow);
+    }
+    function refreshRelaSpread() {
+        leafXmjSpread.refresh();
+        gatherLeafXmjSpread.refresh();
+        changeSpread.refresh();
+    }
     // 超计显示
     function checkOverRange(data) {
         const billsGatherOver = function (data, qtyField, tpField, per) {
@@ -124,10 +176,7 @@ $(document).ready(function () {
     // 切换清单行,读取所属项目节数据
     gclSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
         const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
-        if (iNewRow !== iOldRow) {
-            loadLeafXmjData(iNewRow);
-            loadGatherLeafXmjData(iNewRow);
-        }
+        if (iNewRow !== iOldRow) loadRelaData(iNewRow);
     });
     $('.custom-radio').click(() => {
         setLocalCache('StageGatherOverType', $('input[name=customRadio]:checked').attr('id'));
@@ -143,21 +192,21 @@ $(document).ready(function () {
         SpreadJsObj.reLoadSheetData(gclSpread.getActiveSheet());
     });
 
-    postData(preUrl + '/load', { filter: 'ledger;pos;dealBills;spec;changeBills' }, function (result) {
+    postData(preUrl + '/load', { filter: 'ledger;pos;dealBills;spec;change;stageChange;preStageChange' }, function (result) {
         // 解析清单汇总数据
         gclGatherModel.loadDecimal(tenderDecimal);
         gclGatherModel.loadLedgerData(result.ledgerData);
         gclGatherModel.loadPosData(result.posData);
         gclGatherModel.loadDealBillsData(result.dealBills);
-        gclGatherModel.loadChangeBillsData(result.changeBills);
+        gclGatherModel.loadChangeData(result.change);
+        gclGatherModel.loadStageChangeData(result.stageChange, result.preStageChange);
         gclGatherData = gclGatherModel.gatherGclData();
         gclGatherModel.checkDiffer(gclGatherData);
         gclGatherModel.reGatherLeafXmj();
         checkOverRange(gclGatherData);
         // 加载清单数据
         SpreadJsObj.loadSheetData(gclSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gclGatherData);
-        loadLeafXmjData(0);
-        loadGatherLeafXmjData(0);
+        loadRelaData(0);
         // 章节合计
         const chapterData = gclGatherModel.gatherChapterData(chapter, result.spec, ['total_price', 'contract_tp', 'qc_tp', 'pre_contract_tp', 'pre_qc_tp', 'contract_pc_tp', 'qc_pc_tp', 'pc_tp']);
         for (const c of chapterData) {
@@ -209,8 +258,7 @@ $(document).ready(function () {
             showTools(tab.hasClass('active'));
         }
         gclSpread.refresh();
-        leafXmjSpread.refresh();
-        gatherLeafXmjSpread.refresh();
+        refreshRelaSpread();
     });
     // 下部设置显示相关
     $('a', '[name=pos-tab]').click(function() {
@@ -223,6 +271,7 @@ $(document).ready(function () {
                 $(ot).hide();
             }
         }
+        setTimeout(refreshRelaSpread, 100);
     });
     $('[name=gather-xmj]').change(function() {
         const checkOption = $('[name=gather-xmj]:checked');
@@ -249,14 +298,14 @@ $(document).ready(function () {
             gclSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
             $(".sp-wrap").height(bcontent-30);
-            leafXmjSpread.refresh();
+            refreshRelaSpread();
         }
     });
     $.divResizer({
         select: '#right-spr',
         callback: function () {
             gclSpread.refresh();
-            leafXmjSpread.refresh();
+            refreshRelaSpread();
         }
     });
     // 导航栏
@@ -275,8 +324,7 @@ $(document).ready(function () {
             }
             autoFlashHeight();
             gclSpread.refresh();
-            leafXmjSpread.refresh();
-            gatherLeafXmjSpread.refresh();
+            refreshRelaSpread();
         }
     });
     $('#exportExcel').click(function () {

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

@@ -958,7 +958,7 @@ const stageIm = (function () {
     function _sortImData() {
         const st = (['fj', 'sz'].indexOf(tender.s_type) > 0 && [imType.zl.value, imType.bw.value].indexOf(stage.im_type) >= 0)
             ? SortType.TZ
-            : (stage.im_type !== imType.tz.value && stage.im_type !== imType.bb.value ? SortType.TZ : SortType.GCL);
+            : (stage.im_type !== imType.tz.value && stage.im_type !== imType.bb.value ? SortType.GCL : SortType.TZ);
         if (st === SortType.GCL) {
             ImData.sort(function (x, y) {
                 const iCode = compareCode(x.code, y.code);

+ 35 - 3
app/service/ledger_att.js

@@ -58,6 +58,7 @@ module.exports = app => {
             return result.affectedRows === 1;
         }
 
+
         /**
          * 获取所有附件
          * @param {int} tid - 标段id
@@ -65,9 +66,12 @@ module.exports = app => {
          */
         async getDataByTenderId(tid) {
             const sql = 'SELECT att.id, att.lid, att.uid, att.filepath, att.filename, att.fileext, att.filesize, att.extra_upload, att.remark, att.in_time,' +
-                ' pa.name as `username`, leg.name as `lname`, leg.code as `code`, leg.ledger_id as `ledger_id`, leg.b_code as `b_code`' +
-                ' FROM ?? AS att,?? AS pa,?? AS leg' +
-                ' WHERE leg.id = att.lid AND pa.id = att.uid AND att.tid = ? ORDER BY att.id DESC';
+                '     pa.name as `username`, leg.name as `lname`, leg.code as `code`, leg.ledger_id as `ledger_id`, leg.b_code as `b_code`' +
+                '  FROM ?? AS att ' +
+                '    LEFT JOIN ?? AS pa ON att.uid = pa.id ' +
+                '    LEFT JOIN ?? AS leg ON leg.id = att.lid ' +
+                '  WHERE att.tid = ? and revising = 0 and settle_id = -1' +
+                '  ORDER BY att.id DESC';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.ctx.service.ledger.tableName, tid];
             return await this.db.query(sql, sqlParam);
         }
@@ -172,6 +176,34 @@ module.exports = app => {
             }
             return result;
         }
+
+        async getReviseViewData(tid, rid) {
+            const sql = 'SELECT att.id, att.lid, att.uid, att.filepath, att.filename, att.fileext, att.filesize, att.extra_upload, att.remark, att.in_time,' +
+                ' pa.name as `username`' +
+                ' FROM ' + this.tableName + ' att Left Join ' + this.ctx.service.projectAccount.tableName + ' pa On pa.id = att.uid' +
+                ' WHERE att.tid = ? AND att.revise_id = ? ORDER BY att.id DESC';
+            const result = await this.db.query(sql, [tid, rid]);
+            for (const r of result) {
+                r.filepath = this.ctx.app.config.fujianOssPath + r.filepath;
+                if (this.ctx.helper.canPreview(r.fileext)) r.viewpath = r.filepath;
+                r.in_time = this.ctx.moment(r.in_time * 1000).format('YYYY-MM-DD');
+            }
+            return result;
+        }
+
+        async getLedgerViewData(tid) {
+            const sql = 'SELECT att.id, att.lid, att.uid, att.filepath, att.filename, att.fileext, att.filesize, att.extra_upload, att.remark, att.in_time,' +
+                ' pa.name as `username`' +
+                ' FROM ' + this.tableName + ' att Left Join ' + this.ctx.service.projectAccount.tableName + ' pa On pa.id = att.uid' +
+                ' WHERE att.tid = ? AND att.revising = 0 ORDER BY att.id DESC';
+            const result = await this.db.query(sql, [tid]);
+            for (const r of result) {
+                r.filepath = this.ctx.app.config.fujianOssPath + r.filepath;
+                if (this.ctx.helper.canPreview(r.fileext)) r.viewpath = r.filepath;
+                r.in_time = this.ctx.moment(r.in_time * 1000).format('YYYY-MM-DD');
+            }
+            return result;
+        }
     }
     return LedgerAtt;
 };

+ 5 - 0
app/service/stage_change_final.js

@@ -25,6 +25,11 @@ module.exports = app => {
             this.tableName = 'stage_change_final';
         }
 
+        async getEndStageData(tid, sorder) {
+            const sql = `SELECT cid, cbid, qty FROM ${this.tableName} WHERE tid = ? AND sorder <= ?`;
+            return await this.db.query(sql, [tid, sorder]);
+        }
+
         /**
          * 获取截止本期数据
          * @param {Object} tender - 标段

+ 1 - 1
app/service/tender.js

@@ -16,7 +16,7 @@ const path = require('path');
 const commonQueryColumns = [
     'id', 'project_id', 'name', 'status', 'category', 'ledger_times', 'ledger_status', 'measure_type', 'user_id', 'valuation', 'create_time',
     'total_price', 'deal_tp', 'copy_id', 's2b_gxby_check', 's2b_gxby_limit', 's2b_dagl_check', 's2b_dagl_limit', 'has_rela', 'his_id', 'rpt_show_level',
-    'build_status', 'settle_order', 'spid',
+    'build_status', 'settle_order', 'spid', 's_type',
 ];
 
 module.exports = app => {

+ 7 - 0
app/view/ledger/gather.ejs

@@ -29,6 +29,9 @@
                             <li class="nav-item">
                                 <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">所属项目节</a>
                             </li>
+                            <li class="nav-item" style="display: none">
+                                <a class="nav-link" data-toggle="tab" href="#change" role="tab">相关变更令</a>
+                            </li>
                             <li class="nav-item">
                                 <a class="nav-link" data-toggle="tab" href="#xmjGather" role="tab">项目节汇总</a>
                             </li>
@@ -94,6 +97,10 @@
                             <div class="sp-wrap" id="leaf-xmj-spread">
                             </div>
                         </div>
+                        <div class="tab-pane" id="change">
+                            <div class="sp-wrap" id="change-spread">
+                            </div>
+                        </div>
                         <div class="tab-pane" id="xmjGather">
                             <div class="sp-wrap" id="leaf-xmj-gather-spread">
                             </div>

+ 7 - 12
app/view/stage/gather.ejs

@@ -65,9 +65,9 @@
                         <li class="nav-item">
                             <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">所属项目节</a>
                         </li>
-                        <!--<li class="nav-item">-->
-                        <!--<a class="nav-link " data-toggle="tab" href="#biangeng" role="tab">相关变更令</a>-->
-                        <!--</li>-->
+                        <li class="nav-item" style="display: none">
+                            <a class="nav-link " data-toggle="tab" href="#change" role="tab">相关变更令</a>
+                        </li>
                         <li class="nav-item">
                             <a class="nav-link" data-toggle="tab" href="#xmjGather" role="tab">项目节汇总</a>
                         </li>
@@ -107,17 +107,12 @@
                         <div class="sp-wrap" id="leaf-xmj-spread">
                         </div>
                     </div>
-                    <div class="tab-pane active" id="xmjGather">
-                        <div class="sp-wrap" id="leaf-xmj-gather-spread">
+                    <div class="tab-pane" id="change">
+                        <div class="sp-wrap" id="change-spread">
                         </div>
                     </div>
-                    <div class="tab-pane" id="biangeng">
-                        <div class="sp-wrap">
-                            <table class="table table-sm table-bordered">
-                                <tr><th>变更令</th><th>名称</th><th>批复文号</th><th>变更图号</th><th>数量</th></tr>
-                                <tr><td>BGL01</td><td>XX变更令</td><td></td><td></td><td>100</td></tr>
-                                <tr><td>BGL02</td><td>YY变更令</td><td></td><td></td><td>80</td></tr>
-                            </table>
+                    <div class="tab-pane" id="xmjGather">
+                        <div class="sp-wrap" id="leaf-xmj-gather-spread">
                         </div>
                     </div>
                 </div>

+ 13 - 0
sql/update.sql

@@ -10,3 +10,16 @@ ADD COLUMN `unvaluation_tp` decimal(30, 8) NULL DEFAULT 0 COMMENT '不计价金
 ALTER TABLE `zh_change`
 MODIFY COLUMN `positive_tp` decimal(30, 8) NOT NULL DEFAULT 0.00000000 COMMENT '正变更金额' AFTER `order_by`,
 MODIFY COLUMN `negative_tp` decimal(30, 8) NOT NULL DEFAULT 0.00000000 COMMENT '负变更金额' AFTER `positive_tp`,
+
+ALTER TABLE `zh_ledger_attachment`
+MODIFY COLUMN `tid` int(11) UNSIGNED NOT NULL COMMENT '标段id' AFTER `id`,
+ADD COLUMN `revise_id` varchar(36) NOT NULL COMMENT '修订id' AFTER `tid`,
+ADD COLUMN `revising` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '修订中' AFTER `rid`,
+MODIFY COLUMN `uid` int(11) UNSIGNED NOT NULL COMMENT '上传者id' AFTER `lid`,
+ADD COLUMN `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间' AFTER `in_time`;
+
+ALTER TABLE `zh_ledger_attachment`
+ADD INDEX `idx_tid`(`tid`),
+ADD INDEX `idx_tid_sid`(`tid`, `settle_id`),
+ADD INDEX `idx_tid_rid`(`tid`, `revise_id`),
+ADD INDEX `idx_tid_revising`(`tid`, `revising`);