瀏覽代碼

金额概况,列设置

MaiXinRong 1 年之前
父節點
當前提交
cd6ffc8a11

+ 45 - 0
app/const/project_setting.js

@@ -21,6 +21,51 @@ const notice_setting = {
         end: null,
     },
 };
+
+const colSet = {
+    info: [
+        { field: 'name', name: '标段名称', fixed: ['show', 'alias'] },
+        { field: 'measure_type', name: '计量模式', fixed: ['show', 'alias'] },
+        { field: 'calc_flow', name: '计量进度', fixed: ['show', 'alias'] },
+        { field: 'cur_flow', name: '当前流程', fixed: ['show', 'alias'] },
+        { field: 'contract_price', name: '签约合同价', fixed: ['show', 'alias'] },
+        { field: 'total_price', name: '0号台账', fixed: [] },
+        { field: 'gather_tp', name: '本期完成', fixed: [] },
+        { field: 'end_contract_tp', name: '截止本期合同', fixed: [] },
+        { field: 'end_qc_tp', name: '截止本期变更', fixed: [] },
+        { field: 'end_gather_tp', name: '截止本期完成', fixed: [] },
+        { field: 'pre_gather_tp', name: '截止上期完成', fixed: [] },
+        { field: 'advance_tp', name: '预付款', fixed: [] },
+        { field: 'yf_tp', name: '本期应付', fixed: [] },
+        { field: 'end_yf_tp', name: '截止本期应付', fixed: [] },
+        { field: 'sf_tp', name: '本期实付', fixed: [] },
+        { field: 'end_sf_tp', name: '截止本期实付', fixed: [] },
+        { field: 'wf_tp', name: '未付金额', fixed: [], hint:'截止本期完成-截止本期实付' },
+    ]
+};
+const defaultColSet = {
+    info: [
+        { field: 'name', show: 1, alias: '' },
+        { field: 'measure_type', show: 1, alias: '' },
+        { field: 'calc_flow', show: 1, alias: '' },
+        { field: 'cur_flow', show: 1, alias: '' },
+        { field: 'contract_price', show: 1, alias: '' },
+        { field: 'total_price', show: 1, alias: '' },
+        { field: 'gather_tp', show: 1, alias: '' },
+        { field: 'end_contract_tp', show: 1, alias: '' },
+        { field: 'end_qc_tp', show: 1, alias: '' },
+        { field: 'end_gather_tp', show: 1, alias: '' },
+        { field: 'pre_gather_tp', show: 1, alias: '' },
+        { field: 'advance_tp', show: 1, alias: '' },
+        { field: 'yf_tp', show: 1, alias: '' },
+        { field: 'end_yf_tp', show: 1, alias: '' },
+        { field: 'sf_tp', show: 0, alias: '' },
+        { field: 'end_sf_tp', show: 0, alias: '' },
+        { field: 'wf_tp', show: 0, alias: '' },
+    ],
+};
 module.exports = {
     noticeSetting: notice_setting,
+    colSet,
+    defaultColSet,
 };

+ 17 - 0
app/controller/project_controller.js

@@ -152,6 +152,23 @@ module.exports = app => {
 
             ctx.body = responseData;
         }
