Browse Source

成本管理相关

MaiXinRong 1 tháng trước cách đây
mục cha
commit
c1d4534f42

+ 49 - 0
app/controller/cost_controller.js

@@ -109,7 +109,9 @@ module.exports = app => {
             try {
                 const stage_type = this.ctx.service.costStage.stageType.ledger.key;
                 const stages = await this.getTypeStages(ctx, stage_type);
+                const colSet = this.ctx.service.subProject.getColSet('cost_' + stage_type);
                 const renderData = {
+                    colSet,
                     stage_type,
                     auditType: audit.auditType,
                     stages,
@@ -126,6 +128,9 @@ module.exports = app => {
             try {
                 const stage_type = this.ctx.service.costStage.stageType.book.key;
                 const stages = await this.getTypeStages(ctx, stage_type);
+                for (const s of stages) {
+                    s.relaStage = await this.ctx.service.costStage.getStage(s.rela_stage.sid);
+                }
                 const validLedgerStages = await this.ctx.service.costStage.getAllCheckedStages(ctx.tender.id, 'ledger', 'DESC');
                 for (const vls of validLedgerStages) {
                     vls.beenRela = stages.findIndex(x => { return x.rela_stage.sid === vls.id; }) >= 0;
@@ -278,6 +283,7 @@ module.exports = app => {
                     });
                     payStages = stages.map(x => { return { order: x.order, date: x.s_time }; });
                 }
+                const colSet = this.ctx.service.subProject.getColSet('cost_' + ctx.costStage.stage_type);
                 const renderData = {
                     auditConst: audit.common,
                     auditType: audit.auditType,
@@ -290,6 +296,7 @@ module.exports = app => {
                     shenpi_status: ctx.tender.info.shenpi[stageTypeInfo.shenpi_status] || 1,
                     contractTypes,
                     contractUsed,
+                    colSet,
                 };
                 await this.layout(`cost/${stageTypeInfo.key}.ejs`, renderData, `cost/${stageTypeInfo.key}_modal.ejs`);
             } catch (err) {
@@ -449,6 +456,9 @@ module.exports = app => {
                         case 'auditFlow':
                             responseData.data[f] = await ctx.service.costStageAudit.getViewFlow(ctx.costStage);
                             break;
+                        case 'att':
+                            responseData.data[f] = await ctx.service.costStageFile.getData(ctx.costStage.id, 'DESC');
+                            break;
                         default:
                             responseData.data[f] = [];
                             break;
@@ -833,6 +843,45 @@ module.exports = app => {
                 ctx.body = { err: 1, msg: error.toString(), data: null };
             }
         }
+
+        async colSet(ctx) {
+            const stage_type = ctx.request.body.stage_type;
+            try {
+                const colSet = {};
+                for (const prop in ctx.request.body) {
+                    if (prop.indexOf('col_') === 0) colSet[prop.replace('col_', '')] = ctx.request.body[prop] === '1' ? 1 : 0;
+                }
+                await this.ctx.service.subProject.updateColSet('cost_' + stage_type, colSet);
+                ctx.redirect(ctx.request.header.referer);
+            } catch (err) {
+                ctx.log(err);
+                ctx.postError(err, '保存列设置失败');
+                ctx.redirect(ctx.request.header.referer);
+            }
+        }
+
+        async gather(ctx) {
+            try {
+                const ledgerStages = await this.getTypeStages(ctx, 'ledger');
+                const renderData = {
+                    ledgerStages,
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.cost.cost_gather)
+                };
+                await this.layout('cost/gather.ejs', renderData, 'cost/gather_modal.ejs');
+            } catch(err) {
+                ctx.log(err);
+                ctx.postError(err, '获取汇总分析页面错误');
+                ctx.redirect(`/sp/${ctx.subProject.id}/cost`);
+            }
+        }
+        async loadGatherData(ctx) {
+            try {
+
+            } catch(err) {
+                ctx.log(err);
+                ctx.ajaxErrorBody(err, '获取汇总数据错误');
+            }
+        }
     }
 
     return CostController;

+ 65 - 3
app/public/js/cost_stage_analysis.js

@@ -53,6 +53,7 @@ $(document).ready(function() {
             $('a[name="base-opr"]').click(function () {
                 self.baseOpr(this.getAttribute('type'));
             });
+            $('#bills-spread').focusin(this.focusIn);
         }
         refreshOperationValid() {
             const setObjEnable = function (obj, enable) {
@@ -112,11 +113,12 @@ $(document).ready(function() {
             setObjEnable($('a[name=base-opr][type=up-level]'), valid && first && sameParent && tree.getParent(first) && !nodeUsed && first.tree_level > 2 && !isFixed);
             setObjEnable($('a[name=base-opr][type=down-level]'), valid && first && sameParent && preNode && !isFixed && !preNode.node_type);
         }
-        loadRelaData() {
+        loadRelaData(loadAtt = true) {
             this.refreshOperationValid();
             SpreadJsObj.saveTopAndSelect(this.sheet, this.ckBillsSpread);
             const select = SpreadJsObj.getSelectObject(this.sheet);
             detailObj.loadDetailData(select);
+            if (loadAtt) costFile.getCurAttHtml(select);
         }
         refreshTree(data) {
             const sheet = this.sheet;
@@ -268,6 +270,7 @@ $(document).ready(function() {
                             sheet.setSelection(sel.row, sel.col, 1, sel.colCount);
                         }
                         self.refreshOperationValid();
+                        costFile.deleteFileByNodeId(result.delete.map(x => { return x.id; }));
                     });
                 });
             } else {
@@ -277,20 +280,25 @@ $(document).ready(function() {
                     if (['up-move', 'down-move'].indexOf(type) > -1) {
                         if (sel) {
                             sheet.setSelection(tree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
-                            // SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(node)]);
+                            SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(node)]);
                         }
                     } else if (type === 'add') {
                         const sel = sheet.getSelections()[0];
                         if (sel) {
                             sheet.setSelection(tree.nodes.indexOf(refreshData.create[0]), sel.col, sel.rowCount, sel.colCount);
-                            // SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(refreshData.create[0])]);
+                            SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(refreshData.create[0])]);
                         }
+                        billsObj.loadRelaData();
                     }
                     self.refreshOperationValid();
                 });
             }
         }
         // 事件
+        focusIn() {
+            const select = SpreadJsObj.getSelectObject(billsObj.sheet);
+            costFile.getCurAttHtml(select);
+        }
         selectionChanged(e, info) {
             if (info.newSelections) {
                 if (!info.oldSelections || info.newSelections[0].row !== info.oldSelections[0].row) {
@@ -501,9 +509,11 @@ $(document).ready(function() {
             this.commonSpreadSetting.tipsSum = true;
 
             this.initSpread();
+            this.initOtherEvent();
         }
         initSpread() {
             SpreadJsObj.initSheet(this.sheet, this.commonSpreadSetting);
+            this.spread.bind(spreadNS.Events.SelectionChanged, this.selectionChanged);
             this.spread.bind(spreadNS.Events.ClipboardChanging, function (e, info) {
                 const copyText = SpreadJsObj.getFilterCopyText(info.sheet);
                 SpreadJsObj.Clipboard.setCopyData(copyText);
@@ -513,6 +523,9 @@ $(document).ready(function() {
             this.spread.bind(spreadNS.Events.ClipboardPasting, this.clipboardPasting);
             SpreadJsObj.addDeleteBind(this.spread, this.deletePress);
         }
+        initOtherEvent() {
+            $('#detail-spread').focusin(this.focusIn);
+        }
         loadData(datas) {
             this.data.loadDatas(datas);
             this.loadDetailData(SpreadJsObj.getSelectObject(billsObj.sheet));
@@ -541,7 +554,21 @@ $(document).ready(function() {
             this.reloadDetailData();
             SpreadJsObj.locateRow(this.sheet, 0, false);
         }
+        loadRelaData() {
+            const select = SpreadJsObj.getSelectObject(this.sheet);
+            if (select) costFile.getCurAttHtml(this.billsNode, select);
+        }
         // 事件
+        focusIn() {
+            detailObj.loadRelaData();
+        }
+        selectionChanged(e, info) {
+            if (info.newSelections) {
+                if (!info.oldSelections || info.newSelections[0].row !== info.oldSelections[0].row) {
+                    detailObj.loadRelaData();
+                }
+            }
+        }
         editEnded(e, info) {
             const setting = info.sheet.zh_setting;
             if (!setting) return;
@@ -882,10 +909,45 @@ $(document).ready(function() {
             }
         },
     });
+    const costFile = $.ledger_att({
+        selector: '#fujian',
+        key: 'id',
+        subKey: 'id',
+        masterKey: 'rela_id',
+        subMasterKey: 'rela_sub_id',
+        uploadUrl: 'file/upload',
+        deleteUrl: 'file/delete',
+        checked: costStageComplete,
+        zipName: `附件.zip`,
+        readOnly: false,
+        fileIdType: 'string',
+        fileInfo: {
+            user_name: 'user_name',
+            user_id: 'user_id',
+            create_time: 'create_time',
+        },
+        getCurHint: function(node) {
+            return`${node.name || ''}`;
+        },
+        locate: function (att) {
+            if (!att) return;
+            SpreadJsObj.locateTreeNode(billsObj.sheet, att.node.tree_id, true);
+            detailObj.loadDetailData(att.node);
+            if (att.sub_node) SpreadJsObj.locateDataBy(detailObj.sheet, n => { return n.id === att.sub_node.id; });
+            costFile.getCurAttHtml(att.node, att.sub_node);
+        }
+    });
     // 加载数据
     postData('load', { filter: 'bills;detail;att;tags' }, function(result) {
         billsObj.loadData(result.bills);
         detailObj.loadData(result.detail);
+
+        for (const f of result.att) {
+            f.node = billsObj.tree.datas.find(x => { return x.id === f.rela_id; });
+            f.sub_node = f.rela_sub_id ? detailObj.data.getItem(f.rela_sub_id) : null;
+        }
+        costFile.loadDatas(result.att);
+        costFile.getCurAttHtml(SpreadJsObj.getSelectObject(billsObj.sheet));
     });
 
     // 展开收起标准清单

+ 17 - 12
app/public/js/cost_stage_book.js

@@ -16,25 +16,30 @@ $(document).ready(function() {
                 isLeaf: 'tree_is_leaf',
                 fullPath: 'tree_full_path',
                 rootId: -1,
-                calcFields: ['sf_tp', 'in_tp', 'in_excl_tax_tp'],
+                calcFields: ['yf_tp', 'sf_tp', 'end_yf_tp', 'end_sf_tp', 'in_tp', 'in_excl_tax_tp', 'end_in_tp', 'end_in_excl_tax_tp'],
                 keys: ['id', 'stage_id', 'tree_id'],
             };
             this.tree = createNewPathTree('ledger', this.treeSetting);
             this.spreadSetting = {
                 cols: [
-                    {title: '编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 230, formatter: '@', cellType: 'tree', readOnly: true},
-                    {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 185, formatter: '@', cellType: 'autoTip', readOnly: true},
-                    {title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit', readOnly: true},
-                    {title: '税率(%)', colSpan: '1', rowSpan: '1', field: 'tax', hAlign: 2, width: 80, type: 'Number', readOnly: true},
-                    {title: '实付金额', colSpan: '1', rowSpan: '1', field: 'sf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
-                    {title: '入账金额', colSpan: '1', rowSpan: '1', field: 'in_tp', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '入账金额(不含税)', colSpan: '1', rowSpan: '1', field: 'in_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
-                    {title: '本期批注', colSpan: '1', rowSpan: '1', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
-                    {title: '备注', colSpan: '1', rowSpan: '1', field: 'memo', hAlign: 0, width: 120, formatter: '@', cellType: 'ellipsisAutoTip'},
+                    {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 230, formatter: '@', cellType: 'tree', readOnly: true},
+                    {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', cellType: 'autoTip', readOnly: true},
+                    {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit', readOnly: true},
+                    {title: '税率(%)', colSpan: '1', rowSpan: '2', field: 'tax', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                    {title: '本期|应付金额', colSpan: '4|1', rowSpan: '1|1', field: 'yf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                    {title: '|实付金额', colSpan: '|1', rowSpan: '|1', field: 'sf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                    {title: '|入账金额', colSpan: '|1', rowSpan: '|1', field: 'in_tp', hAlign: 2, width: 80, type: 'Number'},
+                    {title: '|入账金额\n(不含税)', colSpan: '|1', rowSpan: '|1', field: 'in_excl_tax_tp', hAlign: 2, width: 100, type: 'Number'},
+                    {title: '截止本期|应付金额', colSpan: '4|1', rowSpan: '1|1', field: 'end_yf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                    {title: '|实付金额', colSpan: '|1', rowSpan: '|1', field: 'end_sf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                    {title: '|入账金额', colSpan: '|1', rowSpan: '|1', field: 'end_in_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                    {title: '|入账金额\n(不含税)', colSpan: '|1', rowSpan: '|1', field: 'end_in_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+                    {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
+                    {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 120, formatter: '@', cellType: 'ellipsisAutoTip'},
                 ],
                 emptyRows: 0,
-                headRows: 1,
-                headRowHeight: [32],
+                headRows: 2,
+                headRowHeight: [36, 36],
                 defaultRowHeight: 21,
                 headerFont: '12px 微软雅黑',
                 font: '12px 微软雅黑',

+ 22 - 15
app/public/js/cost_stage_ledger.js

@@ -16,28 +16,34 @@ $(document).ready(function() {
                 isLeaf: 'tree_is_leaf',
                 fullPath: 'tree_full_path',
                 rootId: -1,
-                calcFields: ['yf_tp', 'sf_tp', 'pay_tp', 'cut_tp', 'yf_excl_tax_tp', 'sf_excl_tax_tp'],
+                calcFields: ['yf_tp', 'sf_tp', 'pay_tp', 'cut_tp', 'yf_excl_tax_tp', 'sf_excl_tax_tp', 'end_yf_tp', 'end_sf_tp', 'end_pay_tp', 'end_cut_tp', 'end_yf_excl_tax_tp', 'end_sf_excl_tax_tp'],
                 keys: ['id', 'stage_id', 'tree_id'],
             };
             this.tree = createNewPathTree('ledger', this.treeSetting);
             this.spreadSetting = {
                 cols: [
-                    {title: '编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 230, formatter: '@', cellType: 'tree'},
-                    {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 185, formatter: '@', cellType: 'autoTip'},
-                    {title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
-                    {title: '税率(%)', colSpan: '1', rowSpan: '1', field: 'tax', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '付款金额', colSpan: '1', rowSpan: '1', field: 'pay_tp', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '扣款金额', colSpan: '1', rowSpan: '1', field: 'cut_tp', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '应付金额', colSpan: '1', rowSpan: '1', field: 'yf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true},
-                    {title: '实付金额', colSpan: '1', rowSpan: '1', field: 'sf_tp', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '应付金额(不含税)', colSpan: '1', rowSpan: '1', field: 'yf_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
-                    {title: '实付金额(不含税)', colSpan: '1', rowSpan: '1', field: 'sf_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
-                    {title: '本期批注', colSpan: '1', rowSpan: '1', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
-                    {title: '备注', colSpan: '1', rowSpan: '1', field: 'memo', hAlign: 0, width: 120, formatter: '@', cellType: 'ellipsisAutoTip'},
+                    {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 230, formatter: '@', cellType: 'tree'},
+                    {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', cellType: 'autoTip'},
+                    {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
+                    {title: '税率(%)', colSpan: '1', rowSpan: '2', field: 'tax', hAlign: 2, width: 80, type: 'Number'},
+                    {title: '本期|付款金额', colSpan: '4|1', rowSpan: '1|1', field: 'pay_tp', hAlign: 2, width: 80, type: 'Number', visible: colSet.cur ? true : false},
+                    {title: '|扣款金额', colSpan: '|1', rowSpan: '|1', field: 'cut_tp', hAlign: 2, width: 80, type: 'Number', visible: colSet.cur ? true : false},
+                    {title: '|应付金额', colSpan: '|1', rowSpan: '|1', field: 'yf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, visible: colSet.cur ? true : false},
+                    {title: '|实付金额', colSpan: '|1', rowSpan: '|1', field: 'sf_tp', hAlign: 2, width: 80, type: 'Number', visible: colSet.cur ? true : false},
+                    {title: '本期(不含税)|应付金额', colSpan: '2|1', rowSpan: '1|1', field: 'yf_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, visible: colSet.cur_excl_tax ? true : false},
+                    {title: '|实付金额', colSpan: '|1', rowSpan: '|1', field: 'sf_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, visible: colSet.cur_excl_tax ? true : false},
+                    {title: '截止本期|付款金额', colSpan: '4|1', rowSpan: '1|1', field: 'end_pay_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, visible: colSet.end ? true : false},
+                    {title: '|扣款金额', colSpan: '|1', rowSpan: '|1', field: 'end_cut_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, visible: colSet.end ? true : false},
+                    {title: '|应付金额', colSpan: '|1', rowSpan: '|1', field: 'end_yf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, visible: colSet.end ? true : false},
+                    {title: '|实付金额', colSpan: '|1', rowSpan: '|1', field: 'end_sf_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, visible: colSet.end ? true : false},
+                    {title: '截止本期(不含税)|应付金额', colSpan: '2|1', rowSpan: '1|1', field: 'end_yf_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, visible: colSet.end_excl_tax ? true : false},
+                    {title: '|实付金额', colSpan: '|1', rowSpan: '|1', field: 'end_sf_excl_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, visible: colSet.end_excl_tax ? true : false},
+                    {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
+                    {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 120, formatter: '@', cellType: 'ellipsisAutoTip'},
                 ],
                 emptyRows: 0,
-                headRows: 1,
-                headRowHeight: [32],
+                headRows: 2,
+                headRowHeight: [25, 25],
                 defaultRowHeight: 21,
                 headerFont: '12px 微软雅黑',
                 font: '12px 微软雅黑',
@@ -321,6 +327,7 @@ $(document).ready(function() {
                         }
                         self.refreshOperationValid();
                         billsTag.afterDeleteBills(refreshData.delete);
+                        costFile.deleteFileBySubNodeId(refreshData.delete.map(x => { return x.id; }));
                     });
                 });
             } else {

+ 2 - 0
app/router.js

@@ -557,6 +557,7 @@ module.exports = app => {
     app.post('/sp/:id/cost/tender/:tid/addStage', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, 'costController.addStage');
     app.post('/sp/:id/cost/tender/:tid/delStage', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, 'costController.delStage');
     app.post('/sp/:id/cost/tender/:tid/:stype/auditors', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, 'costController.loadAuditors');
+    app.post('/sp/:id/cost/tender/:tid/colSet', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, 'costController.colSet');
     app.get('/sp/:id/cost/tender/:tid/:stype/:sorder/stage', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, costStageCheck, 'costController.stage');
     app.post('/sp/:id/cost/tender/:tid/:stype/:sorder/load', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, costStageCheck, 'costController.stageLoad');
     app.post('/sp/:id/cost/tender/:tid/:stype/:sorder/update', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, costStageCheck, 'costController.stageUpdate');
@@ -570,6 +571,7 @@ module.exports = app => {
     app.post('/sp/:id/cost/tender/:tid/:stype/:sorder/audit/check', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, costStageCheck, 'costController.stageAuditCheck');
     app.post('/sp/:id/cost/tender/:tid/:stype/:sorder/audit/checkAgain', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, costStageCheck, 'costController.stageAuditCheckAgain');
     app.post('/sp/:id/cost/tender/:tid/:stype/:sorder/audit/checkCancel', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, costStageCheck, 'costController.stageAuditCheckCancel');
+    app.get('/sp/:id/cost/tender/:tid/gather', sessionAuth, subProjectCheck, tenderCheck, tenderPermissionCheck, 'costController.gather');
 
     // 安全管理
     // 安全计量

+ 10 - 0
app/service/cost_stage_analysis.js

@@ -60,6 +60,16 @@ module.exports = app => {
                 data[f] = 0;
             }
         }
+        /**
+         * 删除相关数据 继承
+         * @param mid
+         * @param deleteData
+         * @return {Promise<void>}
+         * @private
+         */
+        async _deleteRelaData(mid, deleteData) {
+            await this.transaction.delete(this.ctx.service.costStageFile.tableName, { rela_id: this._.map(deleteData, 'id') });
+        }
 
         _getDefaultData(data, stage) {
             data.id = this.uuid.v4();

+ 5 - 1
app/service/cost_stage_detail.js

@@ -207,7 +207,7 @@ module.exports = app => {
                 await conn.delete(this.tableName, { id: data });
                 if (updateData.length > 0) await conn.updateRows(this.tableName, updateData);
                 await conn.delete(this.ctx.service.costStageTag.tableName, { rela_sub_id: data });
-                await conn.delete(this.ctx.service.costStageFile.tableName, { rela_sub_id: data });
+                await conn.update(this.ctx.service.costStageFile.tableName, { is_deleted: 1 }, { where: { rela_sub_id: data } });
                 await conn.update(this.ctx.service.costStageLedger.tableName, billsUpdate);
                 await conn.commit();
                 return [data, updateData, billsUpdate];
@@ -337,6 +337,10 @@ module.exports = app => {
             const conn = await this.db.beginTransaction();
             try {
                 await conn.delete(this.tableName, { stage_id: this.ctx.costStage.id, ledger_id: ledgerId });
+                if (detailDatas.length > 0) {
+                    await this.transaction.update(this.ctx.service.costStageFile.tableName, { is_deleted: 1 }, { where: { rela_sub_id: detailDatas.map(x => { return x.id; }) } });
+                    await conn.delete(this.ctx.service.costStageTag.tableName, { rela_sub_id: detailDatas.map(x => { return x.id; }) });
+                }
                 if (insertDetails.length > 0) await conn.insert(this.tableName, insertDetails);
                 await conn.update(this.ctx.service.costStageLedger.tableName, billsUpdate);
                 await conn.commit();

+ 12 - 0
app/service/cost_stage_ledger.js

@@ -161,6 +161,18 @@ module.exports = app => {
         }
 
         /**
+         * 删除相关数据 继承
+         * @param mid
+         * @param deleteData
+         * @return {Promise<void>}
+         * @private
+         */
+        async _deleteRelaData(mid, deleteData) {
+            await this.ctx.service.costStageDetail.deletePartData(this.transaction, mid, this._.map(deleteData, 'id'));
+            await this.transaction.update(this.ctx.service.costStageFile.tableName, { is_deleted: 1 }, { where: { rela_id: this._.map(deleteData, 'id') } });
+            await this.transaction.delete(this.ctx.service.costStageTag.tableName, { rela_id: this._.map(deleteData, 'id') });
+        }
+        /**
          * 新增数据(供内部或其他service类调用, controller不可直接使用)
          * @param {Array|Object} data - 新增数据
          * @param {Number} stageId - 期id

+ 21 - 0
app/service/sub_project.js

@@ -28,6 +28,9 @@ const pageShowConst = require('../const/sp_page_show').defaultSetting;
 const shenpiConst = require('../const/sp_shenpi');
 const defaultShenpi = shenpiConst.defaultInfo.shenpi;
 const arrayInfo = ['shenpi'];
+const ColSetConst = [
+    { key: 'cost_ledger', field: 'cost_ledger_col_set', defaultValue: { cur: 1, cur_excl_tax: 1, end: 1, end_excl_tax: 1} }
+];
 
 class DragTree {
     /**
@@ -758,6 +761,24 @@ module.exports = app => {
             return result.affectedRows === 1;
         }
 
+        getColSet(type) {
+            const colSetInfo = ColSetConst.find(x => { return x.key === type; });
+            if (!colSetInfo) return null;
+
+            const result = this.ctx.subProject[colSetInfo.field] ? JSON.parse(this.ctx.subProject[colSetInfo.field]) : {};
+            this.ctx.helper._.defaults(result, colSetInfo.defaultValue);
+            return result;
+        }
+        async updateColSet(type, colSet) {
+            const colSetInfo = ColSetConst.find(x => { return x.key === type; });
+            if (!colSetInfo) throw '未定义的列设置类型';
+
+            const updateData = { id: this.ctx.subProject.id };
+            updateData[colSetInfo.field] = JSON.stringify(colSet);
+            const result = await this.db.update(this.tableName, updateData);
+            return result.affectedRows === 1;
+        }
+
         async saveCommonJson(id, field, datas) {
             const subProject = await this.getDataById(id);
             subProject.common_json = subProject.common_json ? JSON.parse(subProject.common_json) : {};

+ 5 - 0
app/view/cost/analysis.ejs

@@ -60,6 +60,8 @@
                 <div class="tab-content">
                     <div id="search" class="tab-pane tab-select-show">
                     </div>
+                    <div id="fujian" class="tab-pane tab-select-show">
+                    </div>
                 </div>
             </div>
         </div>
@@ -69,6 +71,9 @@
                 <li class="nav-item">
                     <a class="nav-link" content="#search" href="javascript: void(0);">查找定位</a>
                 </li>
+                <li class="nav-item">
+                    <a class="nav-link" content="#fujian" href="javascript: void(0);">附件</a>
+                </li>
             </ul>
         </div>
     </div>

+ 1 - 0
app/view/cost/analysis_modal.ejs

@@ -1,5 +1,6 @@
 <% include ../shares/delete_hint_modal.ejs %>
 <% include ./audit_modal.ejs %>
+<% include ../shares/upload_att.ejs %>
 <div class="modal" id="import-pay" data-backdrop="static" aria-modal="true" role="dialog">
     <div class="modal-dialog" role="document">
         <div class="modal-content">

+ 23 - 11
app/view/cost/book_list.ejs

@@ -19,16 +19,24 @@
                 <table class="table table-bordered table-hover">
                     <thead>
                     <tr class="text-center">
-                        <th width="80px">期数</th>
-                        <th width="70px">报审月份</th>
-                        <th width="70px">关联成本</th>
-                        <th width="70px">创建人</th>
-                        <th width="180px">本期入账金额</th>
-                        <th width="180px">截止本期入账金额</th>
-                        <th width="180px">本期入账金额(不含税)</th>
-                        <th width="180px">截止本期入账金额(不含税)</th>
-                        <th>审批进度</th>
-                        <th width="100px">操作</th>
+                        <th width="80px" rowspan="2">期数</th>
+                        <th width="70px" rowspan="2">报审月份</th>
+                        <th width="70px" rowspan="2">关联成本</th>
+                        <th width="70px" rowspan="2">创建人</th>
+                        <th width="120px" colspan="4">本期</th>
+                        <th width="120px" colspan="4">截止本期</th>
+                        <th rowspan="2">审批进度</th>
+                        <th width="100px" rowspan="2">操作</th>
+                    </tr>
+                    <tr class="text-center">
+                        <th width="130px">应付金额</th>
+                        <th width="130px">实付金额</th>
+                        <th width="130px">入账金额</th>
+                        <th width="130px">入账金额(不含税)</th>
+                        <th width="130px">应付金额</th>
+                        <th width="130px">实付金额</th>
+                        <th width="130px">入账金额</th>
+                        <th width="130px">入账金额(不含税)</th>
                     </tr>
                     </thead>
                     <tbody>
@@ -40,9 +48,13 @@
                         <td class="text-center"><%- s.stage_date %></td>
                         <td class="text-center">第<%- s.rela_stage.sorder %>期</td>
                         <td class="text-center"><%- s.user_name %></td>
+                        <td class="text-right"><%- s.relaStage.stage_tp.yf_tp %></td>
+                        <td class="text-right"><%- s.relaStage.stage_tp.sf_tp %></td>
                         <td class="text-right"><%- s.stage_tp.in_tp %></td>
-                        <td class="text-right"><%- s.stage_end_tp.in_tp %></td>
                         <td class="text-right"><%- s.stage_tp.in_excl_tax_tp %></td>
+                        <td class="text-right"><%- s.relaStage.stage_end_tp.yf_tp %></td>
+                        <td class="text-right"><%- s.relaStage.stage_end_tp.sf_tp %></td>
+                        <td class="text-right"><%- s.stage_end_tp.in_tp %></td>
                         <td class="text-right"><%- s.stage_end_tp.in_excl_tax_tp %></td>
                         <td class="<%- auditConst.info[s.audit_status].class %>">
                             <% if (s.audit_status === auditConst.status.checked && s.final_auditor_str) { %>

+ 14 - 0
app/view/cost/gather.ejs

@@ -0,0 +1,14 @@
+<% 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>
+    <div class="content-wrap">
+        <div class="c-body">
+            <div class="sjs-height-0">
+            </div>
+        </div>
+    </div>
+</div>

+ 0 - 0
app/view/cost/gather_modal.ejs


+ 2 - 0
app/view/cost/ledger.ejs

@@ -30,6 +30,7 @@
                 <% } %>
             </div>
             <div class="ml-auto">
+                <a href="#cost-ledger-col" data-toggle="modal" data-target="#cost-ledger-col" class="btn btn-primary btn-sm">列设置</a>
             </div>
         </div>
     </div>
@@ -89,4 +90,5 @@
     const stageId = parseInt('<%- ctx.costStage.id %>');
     const stageDate = '<%- ctx.costStage.stage_date %>';
     const costStageComplete = <%- ctx.costStage.audit_status === auditConst.status.checked %>;
+    const colSet = JSON.parse('<%- JSON.stringify(colSet) %>');
 </script>

+ 46 - 10
app/view/cost/ledger_list.ejs

@@ -6,11 +6,12 @@
             <h2>
                 审批列表
             </h2>
-            <% if (ctx.permission.cost.ledger_add && (stages.length === 0 || stages[0].audit_status === auditConst.status.checked)) { %>
             <div class="ml-auto">
+                <a href="#cost-ledger-col" data-toggle="modal" data-target="#cost-ledger-col" class="btn btn-primary btn-sm">列设置</a>
+                <% if (ctx.permission.cost.ledger_add && (stages.length === 0 || stages[0].audit_status === auditConst.status.checked)) { %>
                 <a href="#add-qi" data-toggle="modal" data-target="#add-qi" class="btn btn-primary btn-sm">新建报审</a>
+                <% } %>
             </div>
-            <% } %>
         </div>
     </div>
     <div class="content-wrap">
@@ -21,20 +22,42 @@
                     <tr class="text-center">
                         <th width="80px" rowspan="2">期数</th>
                         <th width="70px" rowspan="2">报审月份</th>
+                        <% if (colSet.cur) { %>
                         <th colspan="4">本期金额</th>
+                        <% } %>
+                        <% if (colSet.cur_excl_tax) { %>
+                        <th colspan="2">本期金额(不含税)</th>
+                        <% } %>
+                        <% if (colSet.end) { %>
                         <th colspan="4">截止本期金额</th>
+                        <% } %>
+                        <% if (colSet.end_excl_tax) { %>
+                        <th colspan="2">截止本期金额(不含税)</th>
+                        <% } %>
                         <th rowspan="2">审批进度</th>
                         <th width="100px" rowspan="2">操作</th>
                     </tr>
                     <tr class="text-center">
-                        <th width="150px">付款</th>
-                        <th width="150px">扣款</th>
-                        <th width="150px">应付</th>
-                        <th width="150px">实付</th>
-                        <th width="150px">付款</th>
-                        <th width="150px">扣款</th>
-                        <th width="150px">应付</th>
-                        <th width="150px">实付</th>
+                        <% if (colSet.cur) { %>
+                        <th width="100px" name="tp-col">付款</th>
+                        <th width="100px" name="tp-col">扣款</th>
+                        <th width="100px" name="tp-col">应付</th>
+                        <th width="100px" name="tp-col">实付</th>
+                        <% } %>
+                        <% if (colSet.cur_excl_tax) { %>
+                        <th width="100px" name="tp-col">应付</th>
+                        <th width="100px" name="tp-col">实付</th>
+                        <% } %>
+                        <% if (colSet.end) { %>
+                        <th width="100px" name="tp-col">付款</th>
+                        <th width="100px" name="tp-col">扣款</th>
+                        <th width="100px" name="tp-col">应付</th>
+                        <th width="100px" name="tp-col">实付</th>
+                        <% } %>
+                        <% if (colSet.end_excl_tax) { %>
+                        <th width="100px" name="tp-col">应付</th>
+                        <th width="100px" name="tp-col">实付</th>
+                        <% } %>
                     </tr>
                     </thead>
                     <tbody>
@@ -44,14 +67,26 @@
                             <a href="/sp/<%- ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/ledger/<%- s.stage_order %>/stage" target="_blank">第 <%- s.stage_order %> 期</a>
                         </td>
                         <td class="text-center"><%- s.stage_date %></td>
+                        <% if (colSet.cur) { %>
                         <td class="text-right"><%- s.stage_tp.pay_tp %></td>
                         <td class="text-right"><%- s.stage_tp.cut_tp %></td>
                         <td class="text-right"><%- s.stage_tp.yf_tp %></td>
                         <td class="text-right"><%- s.stage_tp.sf_tp %></td>
+                        <% } %>
+                        <% if (colSet.cur_excl_tax) { %>
+                        <td class="text-right"><%- s.stage_tp.yf_excl_tax_tp %></td>
+                        <td class="text-right"><%- s.stage_tp.sf_excl_tax_tp %></td>
+                        <% } %>
+                        <% if (colSet.end) { %>
                         <td class="text-right"><%- s.stage_end_tp.pay_tp %></td>
                         <td class="text-right"><%- s.stage_end_tp.cut_tp %></td>
                         <td class="text-right"><%- s.stage_end_tp.yf_tp %></td>
                         <td class="text-right"><%- s.stage_end_tp.sf_tp %></td>
+                        <% } %>
+                        <% if (colSet.end_excl_tax) { %>
+                        <td class="text-right"><%- s.stage_end_tp.yf_excl_tax_tp %></td>
+                        <td class="text-right"><%- s.stage_end_tp.sf_excl_tax_tp %></td>
+                        <% } %>
                         <td class="<%- auditConst.info[s.audit_status].class %>">
                             <% if (s.audit_status === auditConst.status.checked && s.final_auditor_str) { %>
                             <a href="#sp-list" data-toggle="modal" data-target="#sp-list" stage-order="<%- s.stage_order %>"><%- s.final_auditor_str %></a>
@@ -89,4 +124,5 @@
     const stages = JSON.parse('<%- JSON.stringify(stages) %>');
     const auditType = JSON.parse('<%- JSON.stringify(auditType) %>');
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
+    if ($('[name="tp-col"]').length > 0) $('[name="tp-col"]').attr('width', (1200/$('[name="tp-col"]').length) + 'px')
 </script>

+ 45 - 0
app/view/cost/ledger_list_modal.ejs

@@ -49,6 +49,43 @@
         </div>
     </div>
 </div>
+<div class="modal" id="cost-ledger-col" data-backdrop="static" aria-modal="true" role="dialog">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="colSet" method="POST" onsubmit="return convertColSet();">
+            <div class="modal-header">
+                <h5 class="modal-title">列设置</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_cur" <% if (colSet.cur) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_cur">本期</label>
+                </div>
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_cur_excl_tax" <% if (colSet.cur_excl_tax) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_cur_excl_tax">本期(不含税)</label>
+                </div>
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_end" <% if (colSet.end) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_end">截止本期</label>
+                </div>
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_end_excl_tax" <% if (colSet.end_excl_tax) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_end_excl_tax">截止本期(不含税)</label>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                <input type="hidden" name="col_cur" value="<%- colSet.cur %>" />
+                <input type="hidden" name="col_cur_excl_tax" value="<%- colSet.cur_excl_tax %>" />
+                <input type="hidden" name="col_end" value="<%- colSet.end %>" />
+                <input type="hidden" name="col_end_excl_tax" value="<%- colSet.end_excl_tax %>" />
+                <input type="hidden" name="stage_type" value="<%- stage_type %>" />
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-sm btn-primary">确定</button>
+            </div>
+        </form>
+    </div>
+</div>
 <script>
     $('.datepicker-here').datepicker({
         autoClose: true,
@@ -65,4 +102,12 @@
             return false;
         }
     }
+    const convertColSet = function() {
+        const check = $('input[type=checkbox]', '#cost-ledger-col');
+        for (const c of check) {
+            const id = c.getAttribute('id');
+            $(`input[name=${id}]`).val(c.checked ? 1 : 0);
+        }
+        return true;
+    }
 </script>

+ 47 - 0
app/view/cost/ledger_modal.ejs

@@ -66,5 +66,52 @@
         </div>
     </div>
 </div>
+<div class="modal" id="cost-ledger-col" data-backdrop="static" aria-modal="true" role="dialog">
+    <div class="modal-dialog" role="document">
+        <form class="modal-content" action="/sp/<%- ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/colSet" method="POST" onsubmit="return convertColSet();">
+            <div class="modal-header">
+                <h5 class="modal-title">列设置</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_cur" <% if (colSet.cur) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_cur">本期</label>
+                </div>
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_cur_excl_tax" <% if (colSet.cur_excl_tax) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_cur_excl_tax">本期(不含税)</label>
+                </div>
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_end" <% if (colSet.end) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_end">截止本期</label>
+                </div>
+                <div class="form-group form-check mb-0">
+                    <input type="checkbox" class="form-check-input group-checkbox" id="col_end_excl_tax" <% if (colSet.end_excl_tax) { %> checked <%} %>>
+                    <label class="form-check-label" for="col_end_excl_tax">截止本期(不含税)</label>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                <input type="hidden" name="col_cur" value="<%- colSet.cur %>" />
+                <input type="hidden" name="col_cur_excl_tax" value="<%- colSet.cur_excl_tax %>" />
+                <input type="hidden" name="col_end" value="<%- colSet.end %>" />
+                <input type="hidden" name="col_end_excl_tax" value="<%- colSet.end_excl_tax %>" />
+                <input type="hidden" name="stage_type" value="<%- ctx.costStage.stage_type %>" />
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-sm btn-primary">确定</button>
+            </div>
+        </form>
+    </div>
+</div>
+<script>
+    const convertColSet = function() {
+        const check = $('input[type=checkbox]', '#cost-ledger-col');
+        for (const c of check) {
+            const id = c.getAttribute('id');
+            $(`input[name=${id}]`).val(c.checked ? 1 : 0);
+        }
+        return true;
+    }
+</script>
 <link href="/public/css/bootstrap/select2.min.css" rel="stylesheet" />
 <script src="/public/js/bootstrap/select2.min.js"></script>

+ 1 - 1
app/view/cost/list_menu_list.ejs

@@ -2,7 +2,7 @@
 <nav-menu title="成本报审" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/ledger" ml="3" active="<%= (ctx.url.indexOf('ledger') >= 0 ? 1 : -1) %>"></nav-menu>
 <nav-menu title="财务账面" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/book" ml="3" active="<%= (ctx.url.indexOf('book') >= 0 ? 1 : -1) %>"></nav-menu>
 <nav-menu title="成本分析" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/analysis" ml="3" active="<%= (ctx.url.indexOf('analysis') >= 0 ? 1 : -1) %>"></nav-menu>
-<!--<nav-menu title="汇总分析" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/gather" ml="3" active="<%= (ctx.url.indexOf('gather') >= 0 ? 1 : -1) %>"></nav-menu>-->
+<nav-menu title="汇总分析" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/gather" ml="3" active="<%= (ctx.url.indexOf('gather') >= 0 ? 1 : -1) %>"></nav-menu>
 <!--<nav-menu title="输出报表" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/report" ml="3" active="<%= (ctx.url.indexOf('report') >= 0 ? 1 : -1) %>"></nav-menu>-->
 <% if (ctx.session.sessionUser.is_admin) { %>
 <nav-menu title="审批流程" url="/sp/<%= ctx.subProject.id %>/cost/tender/<%- ctx.tender.id %>/flow" ml="3" active="<%= (ctx.url.indexOf('flow') >= 0 ? 1 : -1) %>"></nav-menu>

+ 1 - 1
config/config.default.js

@@ -276,6 +276,6 @@ module.exports = appInfo => {
         algorithm: 'aes-256-cbc',
     };
 
-    config.kkfileUrl = 'preview/onlinePreview?url=';
+    config.kkfileUrl = '/preview/onlinePreview?url=';
     return config;
 };

+ 21 - 0
config/web.js

@@ -2661,6 +2661,27 @@ const JsFiles = {
                 ],
                 mergeFile: 'cost_stage_analysis',
             },
+            cost_gather: {
+                files: [
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/math.min.js',
+                    '/public/js/component/menu.js',
+                    '/public/js/datepicker/datepicker.min.js',
+                    '/public/js/datepicker/datepicker.zh.js',
+                    '/public/js/moment/moment.min.js',
+                ],
+                mergeFiles: [
+                    '/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/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/cost_gather.js',
+                ],
+                mergeFile: 'cost_gather',
+            }
         },
     },
 };

+ 2 - 3
sql/update.sql

@@ -11,9 +11,8 @@
 -- 表结构
 ------------------------------------
 
-
-
-
+ALTER TABLE `zh_sub_project`
+ADD COLUMN `cost_ledger_col_set` json NULL COMMENT '成本报审-列设置' AFTER `cost_calc_template`;
 
 
 ------------------------------------

+ 1 - 1
sql/update20260403.sql

@@ -348,7 +348,7 @@ CREATE TABLE `zh_std_extra`  (
   `extra_pid` int(8) NOT NULL COMMENT '父节点id',
   `level` tinyint(2) NOT NULL DEFAULT 1 COMMENT '目录层级',
   `order` tinyint(5) NOT NULL,
-  `full_path` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+  `full_path` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
   `is_leaf` tinyint(1) NOT NULL,
   `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '分类名称',
   `code` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '编号',

+ 21 - 16
sql/update20250527.sql

@@ -182,7 +182,7 @@ CREATE TABLE `zh_cost_stage_detail`  (
   `stage_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '期id',
   `stage_order` int(11) NOT NULL COMMENT '期序号',
   `ledger_id` varchar(36) NOT NULL COMMENT '所属台账id(zh_stage_ledger.id)',
-  `cost_id` varchar(36) CHARACTER SET utf16le NOT NULL COMMENT '所属台账cost_id(不同期一致zh_stage_ledger.cost_id)',
+  `cost_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '所属台账cost_id(不同期一致zh_stage_ledger.cost_id)',
   `source_cid` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '导入的合同id',
   `d_order` int(11) NOT NULL COMMENT '排序',
   `code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '编号',
@@ -329,14 +329,14 @@ CREATE TABLE `zh_cost_stage_analysis`  (
   `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
   `calc_type` int(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '计算类型(收入1,支出2,其他0)',
   PRIMARY KEY (`id`)
-);
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
 CREATE TABLE `zh_cost_stage_analysis_detail`  (
   `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'uuid',
   `tender_id` int(11) NOT NULL COMMENT '标段id',
   `stage_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '期id',
   `ledger_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '所属台账id(zh_stage_ledger.id)',
-  `cost_id` varchar(36) CHARACTER SET utf16le COLLATE utf16le_general_ci NOT NULL COMMENT '所属台账cost_id(不同期一致zh_stage_ledger.cost_id)',
+  `cost_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '所属台账cost_id(不同期一致zh_stage_ledger.cost_id)',
   `source_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '导入的合同id/明细id',
   `d_order` int(11) NOT NULL COMMENT '排序',
   `code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '编号',
@@ -418,34 +418,34 @@ ALTER TABLE `calculation`.`zh_project`
 ADD COLUMN `calc_tmpl_set` json NULL COMMENT '计算模板配置' AFTER `common_json`;
 
 CREATE TABLE `zh_budget_ctrl`  (
-  `id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '自增id',
+  `id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '自增id',
   `bid` int(10) NOT NULL COMMENT '概算投资项目id',
   `tree_id` int(10) NOT NULL COMMENT '节点id',
   `tree_pid` int(10) NOT NULL COMMENT '父节点id',
   `level` tinyint(4) NOT NULL COMMENT '层级',
   `order` mediumint(4) NOT NULL DEFAULT 0 COMMENT '同级排序',
-  `full_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '层级定位辅助字段parent.full_path.ledger_id',
+  `full_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '层级定位辅助字段parent.full_path.ledger_id',
   `is_leaf` tinyint(1) NOT NULL COMMENT '是否叶子节点,界面显示辅助字段',
-  `code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '节点编号',
-  `b_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名称',
-  `unit` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '单位',
+  `code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '节点编号',
+  `b_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '名称',
+  `unit` varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '单位',
   `unit_price` decimal(24, 8) NOT NULL DEFAULT 0.00000000 COMMENT '单价',
   `quantity` decimal(24, 8) NOT NULL DEFAULT 0.00000000 COMMENT '数量',
   `total_price` decimal(24, 8) NULL DEFAULT 0.00000000 COMMENT '金额',
   `dgn_qty1` decimal(24, 8) NOT NULL DEFAULT 0.00000000 COMMENT '设计数量1',
   `dgn_qty2` decimal(24, 8) NOT NULL DEFAULT 0.00000000 COMMENT '设计数量2',
-  `drawing_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图册号',
-  `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注',
+  `drawing_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '图册号',
+  `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '备注',
   `node_type` int(4) UNSIGNED NULL DEFAULT 0 COMMENT '节点类别',
-  `source` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '添加源',
-  `remark` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注',
+  `source` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '添加源',
+  `remark` varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '备注',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_tender_id`(`bid`) USING BTREE,
   INDEX `idx_template_pid`(`tree_pid`) USING BTREE,
   INDEX `idx_level`(`level`) USING BTREE,
   INDEX `idx_full_path`(`bid`, `full_path`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '控制目标数据' ROW_FORMAT = Dynamic;
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '控制目标数据' ROW_FORMAT = Dynamic;
 
 ALTER TABLE `zh_budget_final`
 ADD COLUMN `ctrl_dgn_qty1` decimal(24, 8) NOT NULL DEFAULT 0.00000000 COMMENT '控制目标-设计数量1' AFTER `zb_tp`,
@@ -459,7 +459,7 @@ ADD COLUMN `ctrl_chapter_id` varchar(255) CHARACTER SET ascii COLLATE ascii_gene
 ADD COLUMN `ctrl_template_id` varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '' COMMENT '控制目标-新建模板-id列表(\',\'分隔)' AFTER `ctrl_chapter_id`,
 ADD COLUMN `ctrl_bills_id` varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '' COMMENT '控制目标-工程量清单-id列表(\',\'分隔)' AFTER `ctrl_template_id`;
 
-ALTER TABLE `zh_sub_project` ADD `shenpi` VARCHAR(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '审批流程设置' AFTER `payment_setting`;
+ALTER TABLE `zh_sub_project` ADD `shenpi` VARCHAR(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '审批流程设置' AFTER `payment_setting`;
 
 ALTER TABLE `zh_shenpi_group`
 ADD COLUMN `spid` varchar(255) NULL DEFAULT NULL COMMENT '项目id' AFTER `id`;
@@ -578,10 +578,15 @@ CREATE TABLE `zh_contract_supplement_attachment` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='合同补充附件表';
 
 ALTER TABLE `zh_sub_project`
-MODIFY COLUMN `fun_rela` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '功能设置(json.stringify)' AFTER `page_show`;
+MODIFY COLUMN `fun_rela` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '功能设置(json.stringify)' AFTER `page_show`;
 
 ALTER TABLE `zh_calc_tmpl`
 ADD COLUMN `sub_spread_cache` json NULL COMMENT '子数据spreadjs表头设置缓存' AFTER `spread_cache`;
 ------------------------------------
 -- 表数据
 ------------------------------------
+
+ALTER TABLE `zh_cost_stage`
+	DEFAULT CHARACTER SET=utf8,
+	COLLATE=utf8_unicode_ci
+;