Browse Source

结算汇总

MaiXinRong 1 year ago
parent
commit
8a4929ec44

+ 13 - 4
app/controller/settle_controller.js

@@ -629,8 +629,8 @@ module.exports = app => {
         async loadGatherData(ctx) {
             try {
                 const settle = await this.ctx.service.settle.getLatestCompleteSettle(ctx.tender.id);
-                const bills = await this.ctx.service.settleBills.getDataByCondition({ where: { settle_id: settle.id }});
-                const pos = await this.ctx.service.settlePos.getDataByCondition({ where: { settle_id: settle.id }});
+                const bills = await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: settle.id }});
+                const pos = await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: settle.id }});
                 ctx.body = { err: 0, msg: '', data: { bills, pos } };
             } catch(err) {
                 ctx.log(err);
@@ -640,11 +640,20 @@ module.exports = app => {
         async gather(ctx) {
             try {
                 const renderData = {
+                    settleStatusHint: ctx.service.settle.statusArray,
+                    settleStatusColor: ctx.service.settle.statusColor,
+                    settleStatus: ctx.service.settle.settleStatus,
+                    measureType,
+                    settle: ctx.settle,
+                    thirdParty: {
+                        gxby: ctx.session.sessionProject.gxby_status,
+                        dagl: ctx.session.sessionProject.dagl_status,
+                    },
                     tender: ctx.tender.data,
-                    preUrl: `/tender/${ctx.tender.id}/measure/stage`,
+                    preUrl: `/tender/${ctx.tender.id}/settle`,
                 };
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.settle.gather);
-                await this.layout('settle/gather.ejs', renderData, 'settle/gather_modal.ejs');
+                await this.layout('settle/gather.ejs', renderData);
             } catch (err) {
                 ctx.log(err);
                 ctx.redirect(this.menu.menu.dashboard.url);

+ 1 - 0
app/middleware/tender_check.js

@@ -122,6 +122,7 @@ module.exports = options => {
             tender.schedule_permission = schedule_permission;
             yield next;
         } catch (err) {
+            console.log(err);
             // 输出错误到日志
             if (err.stack) {
                 this.logger.error(err);

+ 283 - 0
app/public/js/settle_gather.js

@@ -0,0 +1,283 @@
+function getGxbyText(data) {
+    const def = thirdParty.gxby.find(function (x) {
+        return x.value === data.gxby_status;
+    });
+    return def ? def.name : '';
+}
+function getDaglText(data) {
+    const def = thirdParty.dagl.find(function (x) {
+        return x.value === data.dagl_status;
+    });
+    return def ? def.name : '';
+}
+
+const ckBillsSpread = window.location.pathname + '-billsSelect';
+
+$(document).ready(() => {
+    autoFlashHeight();
+
+    let searchLedger, settleAtt;
+    const settleTreeSetting = {
+        id: 'tree_id',
+        pid: 'tree_pid',
+        order: 'tree_order',
+        level: 'tree_level',
+        fullPath: 'tree_full_path',
+        isLeaf: 'tree_is_leaf',
+        rootId: -1,
+        keys: ['id', 'tid', 'tree_id'],
+        stageId: 'id',
+        autoExpand: 3,
+        markExpandKey: 'settle-select-expand',
+        markExpandSubKey: window.location.pathname.split('/')[2],
+        calcFields: ['total_price', 'cur_contract_tp', 'cur_qc_tp', 'cur_gather_tp', 'cur_correct_tp'],
+        calcFun: function(node) {
+            if (!node.children || node.children.length === 0) {
+                node.cur_gather_qty = ZhCalc.add(node.cur_contract_qty, node.cur_qc_qty);
+                if (node.cur_contract_qty) {
+                    node.cur_correct_tp = ZhCalc.add(node.cur_qc_tp, ZhCalc.mul(node.cur_contract_qty, node.unit_price, tenderInfo.decimal.tp));
+                } else {
+                    node.cur_correct_tp = node.cur_gather_tp;
+                }
+                node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+                node.end_gather_qty = ZhCalc.add(node.end_contract_qty, node.end_qc_qty);
+                if (node.end_contract_qty) {
+                    node.end_correct_tp = ZhCalc.add(node.end_qc_tp, ZhCalc.mul(node.end_contract_qty, node.unit_price, tenderInfo.decimal.tp));
+                } else {
+                    node.end_correct_tp = node.end_gather_tp;
+                }
+            }
+            node.cur_gather_tp = ZhCalc.add(node.cur_contract_tp, node.cur_qc_tp);
+            node.cur_gather_percent = ZhCalc.mul(ZhCalc.div(node.cur_gather_tp, node.cur_final_tp), 100, 2);
+            node.cur_correct_percent = ZhCalc.mul(ZhCalc.div(node.cur_correct_tp, node.cur_final_tp), 100, 2);
+            node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+            node.pre_gather_percent = ZhCalc.mul(ZhCalc.div(node.pre_gather_tp, node.pre_final_tp), 100, 2);
+            node.pre_correct_percent = ZhCalc.mul(ZhCalc.div(node.pre_correct_tp, node.pre_final_tp), 100, 2);
+            node.end_gather_tp = ZhCalc.add(node.end_contract_tp, node.end_qc_tp);
+            node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_tp), 100, 2);
+            node.end_correct_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_tp), 100, 2);
+        }
+    };
+    const settleTree = createNewPathTree('stage', settleTreeSetting);
+    const settlePosSetting = {
+        id: 'id', ledgerId: 'lid',
+        calcFun: function(pos) {
+            pos.cur_gather_qty = ZhCalc.add(pos.cur_contract_qty, pos.cur_qc_qty);
+            pos.pre_gather_qty = ZhCalc.add(pos.pre_contract_qty, pos.pre_qc_qty);
+            pos.end_gather_qty = ZhCalc.add(pos.end_contract_qty, pos.end_qc_qty);
+        }
+    };
+    const settlePos = new StagePosData(settlePosSetting);
+
+    const slSpread = SpreadJsObj.createNewSpread($('#settle-bills')[0]);
+    const slSheet = slSpread.getActiveSheet();
+    slSheet.frozenColumnCount(billsSpreadSetting.cols.findIndex(x => { return x.field === 'total_price'; }) + 1);
+    slSheet.options.frozenlineColor = '#93b5e4';
+    const ratioCol = billsSpreadSetting.cols.find(x => {return x.field === 'cur_final_1_percent' || x.field === 'cur_correct_1_percent'});
+    if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'cur_correct_1_percent' : 'cur_final_1_percent';
+    billsSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
+        if (!data) return defaultColor;
+        if (data.children && data.children.length > 0) return defaultColor;
+
+        if (col.field === 'gxby') {
+            const def = thirdParty.gxby.find(function (x) {
+                return x.value === data.gxby_status;
+            });
+            if (def && def.color) return def.color;
+        } else if (col.field === 'dagl') {
+            const def = thirdParty.dagl.find(function (x) {
+                return x.value === data.dagl_status;
+            });
+            if (def && def.color) return def.color;
+        }
+    };
+    sjsSettingObj.setFxTreeStyle(billsSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
+    sjsSettingObj.set3FCols(billsSpreadSetting.cols, [
+        {field: 'gxby', getValue: getGxbyText, url_field: 'gxby_url'},
+        {field: 'dagl', getValue: getDaglText, url_field: 'dagl_url'},
+    ]);
+    billsSpreadSetting.afterLocate = function (node) {
+        settleAtt.getCurAttHtml(node);
+    };
+    SpreadJsObj.initSheet(slSheet, billsSpreadSetting);
+
+    const spSpread = SpreadJsObj.createNewSpread($('#settle-pos')[0]);
+    const spSheet = spSpread.getActiveSheet();
+    spSheet.frozenColumnCount(posSpreadSetting.cols.findIndex(x => { return x.field === 'total_price'; }) + 1);
+    spSheet.options.frozenlineColor = '#93b5e4';
+    posSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
+        if (!data) return defaultColor;
+
+        if (col.field === 'gxby') {
+            const def = thirdParty.gxby.find(function (x) {
+                return x.value === data.gxby_status;
+            });
+            if (def && def.color) return def.color;
+        } else if (col.field === 'dagl') {
+            const def = thirdParty.dagl.find(function (x) {
+                return x.value === data.dagl_status;
+            });
+            if (def && def.color) return def.color;
+        }
+    };
+    sjsSettingObj.set3FCols(posSpreadSetting.cols, [
+        {field: 'gxby', getValue: getGxbyText, url_field: 'gxby_url'},
+        {field: 'dagl', getValue: getDaglText, url_field: 'dagl_url'},
+    ]);
+    SpreadJsObj.initSheet(spSheet, posSpreadSetting);
+
+    const settleBillsObj = {
+        loadRelaData: function() {
+            SpreadJsObj.saveTopAndSelect(slSheet, ckBillsSpread);
+            SpreadJsObj.resetTopAndSelect(spSheet);
+            settlePosObj.loadCurPosData();
+        },
+        selectionChanged: function(e, info) {
+            if (!info.oldSelections || !info.oldSelections[0] || info.newSelections[0].row !== info.oldSelections[0].row) {
+                settleBillsObj.loadRelaData();
+            }
+        },
+        topRowChanged(e, info) {
+            SpreadJsObj.saveTopAndSelect(info.sheet, ckBillsSpread);
+        }
+    };
+    slSpread.bind(spreadNS.Events.SelectionChanged, settleBillsObj.selectionChanged);
+    slSpread.bind(spreadNS.Events.TopRowChanged, settleBillsObj.topRowChanged);
+
+    const settlePosObj = {
+        loadCurPosData: function() {
+            const billsNode = SpreadJsObj.getSelectObject(slSheet);
+            if (billsNode) {
+                const posRange = settlePos.getLedgerPos(billsNode.lid) || [];
+                SpreadJsObj.loadSheetData(spSheet, SpreadJsObj.DataType.Data, posRange, readOnly);
+            } else {
+                SpreadJsObj.loadSheetData(spSheet, SpreadJsObj.DataType.Data, [], true);
+            }
+        }
+    };
+
+    postData('gather/load', null, function(result) {
+        settleTree.loadDatas(result.bills);
+        treeCalc.calculateAll(settleTree);
+        settlePos.loadDatas(result.pos);
+        settlePos.calculateAll();
+        SpreadJsObj.loadSheetData(slSheet, SpreadJsObj.DataType.Tree, settleTree);
+        SpreadJsObj.loadTopAndSelect(slSpread.getActiveSheet(), ckBillsSpread);
+        settlePosObj.loadCurPosData();
+    });
+
+    // 展开收起工具栏
+    $('a', '.right-nav').bind('click', function () {
+        const tab = $(this), tabPanel = $(tab.attr('content'));
+        if (!tab.hasClass('active')) {
+            $('a', '.side-menu').removeClass('active');
+            $('.tab-content .tab-select-show').removeClass('active');
+            tab.addClass('active');
+            tabPanel.addClass('active');
+            showSideTools(tab.hasClass('active'));
+            if (tab.attr('content') === '#search' && !searchLedger) {
+                searchLedger = $.billsSearch({
+                    selector: '#search',
+                    searchSpread: slSpread,
+                    searchOver: true,
+                    searchEmpty: true,
+                    keyId: 'tree_id',
+                    resultSpreadSetting: {
+                        cols: [
+                            {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
+                            {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+                            {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
+                            {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},
+                            {title: '单价', field: 'unit_price', hAlign: 2, width: 50},
+                            {title: '数量', field: 'quantity', hAlign: 2, width: 50},
+                        ],
+                        emptyRows: 0,
+                        headRows: 1,
+                        headRowHeight: [32],
+                        headColWidth: [30],
+                        defaultRowHeight: 21,
+                        headerFont: '12px 微软雅黑',
+                        font: '12px 微软雅黑',
+                        selectedBackColor: '#fffacd',
+                        readOnly: true,
+                    },
+                    afterLocated: function () {
+                        settlePosObj.loadCurPosData();
+                    },
+                });
+                searchLedger.spread.refresh();
+            }
+        } else {
+            tab.removeClass('active');
+            tabPanel.removeClass('active');
+            showSideTools(tab.hasClass('active'));
+        }
+        slSpread.refresh();
+        spSpread.refresh();
+    });
+
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        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();
+        }
+    });
+    // 加载上下窗口resizer
+    $.divResizer({
+        select: '#main-resize',
+        callback: function () {
+            slSpread.refresh();
+            let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
+            $(".sp-wrap").height(bcontent-30);
+            spSpread.refresh();
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+        }
+    });
+    // 工具栏resizer
+    $.divResizer({
+        select: '#right-spr',
+        callback: function () {
+            slSpread.refresh();
+            spSpread.refresh();
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+            if (searchLedger) searchLedger.spread.refresh();
+        }
+    });
+
+    // 显示层次
+    (function (select, sheet) {
+        $(select).click(function () {
+            const tag = $(this).attr('tag');
+            const tree = sheet.zh_tree;
+            if (!tree) return;
+            setTimeout(() => {
+                showWaitingView();
+                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;
+                }
+                closeWaitingView();
+            }, 100);
+        });
+    })('a[name=showLevel]', slSheet);
+});

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