+
+        /**
+         * 保存列设置
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async colSet(ctx) {
+            try {
+                const colType = ctx.request.body.col_type;
+                const colSet = JSON.parse(ctx.request.body.col_set);
+                await ctx.service.projectColSet.setProjectColSet(ctx.session.sessionProject.id, colType, colSet);
+                ctx.redirect(ctx.request.header.referer);
+            } catch (err) {
+                ctx.redirect(ctx.request.header.referer);
+            }
+
+        }
     }
 
     return ProjectController;

+ 11 - 2
app/controller/tender_controller.js

@@ -25,6 +25,7 @@ const changeConst = require('../const/change');
 const tenderInfoModel = require('../lib/tender_info');
 const mapConst = require('../const/map');
 const advanceConst = require('../const/advance');
+const projectSetting = require('../const/project_setting');
 
 module.exports = app => {
 
@@ -40,9 +41,10 @@ module.exports = app => {
             super(ctx);
             ctx.showProject = true;
             ctx.showTitle = true;
+            this.colSet = [];
         }
 
-        async _listDetailCache(view, modal = '') {
+        async _listDetailCache(view, modal = '', type) {
             try {
                 // 获取用户新建标段权利
                 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
@@ -66,6 +68,7 @@ module.exports = app => {
                     valuations,
                     uid: this.ctx.session.sessionUser.accountId,
                     pid: this.ctx.session.sessionProject.id,
+                    colSet: this.colSet,
                 };
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = false;
@@ -76,7 +79,7 @@ module.exports = app => {
             }
         }
 
-        async _listDetailFinish(view, modal = '') {
+        async _listDetailFinish(view, modal = '', type) {
             try {
                 // 获取用户新建标段权利
                 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
@@ -100,6 +103,7 @@ module.exports = app => {
                     valuations,
                     uid: this.ctx.session.sessionUser.accountId,
                     pid: this.ctx.session.sessionProject.id,
+                    colSet: this.colSet,
                 };
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = true;
@@ -129,6 +133,7 @@ module.exports = app => {
                 renderData.pid = this.ctx.session.sessionProject.id;
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = false;
+                renderData.colSet = this.colSet;
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -155,6 +160,7 @@ module.exports = app => {
                 renderData.pid = this.ctx.session.sessionProject.id;
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = true;
+                renderData.colSet = this.colSet;
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -169,6 +175,7 @@ module.exports = app => {
             const renderData = {
                 accountInfo,
                 userPermission,
+                colSet: this.colSet,
             };
             await this._listCache('tender/index.ejs', renderData, 'tender/modal.ejs');
         }
@@ -181,6 +188,8 @@ module.exports = app => {
          */
         async listInfo(ctx) {
             this.jsFiles = this.app.jsFiles.tender.info;
+            const projectColSet = await ctx.service.projectColSet.getProjectColSet(ctx.session.sessionProject.id);
+            this.colSet = ctx.service.projectColSet.analysisColSetWithDefine(projectSetting.colSet.info, projectColSet.info);
             await this._listDetailCache('tender/info.ejs', 'tender/modal.ejs');
         }
 

+ 160 - 89
app/public/js/tender_list_info.js

