浏览代码

汇总对比,金额汇总

MaiXinRong 3 月之前
父节点
当前提交
1489e89ad9

+ 67 - 12
app/controller/spss_controller.js

@@ -32,9 +32,9 @@ module.exports = app => {
                 const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
                 const renderData = {
                     categoryData,
-                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.info)
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.spss.gatherInfo)
                 };
-                await this.layout('spss/info.ejs', renderData, 'spss/spss_select_modal.ejs');
+                await this.layout('spss/gather_info.ejs', renderData, 'spss/spss_select_modal.ejs');
             } catch (err) {
                 ctx.helper.log(err);
             }
@@ -105,8 +105,59 @@ module.exports = app => {
             }
         }
 
-        async _loadInfoData(tender) {
+        async _loadStageTpData(info, tender, stage, loadPre = true) {
+            if (!stage) return;
+            if (stage.readOnly && stage.status === status.uncheck) return;
+            if (loadPre) {
+                info.pre_contract_tp = stage.pre_contract_tp;
+                info.pre_qc_tp = stage.pre_qc_tp;
+                info.pre_yf_tp = stage.pre_yf_tp;
+                info.pre_sf_tp = stage.pre_sf_tp;
+            }
+            if (!stage.readOnly) await this.ctx.service.stage.checkStageGatherData(stage, this.ctx.session.sessionUser.is_admin);
 
+            info.contract_tp = this.ctx.helper.add(stage.contract_tp, info.contract_tp);
+            info.qc_tp = this.ctx.helper.add(stage.qc_tp, info.qc_tp);
+            info.contract_pc_tp = this.ctx.helper.add(stage.contract_pc_tp, info.contract_pc_tp);
+            info.qc_pc_tp = this.ctx.helper.add(stage.qc_pc_tp, info.qc_pc_tp);
+            info.pc_tp = this.ctx.helper.add(stage.pc_tp, info.pc_tp);
+            info.yf_tp = this.ctx.helper.add(stage.yf_tp, info.yf_tp);
+            info.sf_tp = this.ctx.helper.add(stage.sf_tp, info.sf_tp);
+        }
+        async _loadStagesTpData(info, tender, stages, preStage, endStage) {
+            if (preStage) {
+                info.pre_contract_tp = this.ctx.helper.sum([preStage.contract_tp, preStage.pre_contract_tp, preStage.contract_pc_tp]);
+                info.pre_contract_tp = this.ctx.helper.sum([preStage.qc_tp, preStage.pre_qc_tp, preStage.qc_pc_tp]);
+                info.pre_yf_tp = this.ctx.helper.add(preStage.yf_tp, preStage.pre_yf_tp);
+                info.pre_sf_tp = this.ctx.helper.add(preStage.sf_tp, preStage.pre_sf_tp);
+            }
+            for (const stage of stages) {
+                await this.ctx.service.stage.doCheckStage(stage);
+                await this._loadStageTpData(info, tender, stage, false);
+            }
+        }
+        async _loadInfoData(tender, filter) {
+            const info = { measure_type_str: '' };
+            if (tender.measure_type === measureType.tz.value) info.measure_type_str = measureType.tz.title;
+            if (tender.measure_type === measureType.gcl.value) info.measure_type_str = measureType.gcl.title;
+            await this.ctx.service.tenderCache.loadTenderCache(tender, this.ctx.session.sessionUser.accountId);
+            info.contract_price = tender.contract_price;
+            info.advance_tp = tender.advance_tp;
+            info.change_tp = tender.change_tp;
+            info.progress = tender.progress;
+            if (filter.type === 'stage') {
+                await this._loadStageTpData(info, tender, filter.stage);
+            } else {
+                await this._loadStagesTpData(info, tender, filter.stages, filter.preStage, filter.endStage);
+            }
+            info.pre_gather_tp = this.ctx.helper.add(info.pre_contract_tp, info.pre_qc_tp);
+            info.gather_tp = this.ctx.helper.sum([info.contract_tp, info.qc_tp, info.pc_tp]);
+            info.end_contract_tp = this.ctx.helper.sum([info.contract_tp, info.contract_pc_tp, info.pre_contract_tp]);
+            info.end_qc_tp = this.ctx.helper.sum([info.qc_tp, info.qc_pc_tp, info.pre_qc_tp]);
+            info.end_gather_tp = this.ctx.helper.add(info.gather_tp, info.pre_gather_tp);
+            info.end_sf_tp = this.ctx.helper.add(info.sf_tp, info.pre_sf_tp);
+            info.end_yf_tp = this.ctx.helper.add(info.yf_tp, info.pre_yf_tp);
+            return info;
         }
         async _loadLedgerData(tender) {
             const bills = await this.ctx.service.ledger.getAllDataByCondition({
@@ -459,12 +510,16 @@ module.exports = app => {
         async _loadTenderData(tid, filter, stageInfo) {
             this.ctx.tender = null;
             const tender = await this.ctx.service.tender.checkTender(tid);
-            const result = { id: tender.id, name: tender.name };
+            const result = { id: tender.id, name: tender.name, category: tender.category };
             let stageFilter = null;
             for (const f of filter) {
                 switch (f) {
                     case 'info':
-                        result.info = await this._loadInfoData(tender);
+                        if (!stageFilter) {
+                            stageFilter = await this._filterStages(tender, stageInfo);
+                            result.stage_filter = stageFilter.filter;
+                        }
+                        result.info = await this._loadInfoData(tender, stageFilter);
                         break;
                     case 'ledger':
                         if (filter.indexOf('stage') < 0) [result.bills, result.pos] = await this._loadLedgerData(tender);
@@ -472,49 +527,49 @@ module.exports = app => {
                     case 'stage':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         [result.bills, result.pos] = await this._loadStageLedgerData(tender, stageFilter);
                         break;
                     case 'jgcl':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         result.jgcl = await this._loadJgclData(tender, stageFilter);
                         break;
                     case 'yjcl':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         result.yjcl = await this._loadYjclData(tender, stageFilter);
                         break;
                     case 'bonus':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         result.bonus = await this._loadBonusData(tender, stageFilter);
                         break;
                     case 'safeProd':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         result.safeProd = await this._loadSafeProdData(tender, stageFilter);
                         break;
                     case 'tempLand':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         result.tempLand = await this._loadTempLandData(tender, stageFilter);
                         break;
                     case 'other':
                         if (!stageFilter) {
                             stageFilter = await this._filterStages(tender, stageInfo);
-                            result.filter = stageFilter.filter;
+                            result.stage_filter = stageFilter.filter;
                         }
                         result.other = await this._loadOtherData(tender, stageFilter);
                         break;

+ 4 - 0
app/public/js/shares/export_excel.js

@@ -68,6 +68,10 @@ const SpreadExcelObj = (function() {
                 } else if (setting.font) {
                     cell.font(setting.font);
                 }
+                if (col.formatter) {
+                    cell.formatter(col.formatter);
+                    cell.value(cell.text());
+                }
                 cell.hAlign(col.hAlign).vAlign(1);
             }
             if (autoFit) sheet.autoFitRow(curRow);

+ 2 - 1
app/public/js/shares/tenders2tree.js

@@ -17,7 +17,7 @@ const Tender2Tree = (function () {
         rootId: -1,
         fullPath: 'full_path',
     };
-    const tenderTree = createNewPathTree('gather', treeSetting);
+    let tenderTree;
 
     // 查询方法
     function findNode (key, value, arr) {
@@ -74,6 +74,7 @@ const Tender2Tree = (function () {
     }
 
     function convert (category, tenders, ledgerAuditConst, stageAuditConst, loadFun) {
+        tenderTree = createNewPathTree('gather', treeSetting);
         tenderTree.clearDatas();
 
         const levelCategory = category.filter(function (c) {

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

@@ -163,7 +163,7 @@ $(document).ready(() => {
         },
         rebuildSpreadSetting(tenders) {
             if(tenders.length > 0) {
-                if (tenders[0].filter.indexOf('~') > 0) {
+                if (tenders[0].stage_filter.indexOf('~') > 0) {
                     $('[datatype=end]').hide();
                 } else {
                     $('[datatype=end]').show();
@@ -174,13 +174,13 @@ $(document).ready(() => {
             for (const [i, tender] of tenders.entries()) {
                 for (const col of billsSpreadSetting.extraCols) {
                     const newCol = JSON.parse(JSON.stringify(col));
-                    if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name).replace('%f', tender.filter);
+                    if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name).replace('%f', tender.stage_filter);
                     if (newCol.formatField) newCol.field = newCol.formatField.replace('%d', i + 1);
                     billsSpreadSetting.cols.push(newCol);
                 }
                 for (const col of posSpreadSetting.extraCols) {
                     const newCol = JSON.parse(JSON.stringify(col));
-                    if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name).replace('%f', tender.filter);
+                    if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name).replace('%f', tender.stage_filter);
                     if (newCol.formatField) newCol.field = newCol.formatField.replace('%d', i + 1);
                     posSpreadSetting.cols.push(newCol)
                 }

+ 43 - 33
app/public/js/spss_gather_stage_extra.js

@@ -68,11 +68,11 @@ $(document).ready(() => {
         },
         bonus: {
             cols: [
-                {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 320, formatter: '@'},
-                {title: '汇总', colSpan: '1', rowSpan: '1', field: 'filter', hAlign: 1, width: 100, formatter: '@'},
+                {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 320, formatter: '@', cellType: 'tree'},
+                {title: '汇总', colSpan: '1', rowSpan: '1', field: 'filter_str', hAlign: 1, width: 100, formatter: '@'},
                 {title: '类型', colSpan: '1', rowSpan: '1', field: 'b_type', hAlign: 1, width: 80, formatter: '@'},
-                {title: '金额', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 1, width: 80, formatter: '@'},
-                {title: '时间', colSpan: '1', rowSpan: '1', field: 'real_time', hAlign: 1, width: 80, formatter: '@'},
+                {title: '金额', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 2, width: 80},
+                {title: '时间', colSpan: '1', rowSpan: '1', field: 'real_time', hAlign: 1, width: 100, formatter: 'yyyy-MM-dd'},
             ],
             emptyRows: 0,
             headRows: 1,
@@ -113,14 +113,14 @@ $(document).ready(() => {
         },
         tempLand: {
             cols: [
-                {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 320, formatter: '@'},
-                {title: '汇总', colSpan: '1', rowSpan: '2', field: 'filter', hAlign: 1, width: 100, formatter: '@'},
+                {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 320, formatter: '@', cellType: 'tree'},
+                {title: '汇总', colSpan: '1', rowSpan: '2', field: 'filter_str', hAlign: 1, width: 100, formatter: '@'},
                 {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 80, formatter: '@'},
                 {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'},
-                {title: '本期|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qty', hAlign: 1, width: 80, formatter: '@'},
-                {title: '|数量', colSpan: '|1', rowSpan: '|1', field: 'tp', hAlign: 1, width: 80, formatter: '@'},
-                {title: '截止本期|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qty', hAlign: 1, width: 80, formatter: '@'},
-                {title: '|数量', colSpan: '|1', rowSpan: '|1', field: 'end_tp', hAlign: 1, width: 80, formatter: '@'},
+                {title: '本期|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qty', hAlign: 2, width: 80, formatter: '@'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: '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,
@@ -132,13 +132,13 @@ $(document).ready(() => {
         },
         other: {
             cols: [
-                {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 320, formatter: '@'},
-                {title: '汇总', colSpan: '1', rowSpan: '1', field: 'filter', hAlign: 1, width: 100, formatter: '@'},
+                {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 320, formatter: '@', cellType: 'tree'},
+                {title: '汇总', colSpan: '1', rowSpan: '1', field: 'filter_str', hAlign: 1, width: 100, formatter: '@'},
                 {title: '类型', colSpan: '1', rowSpan: '1', field: 'o_type', hAlign: 1, width: 80, formatter: '@'},
-                {title: '金额', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 1, width: 80, formatter: '@'},
-                {title: '本期', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 1, width: 80, formatter: '@'},
-                {title: '截止本期', colSpan: '1', rowSpan: '1', field: 'end_tp', hAlign: 1, width: 80, formatter: '@'},
-                {title: '时间', colSpan: '1', rowSpan: '1', field: 'real_time', hAlign: 1, width: 80, formatter: '@'},
+                {title: '金额', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 80},
+                {title: '本期', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 2, width: 80},
+                {title: '截止本期', colSpan: '1', rowSpan: '1', field: 'end_tp', hAlign: 2, width: 80},
+                {title: '时间', colSpan: '1', rowSpan: '1', field: 'real_time', hAlign: 1, width: 100, formatter: 'yyyy-MM-dd'},
             ],
             emptyRows: 0,
             headRows: 1,
@@ -157,10 +157,10 @@ $(document).ready(() => {
         seData: 'cur',
         jgcl: [],
         yjcl: [],
-        bonus: [],
-        other: [],
+        bonus: createNewPathTree('gather', {id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, fullPath: 'full_path'}),
+        other: createNewPathTree('gather', {id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, fullPath: 'full_path'}),
         safeProd: [],
-        tempLand: [],
+        tempLand: createNewPathTree('gather', {id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, fullPath: 'full_path'}),
         gatherJgcl(tenders) {
             this.jgcl = [];
             for (const [i, t] of tenders.entries()) {
@@ -223,18 +223,24 @@ $(document).ready(() => {
             }
         },
         gatherBonus(tenders) {
-            this.bonus = [];
+            this.bonus.clearDatas();
             for (const [i, t] of tenders.entries()) {
-                this.bonus.push({ tid: t.id, name: t.name, filter: t.filter });
-                this.bonus.push(...t.bonus);
+                const tenderNode = this.bonus.addNode({ tid: t.id, name: t.name, filter_str: t.filter });
+                for (const b of t.bonus) {
+                    this.bonus.addNode(b, tenderNode);
+                }
             }
+            this.bonus.sortTreeNode(true);
         },
         gatherOther(tenders) {
-            this.other = [];
+            this.other.clearDatas();
             for (const [i, t] of tenders.entries()) {
-                this.other.push({ tid: t.id, name: t.name, filter: t.filter });
-                this.other.push(...t.other);
+                const tenderNode = this.other.addNode({ tid: t.id, name: t.name, filter_str: t.stage_filter });
+                for (const o of t.other) {
+                    this.other.addNode(o, tenderNode);
+                }
             }
+            this.other.sortTreeNode(true);
         },
         gatherSafeProd(tenders) {
             this.safeProd = [];
@@ -265,10 +271,12 @@ $(document).ready(() => {
             }
         },
         gatherTempLand(tenders) {
-            this.tempLand = [];
+            this.tempLand.clearDatas();
             for (const [i, t] of tenders.entries()) {
-                this.tempLand.push({ tid: t.id, name: t.name, filter: t.filter });
-                this.tempLand.push(...t.tempLand);
+                const tenderNode = this.tempLand.addNode({ tid: t.id, name: t.name, filter_str: t.filter });
+                for (const tl of t.tempLand) {
+                    this.tempLand.addNode(tl, tenderNode);
+                }
                 // const endfix = '_' + (i + 1);
                 // for (const data of t.tempLand) {
                 //     if (!data.unit) data.unit = '';
@@ -293,6 +301,7 @@ $(document).ready(() => {
                 //     tl['sum_end_tp'] = ZhCalc.add(tl['sum_end_tp'], data.end_tp);
                 // }
             }
+            this.tempLand.sortTreeNode(true);
         },
         gatherStageExtraData(tenders) {
             this.tenderCount = tenders.length;
@@ -311,7 +320,7 @@ $(document).ready(() => {
                 for (const [i, tender] of tenders.entries()) {
                     for (const col of spreadSetting.extraCols) {
                         const newCol = JSON.parse(JSON.stringify(col));
-                        if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name).replace('%f', tender.filter);
+                        if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name).replace('%f', tender.stage_filter);
                         if (newCol.formatField) newCol.field = newCol.formatField.replace('%d', i + 1);
                         spreadSetting.cols.push(newCol);
                     }
@@ -380,7 +389,8 @@ $(document).ready(() => {
         },
         loadSheetData() {
             SpreadJsObj.initSheet(dataSheet, spreadSetting[this.seType]);
-            SpreadJsObj.loadSheetData(dataSheet, SpreadJsObj.DataType.Data, this[this.seType]);
+            const isTree = spreadSetting[this.seType].cols.find(x => { return x.cellType === 'tree'; });
+            SpreadJsObj.loadSheetData(dataSheet, isTree ? SpreadJsObj.DataType.Tree : SpreadJsObj.DataType.Data, this[this.seType]);
             SpreadJsObj.locateRow(dataSheet, 0);
         },
         refreshStageExtraData(type) {
@@ -423,10 +433,10 @@ $(document).ready(() => {
         const sheets = [];
         sheets.push({ name: '甲供材料', setting: spreadSetting.jgcl, data: stageExtra.jgcl });
         sheets.push({ name: '永久材料', setting: spreadSetting.yjcl, data: stageExtra.yjcl });
-        sheets.push({ name: '奖罚金', setting: spreadSetting.bonus, data: stageExtra.bonus });
+        sheets.push({ name: '奖罚金', setting: spreadSetting.bonus, data: stageExtra.bonus.nodes });
         sheets.push({ name: '安全生产', setting: spreadSetting.safeProd, data: stageExtra.safeProd });
-        sheets.push({ name: '临时占地', setting: spreadSetting.tempLand, data: stageExtra.tempLand });
-        sheets.push({ name: '其他', setting: spreadSetting.other, data: stageExtra.other });
+        sheets.push({ name: '临时占地', setting: spreadSetting.tempLand, data: stageExtra.tempLand.nodes });
+        sheets.push({ name: '其他', setting: spreadSetting.other, data: stageExtra.other.nodes });
         SpreadExcelObj.exportSimpleXlsxSheets(sheets, "计量汇总-其他台账.xlsx");
     });
     $.subMenu({

+ 112 - 0
app/public/js/spss_gather_stage_info.js

@@ -0,0 +1,112 @@
+$(document).ready(() => {
+    autoFlashHeight();
+    const infoSpreadSetting = {
+        cols: [
+            {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 235, formatter: '@', cellType: 'tree'},
+            {title: '计量模式', colSpan: '1', rowSpan: '1', field: 'measure_type_str', hAlign: 1, width: 80, formatter: '@'},
+            {title: '标段状态', colSpan: '1', rowSpan: '1', field: 'progress_str', hAlign: 1, width: 110, formatter: '@'},
+            {title: '汇总', colSpan: '1', rowSpan: '1', field: 'stage_filter', hAlign: 1, width: 100, formatter: '@'},
+            {title: '签约合同价', colSpan: '1', rowSpan: '1', field: 'contract_price', hAlign: 2, width: 80, type: 'Number'},
+            {title: '0号台账', colSpan: '1', rowSpan: '1', field: 'total_price', hAlign: 2, width: 80, type: 'Number'},
+            {title: '本期合同', colSpan: '1', rowSpan: '1', field: 'contract_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '本期变更', colSpan: '1', rowSpan: '1', field: 'qc_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '本期完成', colSpan: '1', rowSpan: '1', field: 'gather_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '截止本期合同', colSpan: '1', rowSpan: '1', field: 'end_contract_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '截止本期变更', colSpan: '1', rowSpan: '1', field: 'end_qc_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '截止本期完成', colSpan: '1', rowSpan: '1', field: 'end_gather_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '本期应付', colSpan: '1', rowSpan: '1', field: 'yf_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '截止本期应付', colSpan: '1', rowSpan: '1', field: 'end_yf_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '本期实付', colSpan: '1', rowSpan: '1', field: 'sf_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '截止本期实付', colSpan: '1', rowSpan: '1', field: 'end_sf_tp', hAlign: 2, width: 80, type: 'Number'},
+        ],
+        emptyRows: 0,
+        headRows: 1,
+        headRowHeight: [32],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+    };
+
+    const infoSpread = SpreadJsObj.createNewSpread($('#info-spread')[0]);
+    const infoSheet = infoSpread.getActiveSheet();
+    SpreadJsObj.initSheet(infoSheet, infoSpreadSetting);
+    let infoTree;
+
+    const tenderSelect = TenderSelectMulti({
+        title: '汇总标段',
+        type: 'gather',
+        dataType: 'stage',
+        afterSelect: function(select) {
+            const data = { filter: 'info', tender: select };
+            postData(`/sp/${spid}/spss/load`, data, function(result) {
+                infoTree = Tender2Tree.convert(category, result, null, null, function(node, tender) {
+                    node.measure_type_str = tender.info.measure_type_str;
+                    node.progress = tender.info.progress;
+                    node.progress_str = `${node.progress.title}(${node.progress.status})`;
+                    node.stage_filter = tender.stage_filter;
+                    node.contract_price = tender.info.contract_price;
+                    node.total_price = tender.total_price;
+                    node.contract_tp = tender.info.contract_tp;
+                    node.qc_tp = tender.info.qc_tp;
+                    node.gather_tp = tender.info.gather_tp;
+                    node.end_contract_tp = tender.info.end_contract_tp;
+                    node.end_qc_tp = tender.info.end_qc_tp;
+                    node.end_gather_tp = tender.info.end_gather_tp;
+                    node.yf_tp = tender.info.yf_tp;
+                    node.end_yf_tp = tender.info.end_yf_tp;
+                    node.sf_tp = tender.info.sf_tp;
+                    node.end_sf_tp = tender.info.end_sf_tp;
+                });
+                SpreadJsObj.loadSheetData(infoSheet, SpreadJsObj.DataType.Tree, infoTree, true);
+            });
+        },
+    });
+    $('#gather-select').click(tenderSelect.showSelect);
+
+    $('#export-excel').click(function() {
+        if (!infoTree || infoTree.nodes.length === 0) {
+            toastr.warning('无可导出数据');
+            return;
+        }
+        SpreadExcelObj.exportSimpleXlsxSheet(infoSpreadSetting, infoTree.nodes, "计量汇总-其他台账.xlsx");
+    });
+    // 显示层次
+    (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":
+                    tree.expandByLevel(parseInt(tag));
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+                case "last":
+                    tree.expandByCustom(() => { return true; });
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+            }
+        });
+    })('a[name=showLevel]', infoSheet);
+    $.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');
+                $('.c-body table thead').css('left', '56px');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+                $('.c-body table thead').css('left', '176px');
+            }
+            autoFlashHeight();
+            infoSpread.refresh();
+        }
+    });
+});

+ 9 - 8
app/view/spss/info.ejs

@@ -9,10 +9,10 @@
                         <!--展开/收起-->
                         <div class="btn-group">
                             <button type="button" class="btn btn-sm btn-light text-primary dropdown-toggle" data-toggle="dropdown" id="zhankai" aria-expanded="false">显示层级</button>
-                            <div class="dropdown-menu" aria-labelledby="zhankai" style="will-change: transform;">
-                                <a class="dropdown-item" href="#">第一层</a>
-                                <a class="dropdown-item" href="#">第二层</a>
-                                <a class="dropdown-item" href="#">最底层</a>
+                            <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="last" href="javascript:void(0);">最底层</a>
                             </div>
                         </div>
                     </div>
@@ -25,9 +25,10 @@
         </div>
     </div>
     <div class="content-wrap">
-        <div class="sjs-height-0" style="background-color: #fff">
-            <div class="c-body">
-            </div>
+        <div class="sjs-height-0" style="background-color: #fff" id="info-spread">
         </div>
     </div>
-</div>
+</div>
+<script>
+    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
+</script>

+ 1 - 4
app/view/spss/spss_select_modal.ejs

@@ -108,7 +108,4 @@
             </div>
         </div>
     </div>
-</div>
-<script>
-    const category = JSON.parse('<%- JSON.stringify(categoryData) %>');
-</script>
+</div>

+ 3 - 3
config/web.js

@@ -1885,7 +1885,7 @@ const JsFiles = {
             },
         },
         spss: {
-            info: {
+            gatherInfo: {
                 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',
@@ -1905,9 +1905,9 @@ const JsFiles = {
                     '/public/js/zh_calc.js',
                     '/public/js/path_tree.js',
                     '/public/js/shares/tenders2tree.js',
-                    '/public/js/spss_info.js',
+                    '/public/js/spss_gather_stage_info.js',
                 ],
-                mergeFile: 'spss_info',
+                mergeFile: 'spss_gather_stage_info',
             },
             gatherLedger: {
                 files: [