@@ -285,6 +285,7 @@ $(document).ready(() => {
                     searchSpread: slSpread,
                     searchOver: true,
                     searchEmpty: true,
+                    keyId: 'tree_id',
                     resultSpreadSetting: {
                         cols: [
                             {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},

+ 3 - 3
app/router.js

@@ -434,6 +434,9 @@ module.exports = app => {
     app.post('/tender/:id/settle/add', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'settleController.add');
     app.post('/tender/:id/settle/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'settleController.save');
     app.post('/tender/:id/settle/delete', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'settleController.delete');
+    // 结算汇总
+    app.get('/tender/:id/settle/gather', sessionAuth, tenderCheck, uncheckTenderCheck, 'settleController.gather');
+    app.post('/tender/:id/settle/gather/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'settleController.loadGatherData');
     // 结算期
     app.get('/tender/:id/settle/:sorder', sessionAuth, tenderCheck, uncheckTenderCheck, settleCheck, 'settleController.index');
     app.get('/tender/:id/settle/:sorder/select', sessionAuth, tenderCheck, uncheckTenderCheck, settleCheck, 'settleController.select');
@@ -450,9 +453,6 @@ module.exports = app => {
     app.post('/tender/:id/settle/:sorder/audit/check', sessionAuth, tenderCheck, uncheckTenderCheck, settleCheck, 'settleController.auditCheck');
     app.post('/tender/:id/settle/:sorder/audit/checkAgain', sessionAuth, tenderCheck, uncheckTenderCheck, settleCheck, 'settleController.auditCheckAgain');
     app.post('/tender/:id/settle/:sorder/audit/checkCancel', sessionAuth, tenderCheck, uncheckTenderCheck, settleCheck, 'settleController.auditCheckCancel');
-    // 结算汇总
-    app.get('/tender/:id/settle/gather', sessionAuth, tenderCheck, uncheckTenderCheck, 'settleController.gather');
-    app.get('/tender/:id/settle/gather/load', sessionAuth, tenderCheck, uncheckTenderCheck, 'settleController.loadGatherData');
 
     // 报表
     app.get('/tender/:id/report', sessionAuth, tenderCheck, uncheckTenderCheck, 'reportController.index');

+ 2 - 2
app/service/stage.js

@@ -455,9 +455,9 @@ module.exports = app => {
         async addStage(tenderId, date, period) {
             const stages = await this.getAllDataByCondition({
                 where: { tid: tenderId },
-                order: [['order', 'asc']],
+                orders: [['order', 'DESC']],
             });
-            const preStage = stages[stages.length - 1];
+            const preStage = stages[0];
             const preCheckedStage = stages.find(x => { return x.status === auditConst.stage.status.checked; });
             const order = stages.length + 1;
             const newStage = {

+ 190 - 0
app/view/settle/gather.ejs

@@ -0,0 +1,190 @@
+<% include ./list_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex">
+            <% include ./list_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="javascript: void(0);">第一层</a>
+                            <a class="dropdown-item" name="showLevel" tag="2" href="javascript: void(0);">第二层</a>
+                            <a class="dropdown-item" name="showLevel" tag="3" href="javascript: void(0);">第三层</a>
+                            <a class="dropdown-item" name="showLevel" tag="4" href="javascript: void(0);">第四层</a>
+                            <a class="dropdown-item" name="showLevel" tag="5" href="javascript: void(0);">第五层</a>
+                            <a class="dropdown-item" name="showLevel" tag="last" href="javascript: void(0);">最底层</a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="ml-auto">
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap pr-46">
+        <div class="c-header p-0">
+        </div>
+        <div class="row w-100 sub-content">
+            <div id="left-view" class="c-body" style="width: 100%">
+                <!--上部分-->
+                <div class="sjs-height-1" id="settle-bills">
+                </div>
+                <!--下部分-->
+                <div class="bcontent-wrap" id="main-bottom">
+                    <div id="main-resize" class="resize-y" r-Type="height" div1="#settle-bills" div2="#main-bottom" store-id="settle-main" store-version="1.0.0" min="100"></div>
+                    <div class="bc-bar mb-1">
+                        <ul class="nav nav-tabs">
+                            <li class="nav-item">
+                                <a class="nav-link active" href="#">计量单元</a>
+                            </li>
+                        </ul>
+                    </div>
+                    <div class="sp-wrap" id="settle-pos">
+                    </div>
+                </div>
+            </div>
+            <div id="right-view" class="c-body" style="display: none; width: 33%;">
+                <div class="resize-x" id="right-spr" r-Type="width" div1="#left-view" div2="#right-view" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
+                <div class="tab-content">
+                    <!--查找定位-->
+                    <div id="search" class="tab-pane tab-select-show">
+                        <div class="sjs-bar-1">
+                            <div class="input-group input-group-sm pb-1">
+                                <div class="input-group-prepend">
+                                    <div class="input-group-text">
+                                        <input type="radio" name="searchType" id="over"> 超计
+                                    </div>
+                                    <div class="input-group-text">
+                                        <input type="radio" name="searchType" id="empty"> 漏计
+                                    </div>
+                                </div>
+                                <input type="text" class="form-control form-control-sm" placeholder="可查找 项目节编号 / 清单编号 /名称" id="keyword">
+                                <div class="input-group-append">
+                                    <button class="btn btn-outline-secondary btn-sm" type="button" id="searchLedger">搜索</button>
+                                </div>
+                            </div>
+                        </div>
+                        <div id="search-result" class="sjs-sh-1">
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="side-menu">
+            <!--右侧菜单-->
+            <ul class="nav flex-column right-nav">
+                <li class="nav-item">
+                    <a class="nav-link" content="#search" href="javascript: void(0);">查找定位</a>
+                </li>
+            </ul>
+        </div>
+    </div>
+</div>
+<div style="display: none">
+    <img src="/public/images/ellipsis_horizontal.png" id="ellipsis-icon" />
+    <img src="/public/images/icon-ok.png" id="icon-ok" />
+    <img src="/public/images/file_clip.png" id="rela-file-icon">
+    <img src="/public/images/file_clip_hover.png" id="rela-file-hover">
+</div>
+<script>
+    const readOnly = true;
+    const tenderName = '<%- ctx.tender.name %>';
+    const tenderInfo = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.tender.info)) %>'));
+    const thousandth = <%- ctx.tender.info.display.thousandth %>;
+    const thirdParty = JSON.parse('<%- JSON.stringify(thirdParty) %>');
+    const settleStatusHint = JSON.parse('<%- JSON.stringify(settleStatusHint )%>');
+    const settleStatus = JSON.parse('<%- JSON.stringify(settleStatus )%>');
+    const settleStatusColor = JSON.parse('<%- JSON.stringify(settleStatusColor )%>');
+    const billsSpreadSetting = {
+        cols: [
+            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', readOnly: true, getValue: function(data) {
+                    // return data.b_code ? '' : settleStatusHint[data.settle_status] || ''
+                    return settleStatusHint[data.settle_status] || '';
+                }},
+            {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
+            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@', readOnly: true},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true, cellType: 'unit'},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '台账|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '本期合同结算|数量', colSpan: '2|1', rowSpan: '1|1', field: 'cur_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'cur_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'cur_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'cur_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '本期完成结算|数量', colSpan: '3|1', rowSpan: '1|1', field: 'cur_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'cur_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'cur_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            {title: '截止本期合同结算|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '截止本期完成结算|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip', readOnly: true},
+            <% if (ctx.session.sessionProject.gxby) { %>
+            {title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            <% } %>
+            <% if (ctx.session.sessionProject.dagl) { %>
+            {title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            <% } %>
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        frozenColCount: 5,
+        frozenLineColor: '#93b5e4',
+        readOnly: true,
+        getForeColor: function(sheet, data, row, col, foreColor) {
+            if (col.field === 'settle_status') {
+                return data ? settleStatusColor[data.settle_status] || foreColor : foreColor;
+            } else {
+                return foreColor;
+            }
+        }
+    };
+    const posSpreadSetting = {
+        cols: [
+            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', readOnly: true, getValue: function(data) { return settleStatusHint[data.settle_status] || '' }},
+            {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@', readOnly: true},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@', readOnly: true},
+            {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, formatter: '@', readOnly: true},
+            {title: '本期结算|合同', colSpan: '3|1', rowSpan: '1|1', field: 'cur_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'cur_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+            {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'cur_gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '截止本期结算|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+            {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+            <% if (ctx.session.sessionProject.gxby) { %>
+            {title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            <% } %>
+            <% if (ctx.session.sessionProject.dagl) { %>
+            {title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            <% } %>
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        headColWidth: [30],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+        getForeColor: function(sheet, data, row, col, foreColor) {
+            if (col.field === 'settle_status') {
+                return data ? settleStatusColor[data.settle_status] || foreColor : foreColor;
+            } else {
+                return foreColor;
+            }
+        }
+    };
+</script>

+ 22 - 1
config/web.js

@@ -1448,7 +1448,28 @@ const JsFiles = {
                     '/public/js/settle_ledger.js',
 
                 ],
-                mergeFile: 'settle',
+                mergeFile: 'settle_ledger',
+            },
+            gather: {
+                files: [
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                ],
+                mergeFiles: [
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/component/menu.js',
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/tools_att.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/settle_gather.js',
+
+                ],
+                mergeFile: 'settle_gather',
             }
         }
     },