@@ -8,65 +8,81 @@
  * @version
  */
 const tenderListSpec = (function(){
+    let colSetCache;
+    function generateColSetCache() {
+        const result = {};
+        colSet.forEach(x => {
+            result[x.field] = { show: x.show, alias: x.alias || x.name };
+        });
+        return result;
+    };
     function getTenderNodeHtml(node, arr, pid) {
         const html = [];
         html.push('<tr pid="' + pid + '">');
         // 名称
-        html.push('<td style="min-width: 300px;" class="in-' + node.level + '">');
-        if (node.cid) {
-            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ');
-            html.push((node.level === 1 ? '<b>' : ''), node.name, (node.level === 1 ? '</b>' : ''));
-        } else {
-            html.push('<span class="text-muted mr-2">');
-            html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
-            html.push('</span>');
-            //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
-            html.push('<a href="javascript: void(0)" name="name" style="min-width: 300px;word-break:break-all;" id="' + node.id + '">', node.name, '</a>');
-        }
-        html.push('</td>');
+        if (colSetCache.name.show) {
+            html.push('<td style="min-width: 300px;" class="in-' + node.level + '">');
+            if (node.cid) {
+                html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="' + node.sort_id + '"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ');
+                html.push((node.level === 1 ? '<b>' : ''), node.name, (node.level === 1 ? '</b>' : ''));
+            } else {
+                html.push('<span class="text-muted mr-2">');
+                html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+                html.push('</span>');
+                //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
+                html.push('<a href="javascript: void(0)" name="name" style="min-width: 300px;word-break:break-all;" id="' + node.id + '">', node.name, '</a>');
+            }
+            html.push('</td>');
+        }
         // 计量模式
-        html.push('<td style="width: 85px" class="text-center">');
-        if (node.measure_type) {
-            html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+        if (colSetCache.measure_type.show) {
+            html.push('<td style="width: 85px" class="text-center">');
+            if (node.measure_type) {
+                html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+            }
+            html.push('</td>');
         }
-        html.push('</td>');
         // 计量进度
-        html.push('<td style="width: 125px">');
-        if (!node.cid && node.cur_flow) {
-            if (node.progress) {
-                html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
-            } else {
-                html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
+        if (colSetCache.calc_flow.show) {
+            html.push('<td style="width: 125px">');
+            if (!node.cid && node.cur_flow) {
+                if (node.progress) {
+                    html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class + '">' + node.progress.status + '</span>' + ')');
+                } else {
+                    html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class + '">' + node.cur_flow.status + '</span>' + ')');
+                }
             }
+            html.push('</td>');
         }
-        html.push('</td>');
         // 当前流程
-        html.push('<td style="width: 230px">');
-        if (!node.cid && node.cur_flow) {
-            const curUser = node.cur_flow instanceof Array && node.cur_flow[0].audit_type && node.cur_flow[0].audit_type !== auditType.key.common
-                ? transFormToChinese(node.cur_flow[0].audit_order) + '审'
-                : node.cur_flow instanceof Array ? (node.cur_flow[0].name + (node.cur_flow[0].role ? '-'+node.cur_flow[0].role  : '')): (node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
-            if (node.stage_status !== undefined) {
-                html.push(((node.stage_count && node.stage_status === auditConst.stage.status.uncheck) || node.ledger_status === auditConst.ledger.status.uncheck)
-                    ? curUser
-                    : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
-                );
-                html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
-            } else {
-                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
-                    '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
-                    ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
-                html.push(curUser);
-                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
-                    '</a> ');
-                if (node.cur_flow instanceof Array) {
-                    html.push('<span class="' + node.cur_flow[0].status_class +'">' + node.cur_flow[0].status + '</span>');
+        if (colSetCache.cur_flow.show) {
+            html.push('<td style="width: 230px">');
+            if (!node.cid && node.cur_flow) {
+                const curUser = node.cur_flow instanceof Array && node.cur_flow[0].audit_type && node.cur_flow[0].audit_type !== auditType.key.common
+                    ? transFormToChinese(node.cur_flow[0].audit_order) + '审'
+                    : node.cur_flow instanceof Array ? (node.cur_flow[0].name + (node.cur_flow[0].role ? '-' + node.cur_flow[0].role : '')) : (node.cur_flow.name + (node.cur_flow.role ? '-' + node.cur_flow.role : ''));
+                if (node.stage_status !== undefined) {
+                    html.push(((node.stage_count && node.stage_status === auditConst.stage.status.uncheck) || node.ledger_status === auditConst.ledger.status.uncheck)
+                        ? curUser
+                        : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
+                    );
+                    html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
                 } else {
-                    html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+                    html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck) ? '' :
+                        '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="' + (node.lastStage ? 'stage' : 'ledger') + '"' +
+                        ' data-tender="' + node.id + '" data-order="' + (node.lastStage ? node.lastStage.order : '') + '">');
+                    html.push(curUser);
+                    html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck) ? ' ' :
+                        '</a> ');
+                    if (node.cur_flow instanceof Array) {
+                        html.push('<span class="' + node.cur_flow[0].status_class + '">' + node.cur_flow[0].status + '</span>');
+                    } else {
+                        html.push('<span class="' + node.cur_flow.status_class + '">' + node.cur_flow.status + '</span>');
+                    }
                 }
             }
+            html.push('</td>');
         }
-        html.push('</td>');
         // 上一流程审批时间
         // html.push('<td style="width: 7%">');
         // if (!node.cid && node.pre_flow) {
@@ -74,67 +90,110 @@ const tenderListSpec = (function(){
         // }
         // html.push('</td>');
         // 签约合同价
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.contract_price || '');
-        html.push('</td>');
+        if (colSetCache.contract_price.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.contract_price || '');
+            html.push('</td>');
+        }
         // 0号台账合同
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.total_price || '');
-        html.push('</td>');
+        if (colSetCache.total_price.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.total_price || '');
+            html.push('</td>');
+        }
         // 本期完成
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.gather_tp || '');
-        html.push('</td>');
+        if (colSetCache.gather_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.gather_tp || '');
+            html.push('</td>');
+        }
         // 截止本期合同
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_contract_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_contract_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_contract_tp || '');
+            html.push('</td>');
+        }
         // 截止本期变更
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_qc_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_qc_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_qc_tp || '');
+            html.push('</td>');
+        }
         // 截止本期完成
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_gather_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_gather_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_gather_tp || '');
+            html.push('</td>');
+        }
         // 截止上期完成
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.pre_gather_tp || '');
-        html.push('</td>');
+        if (colSetCache.pre_gather_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.pre_gather_tp || '');
+            html.push('</td>');
+        }
         // 预付款
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.advance_tp || '');
-        html.push('</td>');
+        if (colSetCache.advance_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.advance_tp || '');
+            html.push('</td>');
+        }
         // 本期应付
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.yf_tp || '');
-        html.push('</td>');
+        if (colSetCache.yf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.yf_tp || '');
+            html.push('</td>');
+        }
         // 截止本期应付
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_yf_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_yf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_yf_tp || '');
+            html.push('</td>');
+        }
+        // 本期实付
+        if (colSetCache.sf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.yf_tp || '');
+            html.push('</td>');
+        }
+        // 截止本期实付
+        if (colSetCache.end_sf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_sf_tp || '');
+            html.push('</td>');
+        }
+        // 本期未付
+        if (colSetCache.wf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.wf_tp || '');
+            html.push('</td>');
+        }
         html.push('</tr>');
         return html.join('');
     }
     function getTenderTreeHeaderHtml() {
+        colSetCache = generateColSetCache();
+        console.log(colSetCache);
         const html = [];
         html.push('<table class="table table-hover table-bordered">');
         html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
-        html.push('<th class="text-center" style="min-width: 300px;">', '标段名称', '</th>');
-        html.push('<th class="text-center" style="width: 85px">', '计量模式', '</th>');
-        html.push('<th class="text-center" style="width: 125px">', '计量进度', '</th>');
-        html.push('<th class="text-center" style="width: 230px">', '当前流程', '</th>');
+        if (colSetCache.name.show) html.push('<th class="text-center" style="min-width: 300px;">', colSetCache.name.alias, '</th>');
+        if (colSetCache.measure_type.show) html.push('<th class="text-center" style="width: 85px">', colSetCache.measure_type.alias, '</th>');
+        if (colSetCache.calc_flow.show) html.push('<th class="text-center" style="width: 125px">', colSetCache.calc_flow.alias, '</th>');
+        if (colSetCache.cur_flow.show) html.push('<th class="text-center" style="width: 230px">', colSetCache.cur_flow.alias, '</th>');
         // html.push('<th class="text-center" style="width: 7%">', '上一流程审批时间', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '签约合同价', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '0号台账', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '本期完成', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期合同', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期变更', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期完成', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止上期完成', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '预付款', '<i class="fa fa-question-circle text-primary" data-placement="bottom" data-toggle="tooltip" data-original-title="预付款流程中截止本期金额"></i>', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '本期应付', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期应付', '</th>');
+        if (colSetCache.contract_price.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.contract_price.alias, '</th>');
+        if (colSetCache.total_price.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.total_price.alias, '</th>');
+        if (colSetCache.gather_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.gather_tp.alias, '</th>');
+        if (colSetCache.end_contract_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_contract_tp.alias, '</th>');
+        if (colSetCache.end_qc_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_qc_tp.alias, '</th>');
+        if (colSetCache.end_gather_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_gather_tp.alias, '</th>');
+        if (colSetCache.pre_gather_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.pre_gather_tp.alias, '</th>');
+        if (colSetCache.advance_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.advance_tp.alias, '<i class="fa fa-question-circle text-primary" data-placement="bottom" data-toggle="tooltip" data-original-title="预付款流程中截止本期金额"></i>', '</th>');
+        if (colSetCache.yf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.yf_tp.alias, '</th>');
+        if (colSetCache.end_yf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_yf_tp.alias, '</th>');
+        if (colSetCache.sf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.sf_tp.alias, '</th>');
+        if (colSetCache.end_sf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_sf_tp.alias, '</th>');
+        if (colSetCache.wf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.wf_tp.alias, '</th>');
         html.push('</tr>', '</thead>');
         return html.join('');
     }
@@ -147,6 +206,9 @@ const tenderListSpec = (function(){
             tender.pre_gather_tp = ZhCalc.add(tender.stage_tp.pre_contract_tp, tender.stage_tp.pre_qc_tp);
             tender.yf_tp = ZhCalc.add(tender.stage_tp.yf_tp);
             tender.end_yf_tp = ZhCalc.add(tender.stage_tp.pre_yf_tp, tender.yf_tp);
+            tender.sf_tp = ZhCalc.add(tender.stage_tp.sf_tp);
+            tender.end_sf_tp = ZhCalc.add(tender.stage_tp.pre_sf_tp, tender.sf_tp);
+            tender.wf_tp = ZhCalc.sub(tender.end_yf_tp, tender.end_sf_tp);
         } else if (tender.lastStage) {
             tender.gather_tp = ZhCalc.sum([tender.lastStage.contract_tp, tender.lastStage.qc_tp, tender.lastStage.pc_tp]);
             tender.end_contract_tp = ZhCalc.sum([tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp, tender.lastStage.contract_pc_tp]);
@@ -155,6 +217,9 @@ const tenderListSpec = (function(){
             tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
             tender.yf_tp = ZhCalc.add(tender.lastStage.yf_tp);
             tender.end_yf_tp = ZhCalc.add(tender.lastStage.pre_yf_tp, tender.yf_tp);
+            tender.sf_tp = ZhCalc.add(tender.lastStage.sf_tp);
+            tender.end_sf_tp = ZhCalc.add(tender.lastStage.pre_sf_tp, tender.sf_tp);
+            tender.wf_tp = ZhCalc.sub(tender.end_yf_tp, tender.end_sf_tp);
         }
     }
     function calculateParent(node) {
@@ -169,6 +234,9 @@ const tenderListSpec = (function(){
             node.end_yf_tp = 0;
             node.advance_tp = 0;
             node.contract_price = 0;
+            node.sf_tp = 0;
+            node.end_sf_tp = 0;
+            node.wf_tp = 0;
             for (const c of node.children) {
                 calculateParent(c);
                 node.total_price = ZhCalc.add(node.total_price, c.total_price);
@@ -181,6 +249,9 @@ const tenderListSpec = (function(){
                 node.end_yf_tp = ZhCalc.add(node.end_yf_tp, c.end_yf_tp);
                 node.advance_tp = ZhCalc.add(node.advance_tp, c.advance_tp);
                 node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
+                node.sf_tp = ZhCalc.add(node.sf_tp, c.sf_tp);
+                node.end_sf_tp = ZhCalc.add(node.end_sf_tp, c.end_sf_tp);
+                node.wf_tp = ZhCalc.add(node.wf_tp, c.wf_tp);
             }
         }
     }

+ 1 - 0
app/router.js

@@ -160,6 +160,7 @@ module.exports = app => {
     app.post('/list/load2', sessionAuth, 'tenderController.listLoad2');
     app.get('/list/info', sessionAuth, 'tenderController.listInfo');
     app.get('/list/info/finish', sessionAuth, 'tenderController.listInfoFinish');
+    app.post('/list/info/col-set', sessionAuth, projectManagerCheck, 'projectController.colSet');
 
     // 计量进度
     app.get('/list/progress', sessionAuth, 'tenderController.listProgress');

+ 75 - 0
app/service/project_col_set.js

@@ -0,0 +1,75 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2024/3/5
+ * @version
+ */
+
+const JsonFields = [ 'info' ];
+const ProjectSetting = require('../const/project_setting');
+
+module.exports = app => {
+
+    class ProjectColSet extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'project_col_set';
+        }
+
+        _analysisData(data) {
+            if (!data) return;
+            JsonFields.forEach(jf => { if(data[jf]) data[jf] = JSON.parse(data[jf]); });
+        }
+
+        async loadProjectColSet(id) {
+            const result = await this.getDataById(id);
+            this._analysisData(result);
+            return result;
+        }
+
+        async initProjectColSet(id) {
+            const data = ProjectSetting.defaultColSet;
+            JsonFields.forEach(jf => { if(data[jf]) data[jf] = JSON.stringify(data[jf]); });
+            data.id = id;
+            await this.db.insert(this.tableName, data);
+        }
+
+        async getProjectColSet(id) {
+            const curSet = await this.loadProjectColSet(id);
+            if (curSet) return curSet;
+            await this.initProjectColSet(id);
+            return await this.loadProjectColSet(id);
+        }
+
+        async setProjectColSet(id, colSetType, colSet) {
+            const data = {id};
+            data[colSetType] = JSON.stringify(colSet);
+            await this.defaultUpdate(data);
+        }
+
+        analysisColSetWithDefine(colSetDefine, colSet) {
+            const result = [];
+            for (const csd of colSetDefine) {
+                const cs = colSet.find(x => { return x.field === csd.field });
+                if (cs) {
+                    result.push({...csd, ...cs});
+                } else {
+                    result.push({...csd});
+                }
+            }
+            return result;
+        }
+    }
+
+    return ProjectColSet;
+};

+ 60 - 1
app/view/tender/modal.ejs

@@ -72,6 +72,56 @@
         </div>
     </div>
 </div>
+<!--弹出列设置-->
+<div class="modal fade" id="col-set" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">列设置</h5>
+            </div>
+            <div class="modal-body">
+                <table class="table table-hover table-bordered">
+                    <thead><tr><th width="150px">列名</th><th width="150px">别名</th><th width="50px">显示</th></tr></thead>
+                    <tbody class="text-center">
+                    <% for (const cs of colSet) { %>
+                    <tr code="<%- cs.field %>">
+                        <td><%- cs.name %><% if (cs.hint) { %><i class="fa fa-question-circle text-primary ml-1" data-placement="bottom" data-toggle="tooltip" data-original-title="<%- cs.hint %>"></i><% } %></td>
+                        <% if (cs.fixed.indexOf('alias') >= 0) { %>
+                        <td class="disabled">-</td>
+                        <% } else {%>
+                        <td><input type="text" class="form-control form-control-sm" value="<%- cs.alias %>"></td>
+                        <% } %>
+                        <% if (cs.fixed.indexOf('show') >= 0 ) { %>
+                        <td>
+                            <div class="form-check form-check-inline">
+                                <input class="form-check-input" type="checkbox" id="inlineCheckbox-<%- cs.code %>" checked="" disabled="">
+                                <label class="form-check-label" for="inlineCheckbox-<%- cs.code %>"></label>
+                            </div>
+                        </td>
+                        <% } else { %>
+                        <td>
+                            <div class="form-check form-check-inline">
+                                <input class="form-check-input" type="checkbox" id="inlineCheckbox-<%- cs.code %>" <% if (cs.show) { %> checked <% } %> >
+                                <label class="form-check-label" for="inlineCheckbox-<%- cs.code %>"></label>
+                            </div>
+                        </td>
+                        <% } %>
+                    </tr>
+                    <% } %>
+                    </tbody>
+                </table>
+                <div class="text-danger">谨慎修改别名(修改后将导致各页面概念不一致)</div>
+            </div>
+            <form class="modal-footer" action="/list/info/col-set" method="post" onsubmit="return onSetCol();">
+                <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>">
+                <input type="hidden" name="col_set" value="">
+                <input type="hidden" name="col_type" value="info">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-primary btn-sm" id="add-bd-ok">确定修改</button>
+            </form>
+        </div>
+    </div>
+</div>
 <!--弹出计量模式选择-->
 <div class="modal fade" id="jlms" data-backdrop="static">
     <div class="modal-dialog modal-lg" role="document">
@@ -118,6 +168,15 @@
 </div>
 <script>
     const auditType = JSON.parse('<%- JSON.stringify(auditConst.auditType) %>');
+    const colSet = JSON.parse('<%- JSON.stringify(colSet) %>');
+    const onSetCol = function() {
+        const trs = $('tr[code]', '#col-set');
+        const colSet = [];
+        for (const tr of trs) {
+            colSet.push({ field: $(tr).attr('code'), show: $('input[type=checkbox]', tr)[0].checked, alias: $('input[type=text]', tr).val() || ''});
+        }
+        $('input[name=col_set]').val(JSON.stringify(colSet));
+    };
     $(document).ready(function () {
         const getAuditTypeText = function (type) {
             if (type === auditType.key.common) return '';
@@ -425,5 +484,5 @@
             }
             return `${year}<span class="${dayMode ? 'text-light' : ''}">${mon}-${day}</span><span class="${dayMode ? 'text-light' : ''}">${hour}:${minute}:${scond}</span>`;
         };
-    })
+    });
 </script>

+ 6 - 3
app/view/tender/sub_menu.ejs

@@ -36,11 +36,14 @@
                 <!--</div>-->
             <!--</div>-->
         </div>
-        <% if (ctx.app.config.is_debug) { %>
         <div>
-            <a href="/compare/tz" class="btn btn-sm btn-primary pull-right" target="_blank">统计分析</a>
+            <% if (ctx.app.config.is_debug) { %>
+            <a href="/compare/tz" class="btn btn-sm btn-primary" target="_blank">统计分析</a>
+            <% } %>
+            <% if (ctx.session.sessionUser.is_admin && ctx.url === '/list/info') { %>
+            <a href="#col-set" class="btn btn-sm btn-primary ml-1" data-toggle="modal" data-target="#col-set">列设置</a>
+            <% } %>
         </div>
-        <% } %>
         <div>
             <a href="/list/info/finish" class="btn btn-sm btn-primary pull-right ml-1" target="_blank">完工标段</a>
             <% if (userPermission !== null && userPermission.tender !== undefined && userPermission.tender.indexOf('1') !== -1) { %>