Selaa lähdekoodia

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

TonyKang 4 vuotta sitten
vanhempi
commit
980f2e1ac1

+ 11 - 0
Dockerfile

@@ -0,0 +1,11 @@
+FROM node:12
+
+WORKDIR /home
+
+COPY . .
+
+RUN npm install --registery=https://registery.npm.taobao.org
+
+EXPOSE 7005
+
+CMD ["npm", "run", "dev-docker"]

+ 2 - 1
app/base/base_bills_service.js

@@ -470,8 +470,9 @@ class BaseBillsSerivce extends TreeService {
 
     // 统计方法
     async addUp(condition) {
+        if (!condition.tender_id) throw new TypeError('statistical lacks necessary parameter');
         const sql = 'SELECT Sum(total_price) As total_price, Sum(deal_tp) As deal_tp' +
-            '  FROM ' + this.tableName + this.ctx.helper.whereSql(condition);
+            '  FROM ' + this.departTableName(condition.tender_id) + this.ctx.helper.whereSql(condition);
         const result = await this.db.queryOne(sql);
         return result;
     }

+ 9 - 2
app/base/base_service.js

@@ -47,8 +47,15 @@ class BaseService extends Service {
     get tableName() {
         if (this.depart <= 0) return this._table;
 
-        if (!this.ctx.query_tender && !this.ctx.tender) throw '获取数据表错误';
-        return this._table + '_' + ((this.ctx.query_tender ? this.ctx.query_tender.id : this.ctx.tender.id) % this.depart);
+        if (!this.ctx.tender) throw  new TypeError('tableName error: Without Tender');
+        return this._table + '_' + (this.ctx.tender.id % this.depart);
+    }
+
+    departTableName(key) {
+        if (this.depart <= 0) return this._table;
+
+        if (!key) throw  new TypeError('tableName error: Without DepartKey');
+        return this._table + '_' + (key % this.depart);
     }
 
     /**

+ 2 - 2
app/base/base_tree_service.js

@@ -74,10 +74,10 @@ class TreeService extends Service {
                 operate: '<=',
                 value: level,
             });
-            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
+            const [sql, sqlParam] = this.sqlBuilder.build(this.departTableName(mid));
             return await this.db.query(sql, sqlParam);
         } else {
-            return await this.db.select(this.tableName, {
+            return await this.db.select(this.departTableName(mid), {
                 where: this.getCondition({mid: mid})
             });
         }

+ 70 - 2
app/controller/schedule_controller.js

@@ -29,7 +29,11 @@ module.exports = app => {
 
         async index(ctx) {
             try {
+                const scheduleInfo = await ctx.service.schedule.getDataByCondition({ tid: ctx.tender.id });
+                const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: ctx.tender.id }, orders: [['yearmonth', 'asc']] });
                 const renderData = {
+                    scheduleInfo,
+                    scheduleMonth,
                     tender: ctx.tender.data,
                     tenderMenu: this.menu.tenderMenu,
                     planMonth: await this._getLastPlanMonth(ctx),
@@ -105,8 +109,9 @@ module.exports = app => {
                 }), 'yearmonth');
                 yearSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, yearConllection);
                 // 获取本年完成计量数据
+                const curStage = _.find(stageOrderList, { order: curScheduleStage.order });
                 const stageList = _.filter(stageOrderList, function(item) {
-                    return item.s_time.indexOf(curScheduleStage.yearmonth.split('-')[0]) !== -1;
+                    return item.s_time.indexOf(curStage.s_time.split('-')[0]) !== -1;
                 });
                 const stageIdList = _.map(_.filter(stageList, function(item) {
                     return _.find(newSS, { order: item.order });
@@ -137,12 +142,16 @@ module.exports = app => {
             const tender = ctx.tender;
             const schedule = await ctx.service.schedule.getDataByCondition({ tid: tender.id });
             const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] });
+            const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: tender.id }, orders: [['order', 'desc']] });
+            const curScheduleStage = scheduleStage.length > 0 ? _.maxBy(scheduleStage, 'order') : null;
             const renderData = {
                 tender: tender.data,
                 tenderInfo: tender.info,
                 schedule,
                 scheduleMonth,
                 measureType,
+                scheduleStage,
+                curScheduleStage,
                 scheduleLedgerList: await this._getSelectedLedgerList(ctx),
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.stageGcl),
             };
@@ -150,7 +159,66 @@ module.exports = app => {
         }
 
         /**
-         * 获取部位明细数据(Ajax)
+         * 获取金额模式下台账数据(Ajax)
+         *
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async loadTpLedgerData(ctx) {
+            try {
+                const tender = ctx.tender;
+                // const ledgerData = await ctx.controller.stage._getStageLedgerData(ctx);
+                // console.log(ledgerData);
+                const stageOrderList = await ctx.service.stage.getAllDataByCondition({ columns: ['id', 's_time', 'order'], where: { tid: tender.id } });
+                const scheduleStage = await ctx.service.scheduleStage.getAllDataByCondition({ where: { tid: tender.id }, orders: [['order', 'desc']] });
+                const curScheduleStage = _.find(scheduleStage, { order: parseInt(ctx.params.order) });
+                let slmList = [];
+                let nextSlmList = [];
+                let endSlmList = [];
+                let yearSlmList = [];
+                let curYearStageData = [];
+                if (curScheduleStage) {
+                    const newSS = _.sortBy(scheduleStage, 'yearmonth');
+                    const nowScheduleStage = _.findIndex(newSS, { yearmonth: curScheduleStage.yearmonth });
+                    slmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: curScheduleStage.yearmonth } });
+                    const nextScheduleStage = nowScheduleStage >= 0 && nowScheduleStage + 1 <= newSS.length - 1 ? newSS[nowScheduleStage + 1] : null;
+                    if (nextScheduleStage) nextSlmList = await ctx.service.scheduleLedgerMonth.getAllDataByCondition({ where: { tid: tender.id, yearmonth: nextScheduleStage.yearmonth } });
+                    if (nowScheduleStage === 0) {
+                        endSlmList = slmList;
+                    } else if (nowScheduleStage > 0) {
+                        const endYearmonthCollection = _.map(_.take(newSS, nowScheduleStage + 1), 'yearmonth');
+                        endSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, endYearmonthCollection);
+                    }
+                    const yearConllection = _.map(_.filter(newSS, function(item) {
+                        return item.yearmonth.indexOf(curScheduleStage.yearmonth.split('-')[0]) !== -1;
+                    }), 'yearmonth');
+                    yearSlmList = await ctx.service.scheduleLedgerMonth.getConllectionList(tender.id, yearConllection);
+                    // 获取本年完成计量数据
+                    const curStage = _.find(stageOrderList, { order: curScheduleStage.order });
+                    const stageList = _.filter(stageOrderList, function(item) {
+                        return item.s_time.indexOf(curStage.s_time.split('-')[0]) !== -1;
+                    });
+                    const stageIdList = _.map(_.filter(stageList, function(item) {
+                        return _.find(newSS, { order: item.order });
+                    }), 'id');
+                    curYearStageData = await ctx.service.stageBills.getStagesData(tender.id, stageIdList.join(','));
+                }
+                ctx.body = { err: 0, msg: '', data: {
+                    // ledgerData,
+                    slmList,
+                    nextSlmList,
+                    endSlmList,
+                    yearSlmList,
+                    curYearStageData,
+                } };
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: [] };
+            }
+        }
+
+        /**
+         * 获取台账数据(Ajax)
          *
          * @param ctx
          * @return {Promise<void>}

+ 0 - 2
app/controller/spss_controller.js

@@ -31,12 +31,10 @@ module.exports = app => {
             if (!tender || tender.project_id !== this.ctx.session.sessionProject.id) {
                 throw '不存在该标段';
             }
-            this.ctx.query_tender = tender;
             const bills = await this.ctx.service.ledger.getData(tid);
             const pos = tender.measure_type === measureType.tz.value || includePos
                 ? await this.ctx.service.pos.getPosData({tid: tid})
                 : [];
-            this.ctx.query_tender = null;
 
             return { id: tid, name: tender.name, bills: bills, pos: pos };
         }

+ 1 - 1
app/controller/stage_controller.js

@@ -1513,7 +1513,7 @@ module.exports = app => {
             };
             let stream;
             try {
-                this._checkStageCanModifyRe(ctx);
+                // this._checkStageCanModifyRe(ctx);
                 stream = await ctx.getFileStream({ requireFile: false });
                 let fileData = {};
                 if (stream.filename !== undefined) {

+ 10 - 5
app/controller/stage_extra_controller.js

@@ -203,13 +203,13 @@ module.exports = app => {
                 const parts = ctx.multipart({ autoFields: true });
                 let index = 0;
                 const create_time = Date.parse(new Date()) / 1000;
-                let bonus;
-                while ((stream = await parts()) !== undefined) {
+                let stream = await parts();
+                const bonus = await ctx.service.stageBonus.getStageDataById(parts.field.bonus_id);
+                if (!bonus || bonus.sid !== ctx.stage.id) throw '该奖罚金,当前不允许上传附件';
+                while (stream !== undefined) {
                     if (!stream.filename) {
                         throw '未发现上传文件!';
                     }
-                    if (!bonus) bonus = await ctx.service.stageBonus.getStageDataById(parts.field.bonus_id);
-                    if (!bonus || bonus.sid !== ctx.stage.id) throw '该奖罚金,当前不允许上传附件';
 
                     const fileInfo = path.parse(stream.filename);
                     const dirName = 'app/public/upload/extra/' + moment().format('YYYYMMDD');
@@ -229,6 +229,11 @@ module.exports = app => {
                         in_time: moment(create_time * 1000).format('YYYY-MM-DD'),
                     });
                     ++index;
+                    if (Array.isArray(parts.field.size) && index < parts.field.size.length) {
+                        stream = await parts();
+                    } else {
+                        stream = undefined;
+                    }
                 }
                 const result = await ctx.service.stageBonus.updateDatas({
                     update: [
@@ -315,4 +320,4 @@ module.exports = app => {
     }
 
     return StageExtraController;
-};
+};

+ 1 - 0
app/controller/standard_lib_controller.js

@@ -34,6 +34,7 @@ module.exports = app => {
                         throw '查询的标准清单不存在';
                 }
             } catch (error) {
+                this.log(error);
                 responseData.err = 1;
                 responseData.msg = error;
             }

+ 5 - 2
app/controller/tender_controller.js

@@ -123,7 +123,6 @@ module.exports = app => {
                 const tenderList = await this.ctx.service.tender.getList('', userPermission);
 
                 for (const t of tenderList) {
-                    this.ctx.query_tender = t;
                     if (t.user_id === this.ctx.session.sessionUser.accountId && (
                         t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck)) {
                         const sum = await this.ctx.service.ledger.addUp({ tender_id: t.id/* , is_leaf: true*/ });
@@ -148,7 +147,6 @@ module.exports = app => {
                         await this._getLedgerAuditInfo(t);
                     }
                 }
-                this.ctx.query_tender = null;
                 const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id);
                 const renderData = {
@@ -166,12 +164,14 @@ module.exports = app => {
                 };
                 await this.layout(view, renderData, modal);
             } catch (err) {
+                console.log(err);
                 this.log(err);
                 this.ctx.redirect('/dashboard');
             }
         }
 
         async _list(view, renderData, modal = '', list_status = '') {
+            console.log(1);
             try {
                 renderData.tenderList = await this.ctx.service.tender.getList(list_status, renderData.userPermission);
 
@@ -231,6 +231,7 @@ module.exports = app => {
          * @return {void}
          */
         async listInfo(ctx) {
+            console.log('listInfo');
             this.jsFiles = this.app.jsFiles.tender.info;
             await this._listDetail('tender/info.ejs', 'tender/modal.ejs');
         }
@@ -242,6 +243,7 @@ module.exports = app => {
          * @return {Promise<void>}
          */
         async listProgress(ctx) {
+            console.log('listProgress');
             this.jsFiles = this.app.jsFiles.tender.progress;
             await this._listDetail('tender/progress.ejs', 'tender/modal.ejs');
         }
@@ -253,6 +255,7 @@ module.exports = app => {
          * @return {Promise<void>}
          */
         async listManage(ctx) {
+            console.log('listManager');
             this.jsFiles = this.app.jsFiles.tender.manage;
             // 先判断权限
             // 获取用户新建标段权利

+ 0 - 2
app/controller/wap_controller.js

@@ -147,7 +147,6 @@ module.exports = app => {
 
                 const tenderList = await this.ctx.service.tender.getList('', userPermission);
                 for (const t of tenderList) {
-                    this.ctx.query_tender = t;
                     if (t.user_id === this.ctx.session.sessionUser.accountId && (
                         t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck)) {
                         const sum = await this.ctx.service.ledger.addUp({tender_id: t.id/*, is_leaf: true*/});
@@ -166,7 +165,6 @@ module.exports = app => {
                         await this.ctx.service.stage.checkStageGatherData(t.lastStage);
                     }
                 }
-                this.ctx.query_tender = null;
                 const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 const valuations = await this.ctx.service.valuation.getProjectValidValuation(this.ctx.session.sessionProject.id);
                 const renderData = {

+ 3 - 48
app/lib/rpt_data_analysis.js

@@ -49,14 +49,13 @@ const valueCheck = {
         }
     },
     _checkString(ctx, value, condition) {
-        if (!value) return false;
         switch (condition.operate) {
             case '=':
                 return value === condition.value;
             case 'part':
-                return !ctx.helper._.isNil(value) ? value.indexOf(condition.value) >= 0 : false;
+                return value ? value.indexOf(condition.value) >= 0 : false;
             case 'enum':
-                return (!ctx.helper._.isNil(value) && condition.value instanceof Array) ? condition.value.indexOf(value) >= 0 : false;
+                return (value && condition.value instanceof Array) ? condition.value.indexOf(value) >= 0 : false;
             default:
                 return true;
         }
@@ -662,7 +661,6 @@ const gatherChapter = {
             return (x.visible !== undefined && x.visible !== null) ? x.visible : true;
 
         });
-        console.log(data[fieldsKey[0].table])
     },
 };
 const join = {
@@ -785,52 +783,10 @@ const filter = {
         str: '_checkString',
         num: '_checkNumber',
     },
-    _checkBoolean(ctx, value, condition) {
-        switch (condition.value) {
-            case 'true':
-                return !!value;
-            case 'false':
-                return !value;
-            default:
-                return true;
-        }
-    },
-    _checkNumber(ctx, value, condition) {
-        // if (ctx.helper._.isNil(value)) value = 0;
-        switch (condition.operate) {
-            case 'non-zero':
-                return !ctx.helper.checkZero(value);
-            case '=':
-                return !ctx.helper._.isNil(value) ? value === condition.value : false;
-            case '>':
-                return !ctx.helper._.isNil(value) ? value > condition.value : false;
-            case '<':
-                return !ctx.helper._.isNil(value) ? value < condition.value : false;
-            case '>=':
-                return !ctx.helper._.isNil(value) ? value >= condition.value : false;
-            case '<=':
-                return !ctx.helper._.isNil(value) ? value <= condition.value : false;
-            default:
-                return true;
-        }
-    },
-    _checkString(ctx, value, condition) {
-        switch (condition.operate) {
-            case '=':
-                return value === condition.value;
-            case 'part':
-                return !ctx.helper._.isNil(value) ? value.indexOf(condition.value) >= 0 : false;
-            case 'enum':
-                return (!ctx.helper._.isNil(value) && condition.value instanceof Array) ? condition.value.indexOf(value) >= 0 : false;
-            default:
-                return true;
-        }
-    },
     fun(ctx, data, fields, options) {
         if (!options || !options.table || !options.condition) return;
 
-        const fData = data[options.table],
-            self = this;
+        const fData = data[options.table];
         if (!fData) return;
 
         valueCheck.loadTypeFun(options.condition);
@@ -848,7 +804,6 @@ const filter = {
                 return result;
             }
             return true;
-
         });
     },
 };

+ 10 - 0
app/public/js/change_information_set.js

@@ -731,6 +731,12 @@ $(document).ready(() => {
             toastr.error('工程名称不能为空!');
             return;
         }
+        // 换行更改并提交
+        changeInfo.content = changeInfo.content.replace(/<br><br>/g, '\r\n');
+        changeInfo.basis = changeInfo.basis.replace(/<br><br>/g, '\r\n');
+        changeInfo.expr = changeInfo.expr.replace(/<br><br>/g, '\r\n');
+        changeInfo.memo = changeInfo.memo.replace(/<br><br>/g, '\r\n');
+        // 后改为br
         // 更新至服务器
         postData(window.location.pathname + '/save', { type:'info', updateData: changeInfo }, function (result) {
             $('.reduction-code').attr('data-code', $('input[name="code"]').val());
@@ -738,6 +744,10 @@ $(document).ready(() => {
             $('#show-save-btn').hide();
             $('#sp-btn').show();
             $('.title-main').removeClass('bg-warning');
+            changeInfo.content = changeInfo.content.replace(/[\r\n]/g, '<br>');
+            changeInfo.basis = changeInfo.basis.replace(/[\r\n]/g, '<br>');
+            changeInfo.expr = changeInfo.expr.replace(/[\r\n]/g, '<br>');
+            changeInfo.memo = changeInfo.memo.replace(/[\r\n]/g, '<br>');
             back_changeInfo = Object.assign({}, changeInfo);
         });
         return false;

+ 15 - 1
app/public/js/schedule_plan.js

@@ -26,7 +26,7 @@ $(function () {
         // markFoldKey: 'bills-fold',
         // markFoldSubKey: window.location.pathname.split('/')[2],
     };
-    const ledgerTree = createNewPathTree('filter', treeSetting);
+
 
     const static_cols = [
         {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
@@ -51,6 +51,7 @@ $(function () {
         }
     };
     const monthsCols = [];
+    const calcCols = [];
     if(scheduleMonth.length > 0) {
         for (const sm of scheduleMonth) {
             const readOnly = sm.stage_used !== 0;
@@ -59,8 +60,12 @@ $(function () {
             const cols2 = {title: '|计划金额(万元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_tp', hAlign: 2, width: 90, type: 'Number', readOnly: readOnly ? readOnly : 'readOnly.tp'};
             monthsCols.push(cols);
             monthsCols.push(cols2);
+            calcCols.push(sm.yearmonth+'_gcl');
+            calcCols.push(sm.yearmonth+'_tp');
         }
     }
+    treeSetting.calcFields = calcCols;
+    const ledgerTree = createNewPathTree('filter', treeSetting);
     const spreadHeaderCols = static_cols.concat(monthsCols);
     ledgerSpreadSetting.cols = spreadHeaderCols;
 
@@ -135,6 +140,7 @@ $(function () {
         }
         console.log(ledgerTree);
         ledgerTree.sortTreeNode(true);
+        treeCalc.calculateAll(ledgerTree);
         // console.log(ledgerTree);
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
     }, null, true);
@@ -242,9 +248,13 @@ $(function () {
                     } else {
                         select[yearmonth + '_tp'] = plan_tp;
                     }
+                    const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 },function () {
                     select[col.field] = orgValue;
+                    const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 })
             }
@@ -314,9 +324,13 @@ $(function () {
                 } else {
                     select[yearmonth + '_tp'] = plan_tp;
                 }
+                const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
             },function () {
                 select[col.field] = orgValue;
+                const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
             })
         },

+ 225 - 4
app/public/js/schedule_stage_gcl.js

@@ -26,7 +26,7 @@ $(function () {
         // markFoldKey: 'bills-fold',
         // markFoldSubKey: window.location.pathname.split('/')[2],
     };
-    const ledgerTree = createNewPathTree('filter', treeSetting);
+
 
     const static_cols = [
         {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
@@ -51,6 +51,7 @@ $(function () {
         }
     };
     const monthsCols = [];
+    const calcCols = [];
     if(scheduleMonth.length > 0) {
         for (const sm of scheduleMonth) {
             if (sm.stage_gcl_used === 1) {
@@ -63,9 +64,15 @@ $(function () {
                 monthsCols.push(cols2);
                 monthsCols.push(cols3);
                 monthsCols.push(cols4);
+                calcCols.push(sm.yearmonth + '_plan_gcl');
+                calcCols.push(sm.yearmonth + '_plan_tp');
+                calcCols.push(sm.yearmonth + '_sj_gcl');
+                calcCols.push(sm.yearmonth + '_sj_tp');
             }
         }
     }
+    treeSetting.calcFields = calcCols;
+    const ledgerTree = createNewPathTree('filter', treeSetting);
     const spreadHeaderCols = static_cols.concat(monthsCols);
     ledgerSpreadSetting.cols = spreadHeaderCols;
 
@@ -133,6 +140,7 @@ $(function () {
         }
         console.log(ledgerTree);
         ledgerTree.sortTreeNode(true);
+        treeCalc.calculateAll(ledgerTree);
         // console.log(ledgerTree);
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
     }, null, true);
@@ -222,9 +230,13 @@ $(function () {
                 console.log(updateData);
                 postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
                     select[yearmonth + '_sj_tp'] = sj_tp;
+                    const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 },function () {
                     select[col.field] = orgValue;
+                    const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                    SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 })
             }
@@ -277,9 +289,13 @@ $(function () {
             console.log(updateData);
             postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
                 select[yearmonth + '_sj_tp'] = sj_tp;
+                const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
             },function () {
                 select[col.field] = orgValue;
+                const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
+                SpreadJsObj.reLoadNodesData(info.sheet, nodes);
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
             })
         },
@@ -289,6 +305,161 @@ $(function () {
     SpreadJsObj.addDeleteBind(ledgerSpread, ledgerSpreadObj.deletePress);
     ledgerSpread.bind(spreadNS.Events.ClipboardPasted, ledgerSpreadObj.clipboardPasted);
 
+
+    // 下方金额模式的sjs
+    const huizongSpread = SpreadJsObj.createNewSpread($('#huizong-spread')[0]);
+    const huizongTreeSetting = {
+        id: 'ledger_id',
+        pid: 'ledger_pid',
+        order: 'order',
+        level: 'level',
+        rootId: -1,
+        fullPath: 'full_path',
+        calcFields: ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp'],
+    };
+
+    const huizong_static_cols = [
+        {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
+        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},
+        {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
+        {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+        {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '自开工至本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'end_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '截止本月完成计量|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '本年计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'year_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'year_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '本年累计完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'year_contract_qty', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'year_gather_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '本月计划完成|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '下月计划|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'next_plan_gcl', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'next_plan_tp', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+    ];
+
+    const huizongSpreadSetting = {
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        // readOnly: true,
+        localCache: {
+            key: 'ledger-bills',
+            colWidth: true,
+        }
+    };
+    huizongSpreadSetting.cols = huizong_static_cols;
+
+    sjsSettingObj.setFxTreeStyle(huizongSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(huizongSpreadSetting);
+    SpreadJsObj.initSheet(huizongSpread.getActiveSheet(), huizongSpreadSetting);
+    SpreadJsObj.selChangedRefreshBackColor(huizongSpread.getActiveSheet());
+
+    const huizongObj = {
+        setSjs: function (order) {
+            postData('/tender/' + getTenderId() + '/measure/stage/' + order + '/load', { filter: 'ledger' }, function (data) {
+                postData('/tender/' + getTenderId() + '/schedule/stage/' + order + '/load', {}, function (data2) {
+                    const calcList = ['year_contract_qty', 'year_gather_tp',
+                        'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+                        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+                    const showList = ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp',
+                        'year_contract_qty', 'year_gather_tp',
+                        'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
+                        'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
+                        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+                    const baseLedgerTreeSetting = {
+                        id: 'ledger_id',
+                        pid: 'ledger_pid',
+                        order: 'order',
+                        level: 'level',
+                        rootId: -1,
+                        fullPath: 'full_path',
+                        calcFields: calcList,
+                    };
+                    baseLedgerTreeSetting.updateFields = ['year_contract_qty', 'year_gather_tp', 'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr'];
+                    baseLedgerTreeSetting.calcFun = function (node) {
+                        if (!node.children || node.children.length === 0) {
+                            node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
+                            node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+                            node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
+                            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+                            node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
+                        }
+                        node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
+                        node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
+                        node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
+                        node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+                        node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
+                        node.end_final_tp = ZhCalc.add(node.end_qc_tp, node.total_price);
+                        if (!node.children || node.children.length === 0) {
+                            if (node.end_contract_qty) {
+                                node.end_correct_tp = ZhCalc.add(node.end_qc_tp, ZhCalc.mul(node.end_contract_qty, node.unit_price, tenderInfo.decimal.tp));
+                            } else {
+                                node.end_correct_tp = node.end_gather_tp;
+                            }
+                        }
+                        node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_tp), 100, 2);
+                        node.end_correct_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_tp), 100, 2);
+                        node.final_dgn_price = ZhCalc.round(ZhCalc.div(node.end_gather_tp, ZhCalc.add(node.deal_dgn_qty1, node.c_dgn_qty1)), tenderInfo.decimal.up);
+                        node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
+                    };
+                    const baseLedgerTree = createNewPathTree('base', baseLedgerTreeSetting);
+                    const newLedgerList = setTpMonthToLedger(data.ledgerData, data2.slmList, data2.nextSlmList, data2.endSlmList, data2.yearSlmList, data2.curYearStageData);
+                    baseLedgerTree.loadDatas(newLedgerList);
+                    treeCalc.calculateAll(baseLedgerTree);
+                    const huizongTree = createNewPathTree('filter', huizongTreeSetting);
+                    for (const d of baseLedgerTree.nodes) {
+                        if (!d.b_code) {
+                            const one = _.find(selectedLedgerList, function (item) {
+                                return item === d.ledger_id;
+                            });
+                            if (one) {
+                                huizongTree.addData(d, showList);
+                            }
+                        }
+                    }
+                    huizongTree.sortTreeNode(true);
+                    treeCalc.calculateAll(huizongTree);
+                    console.log(huizongTree);
+                    SpreadJsObj.loadSheetData(huizongSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, huizongTree);
+                }, null, true);
+            }, null, true);
+        },
+        dropDownHtml: function (order) {
+            let html = '';
+            for (const ss of scheduleStage) {
+                if (ss.order !== order) {
+                    html += '<a class="dropdown-item change-tp" data-order="'+ ss.order +'" href="javascript:void(0);">'+ ss.yearmonth.split('-')[0] + '年' + parseInt(ss.yearmonth.split('-')[1]) +'月(第'+ ss.order +'期)</a>';
+                } else {
+                    $('#dropdownMenuButton').text(ss.yearmonth.split('-')[0] + '年' + parseInt(ss.yearmonth.split('-')[1]) +'月(第'+ ss.order +'期)');
+                }
+            }
+            $('.dropdown-menu').html(html);
+        }
+    };
+
+    if (curScheduleStage && curScheduleStage.order) {
+        let order = parseInt(localStorage.getItem('tender_' + getTenderId() + '_schedule_tp_sjs') ? localStorage.getItem('tender_' + getTenderId() + '_schedule_tp_sjs') : curScheduleStage.order);
+        const ssinfo = _.find(scheduleStage, { order });
+        if (!ssinfo) {
+            order = curScheduleStage.order;
+        }
+        huizongObj.dropDownHtml(order);
+        huizongObj.setSjs(order);
+    }
+
+    // 汇总切换
+    $('body').on('click', '.change-tp', function () {
+        const order = parseInt($(this).data('order'));
+        huizongObj.dropDownHtml(order);
+        huizongObj.setSjs(order);
+        localStorage.setItem('tender_' + getTenderId() + '_schedule_tp_sjs', order);
+    });
+
     // 月份添加
     $('#add-month').click(function () {
         const id = parseInt($('#month-select').val());
@@ -354,8 +525,9 @@ $(function () {
                 $('.panel-title').removeClass('fluid');
                 $('#sub-menu').addClass('panel-sidebar');
             }
-            ledgerSpread.refresh();
             autoFlashHeight();
+            ledgerSpread.refresh();
+            huizongSpread.refresh();
         }
     });
 
@@ -364,8 +536,9 @@ $(function () {
         callback: function () {
             ledgerSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-            $(".tab-content").height(bcontent-30);
-            // posSpread.refresh();
+            $(".sp-wrap").height(bcontent-30);
+            huizongSpread.refresh();
+            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
         }
     });
 });
@@ -396,6 +569,54 @@ function setMonthToLedger(ledgerList, slm) {
     }
     return ledgerList;
 }
+function setTpMonthToLedger(ledgerList, slm, nextSlm, endSlm, yearSlm, yearLedgerData) {
+    if (slm.length > 0) {
+        for(const s of slm) {
+            const index = _.findIndex(ledgerList, { 'ledger_id': s.lid });
+            if (index && index !== -1) {
+                ledgerList[index].plan_tp = s.plan_tp;
+                ledgerList[index].plan_gcl = s.plan_gcl;
+            }
+        }
+    }
+    if (nextSlm.length > 0) {
+        for (const ns of nextSlm) {
+            const index = _.findIndex(ledgerList, {'ledger_id': ns.lid});
+            if (index && index !== -1) {
+                ledgerList[index].next_plan_tp = ns.plan_tp;
+                ledgerList[index].next_plan_gcl = ns.plan_gcl;
+            }
+        }
+    }
+    if (endSlm.length > 0) {
+        for (const es of endSlm) {
+            const index = _.findIndex(ledgerList, {'ledger_id': es.lid});
+            if (index && index !== -1) {
+                ledgerList[index].end_plan_tp = es.plan_tp;
+                ledgerList[index].end_plan_gcl = es.plan_gcl;
+            }
+        }
+    }
+    if (yearSlm.length > 0) {
+        for (const ys of yearSlm) {
+            const index = _.findIndex(ledgerList, {'ledger_id': ys.lid});
+            if (index && index !== -1) {
+                ledgerList[index].year_plan_tp = ys.plan_tp;
+                ledgerList[index].year_plan_gcl = ys.plan_gcl;
+            }
+        }
+    }
+    if (yearLedgerData.length > 0) {
+        for (const yl of yearLedgerData) {
+            const index = _.findIndex(ledgerList, {'id': yl.lid});
+            if (index && index !== -1) {
+                ledgerList[index].year_contract_qty = ZhCalc.add(yl.contract_qty, yl.qc_qty);
+                ledgerList[index].year_gather_tp = ZhCalc.add(yl.contract_tp, yl.qc_tp);
+            }
+        }
+    }
+    return ledgerList;
+}
 const is_numeric = (value) => {
     if (typeof(value) === 'object') {
         return false;

+ 0 - 70
app/public/js/schedule_stage_tp.js

@@ -135,58 +135,6 @@ $(function () {
         }, null, true);
     }
 
-    const ledgerSpreadObj = {
-        refreshTree: function (sheet, data) {
-            SpreadJsObj.massOperationSheet(sheet, function () {
-                const tree = sheet.zh_tree;
-                // 处理删除
-                if (data.delete) {
-                    data.delete.sort(function (x, y) {
-                        return y.deleteIndex - x.deleteIndex;
-                    });
-                    for (const d of data.delete) {
-                        sheet.deleteRows(d.deleteIndex, 1);
-                    }
-                }
-                // 处理新增
-                if (data.create) {
-                    const newNodes = data.create;
-                    if (newNodes) {
-                        newNodes.sort(function (a, b) {
-                            return a.index - b.index;
-                        });
-
-                        for (const node of newNodes) {
-                            sheet.addRows(node.index, 1);
-                            SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(node), 1);
-                        }
-                    }
-                }
-                // 处理更新
-                if (data.update) {
-                    const rows = [];
-                    for (const u of data.update) {
-                        rows.push(tree.nodes.indexOf(u));
-                    }
-                    SpreadJsObj.reLoadRowsData(sheet, rows);
-                }
-                // 处理展开
-                if (data.expand) {
-                    const expanded = [];
-                    for (const e of data.expand) {
-                        if (expanded.indexOf(e) === -1) {
-                            const posterity = tree.getPosterity(e);
-                            for (const p of posterity) {
-                                sheet.setRowVisible(tree.nodes.indexOf(p), p.visible);
-                                expanded.push(p);
-                            }
-                        }
-                    }
-                }
-            });
-        },
-    };
-
     $('#add-stage').click(function () {
         const yearmonth = $('#month_list').val();
         const order = parseInt($('#stage_list').val());
@@ -255,17 +203,6 @@ $(function () {
         }
     });
 });
-function setLeafData(tree) {
-    const newtree = [];
-    for (const t of tree) {
-        const child = _.find(tree, { 'ledger_pid': t.ledger_id });
-        if (!child && !t.is_leaf) {
-            t.is_leaf = true;
-        }
-        newtree.push(t);
-    }
-    return newtree;
-}
 
 function setMonthToLedger(ledgerList, slm, nextSlm, endSlm, yearSlm, yearLedgerData) {
     if (slm.length > 0) {
@@ -315,10 +252,3 @@ function setMonthToLedger(ledgerList, slm, nextSlm, endSlm, yearSlm, yearLedgerD
     }
     return ledgerList;
 }
-const is_numeric = (value) => {
-    if (typeof(value) === 'object') {
-        return false;
-    } else {
-        return !Number.isNaN(Number(value)) && value.toString().trim() !== '';
-    }
-};

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

@@ -364,7 +364,9 @@ $(document).ready(() => {
             // 切换变更令,加载右侧明细数据
             this.spread.bind(spreadNS.Events.SelectionChanged, function (e, info) {
                 const change = SpreadJsObj.getSelectObject(info.sheet);
-                self._loadChangeDetail(change);
+                if(change) {
+                    self._loadChangeDetail(change);
+                }
             });
             // 填写本期计量
             this.spread.bind(spreadNS.Events.EditEnded, function (e, info) {
@@ -499,7 +501,7 @@ $(document).ready(() => {
                 const textareas = $('textarea', this.obj);
                 for (const ta of textareas) {
                     const field = $(ta).attr('name');
-                    const text = (field && change[field]) ? change[field] : '';
+                    const text = (field && change[field]) ? change[field].replace(/<br><br>/g, '\r\n') : '';
                     ta.textContent = text;
                 }
                 const html = [];

+ 1 - 0
app/router.js

@@ -449,6 +449,7 @@ module.exports = app => {
     app.post('/tender/:id/schedule/stage/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.saveStageTp');
     app.get('/tender/:id/schedule/stage/gcl', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.stageGcl');
     app.post('/tender/:id/schedule/stage/gcl/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'scheduleController.saveStageGcl');
+    app.post('/tender/:id/schedule/stage/:order/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'scheduleController.loadTpLedgerData');
 
     // 书签
     app.post('/tender/:id/ledger/tag', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.billsTag');

+ 2 - 2
app/service/ledger.js

@@ -556,7 +556,7 @@ module.exports = app => {
             if (!lastChild) {
                 result.ledger.update = await this.getDataByIds([selectData.id]);
             }
-            result.pos = await this.ctx.service.pos.getPosData({ lid: newIds });
+            result.pos = await this.ctx.service.pos.getPosData({tid: tenderId, lid: newIds });
             return result;
         }
 
@@ -623,7 +623,7 @@ module.exports = app => {
             // 查询应返回的结果
             result.ledger.create = await this.getDataByIds(newIds);
             result.ledger.update = await this.getNextsData(selectData.tender_id, selectData.ledger_pid, selectData.order + data.length);
-            result.pos = await this.ctx.service.pos.getPosData({ lid: newIds });
+            result.pos = await this.ctx.service.pos.getPosData({tid: tenderId, lid: newIds });
             return result;
         }
 

+ 2 - 1
app/service/pos.js

@@ -24,7 +24,8 @@ module.exports = app => {
         }
 
         async getPosData(condition) {
-            return await this.db.select(this.tableName, {
+            if (!condition.tid) throw '查询计量单元缺少必要信息';
+            return await this.db.select(this.departTableName(condition.tid), {
                 where: condition,
                 columns: ['id', 'tid', 'lid', 'name', 'quantity', 'position', 'drawing_code', 'sgfh_qty', 'sjcl_qty',
                     'qtcl_qty', 'in_time', 'porder', 'add_stage', 'sgfh_expr', 'sjcl_expr', 'qtcl_expr', 'real_qty',

+ 56 - 66
app/service/rpt_gather_memory.js

@@ -488,43 +488,38 @@ module.exports = app => {
             for (const t of gsCustom.tenders) {
                 const specialKey = this._checkSpecialTender(t, gsSetting.special);
                 const tender = await this.ctx.service.tender.getCheckTender(t.tid);
-                this.ctx.query_tender = tender;
-                try {
-                    if (specialKey === '') {
-                        const completeData = {
-                            prefix: 't_' + commonIndex + '_',
-                        };
-                        completeDatas.push(completeData);
-                        switch (gsSetting.type) {
-                            case 'month':
-                                await this._gatherMonthData(tender, completeData, gsCustom.month, gsSetting.hasPre);
-                                break;
-                            case 'zone':
-                                await this._gatherZoneData(tender, completeData, gsCustom.zone);
-                                break;
-                            case 'final':
-                                await this._gatherFinalData(tender, completeData, gsSetting.hasPre);
-                                break;
-                            case 'checked-final':
-                                await this._gatherCheckedFinalData(tender, completeData, gsSetting.hasPre);
-                                break;
-                            case 'ledger':
-                                await this._gatherLedgerData(tender, completeData);
-                                break;
-                            case 'stage':
-                                await this._gatherIndexData(tender, completeData, gsCustom.stage, gsSetting.hasPre);
-                                break;
-                            case 'stage-zone':
-                                await this._gatherIndexZoneData(tender, completeData, gsCustom.stage_zone);
-                                break;
-                        }
-                        commonIndex++;
-                    } else {
-                        await this._gatherSpecialData(tender, specialKey);
+                if (specialKey === '') {
+                    const completeData = {
+                        prefix: 't_' + commonIndex + '_',
+                    };
+                    completeDatas.push(completeData);
+                    switch (gsSetting.type) {
+                        case 'month':
+                            await this._gatherMonthData(tender, completeData, gsCustom.month, gsSetting.hasPre);
+                            break;
+                        case 'zone':
+                            await this._gatherZoneData(tender, completeData, gsCustom.zone);
+                            break;
+                        case 'final':
+                            await this._gatherFinalData(tender, completeData, gsSetting.hasPre);
+                            break;
+                        case 'checked-final':
+                            await this._gatherCheckedFinalData(tender, completeData, gsSetting.hasPre);
+                            break;
+                        case 'ledger':
+                            await this._gatherLedgerData(tender, completeData);
+                            break;
+                        case 'stage':
+                            await this._gatherIndexData(tender, completeData, gsCustom.stage, gsSetting.hasPre);
+                            break;
+                        case 'stage-zone':
+                            await this._gatherIndexZoneData(tender, completeData, gsCustom.stage_zone);
+                            break;
                     }
-                } catch(err) {
+                    commonIndex++;
+                } else {
+                    await this._gatherSpecialData(tender, specialKey);
                 }
-                this.ctx.query_tender = null;
             }
 
             this.resultTree.generateSortNodes();
@@ -663,39 +658,34 @@ module.exports = app => {
             for (const t of gsCustom.tenders) {
                 const specialKey = this._checkSpecialTender(t, gsSetting.special);
                 const tender = await this.ctx.service.tender.getCheckTender(t.tid);
-                this.ctx.query_tender = tender;
-                try {
-                    if (specialKey === '') {
-                        switch (gsSetting.type) {
-                            case 'month':
-                                await this._gatherMonthTenderInfo(tender, commonIndex, gsCustom.month, gsSetting.hasPre);
-                                break;
-                            case 'zone':
-                                await this._gatherZoneTenderInfo(tender, commonIndex, gsCustom.zone);
-                                break;
-                            case 'final':
-                                await this._gatherFinalTenderInfo(tender, commonIndex, gsSetting.hasPre);
-                                break;
-                            case 'checked-final':
-                                await this._gatherCheckedFinalTenderInfo(tender, commonIndex, gsSetting.hasPre);
-                                break;
-                            case 'ledger':
-                                await this._gatherLedgerTenderInfo(tender, commonIndex);
-                                break;
-                            case 'stage':
-                                await this._gatherOrderTenderInfo(tender, commonIndex, gsCustom.stage, gsSetting.hasPre);
-                                break;
-                            case 'stage-zone':
-                                await this._gatherOrderZoneTenderInfo(tender, commonIndex, gsCustom.stage_zone);
-                                break;
-                        }
-                        commonIndex++;
-                    } else {
-                        await this._gatherSpecialTenderInfo(tender, specialKey);
+                if (specialKey === '') {
+                    switch (gsSetting.type) {
+                        case 'month':
+                            await this._gatherMonthTenderInfo(tender, commonIndex, gsCustom.month, gsSetting.hasPre);
+                            break;
+                        case 'zone':
+                            await this._gatherZoneTenderInfo(tender, commonIndex, gsCustom.zone);
+                            break;
+                        case 'final':
+                            await this._gatherFinalTenderInfo(tender, commonIndex, gsSetting.hasPre);
+                            break;
+                        case 'checked-final':
+                            await this._gatherCheckedFinalTenderInfo(tender, commonIndex, gsSetting.hasPre);
+                            break;
+                        case 'ledger':
+                            await this._gatherLedgerTenderInfo(tender, commonIndex);
+                            break;
+                        case 'stage':
+                            await this._gatherOrderTenderInfo(tender, commonIndex, gsCustom.stage, gsSetting.hasPre);
+                            break;
+                        case 'stage-zone':
+                            await this._gatherOrderZoneTenderInfo(tender, commonIndex, gsCustom.stage_zone);
+                            break;
                     }
-                } catch (err) {
+                    commonIndex++;
+                } else {
+                    await this._gatherSpecialTenderInfo(tender, specialKey);
                 }
-                this.ctx.query_tender = null;
             }
             return this.resultTenderInfo;
         }

+ 9 - 9
app/service/stage_bills.js

@@ -42,9 +42,9 @@ module.exports = app => {
                     lidSql = ' And lid in (' + this.db.escape(lid) + ')';
                 }
             }
-            const sql = 'SELECT Bills.* FROM ' + this.tableName + ' As Bills ' +
+            const sql = 'SELECT Bills.* FROM ' + this.departTableName(tid) + ' As Bills ' +
                         '  INNER JOIN ( ' +
-                        '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `sid` From ' + this.tableName +
+                        '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `sid` From ' + this.departTableName(tid) +
                         '      WHERE tid = ? And sid = ?' + lidSql +
                         '      GROUP BY `lid`' +
                         '  ) As MaxFilter ' +
@@ -70,9 +70,9 @@ module.exports = app => {
          */
         async getAuditorStageData(tid, sid, times, order, lid) {
             const lidSql = lid ? ' And Bills.lid in (?)' : '';
-            const sql = 'SELECT Bills.* FROM ' + this.tableName + ' As Bills ' +
+            const sql = 'SELECT Bills.* FROM ' + this.departTableName(tid) + ' As Bills ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `tid`, `sid` From ' + this.tableName +
+                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `progress`, `lid`, `tid`, `sid` From ' + this.departTableName(tid) +
                 '      WHERE (`times` < ? OR (`times` = ? AND `order` <= ?)) And tid = ? And sid = ?' + lidSql +
                 '      GROUP BY `lid`' +
                 '  ) As MaxFilter ' +
@@ -361,9 +361,9 @@ module.exports = app => {
         }
 
         async getSumTotalPrice(stage) {
-            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp` FROM ' + this.tableName + ' As Bills ' +
+            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp` FROM ' + this.departTableName(stage.tid) + ' As Bills ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid`, `sid` From ' + this.tableName +
+                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid`, `sid` From ' + this.departTableName(stage.tid) +
                 '      WHERE (`times` < ? OR (`times` = ? AND `order` <= ?)) AND `sid` = ?' +
                 '      GROUP BY `lid`' +
                 '  ) As MaxFilter ' +
@@ -375,14 +375,14 @@ module.exports = app => {
 
         async getSumTotalPriceFilter(stage, operate, filter) {
             const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp`' +
-                '  FROM ' + this.tableName + ' As Bills ' +
+                '  FROM ' + this.departTableName(stage.tid) + ' As Bills ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid` From ' + this.tableName +
+                '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid` From ' + this.departTableName(stage.tid) +
                 '      WHERE (`times` < ? OR (`times` = ? AND `order` <= ?)) AND `sid` = ?' +
                 '      GROUP BY `lid`' +
                 '  ) As MaxFilter ' +
                 '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.flow And Bills.lid = MaxFilter.lid ' +
-                '  INNER JOIN ' + this.ctx.service.ledger.tableName + ' As Ledger ON Bills.lid = Ledger.id' +
+                '  INNER JOIN ' + this.ctx.service.ledger.departTableName(stage.tid) + ' As Ledger ON Bills.lid = Ledger.id' +
                 '  WHERE Bills.sid = ? And Ledger.b_code ' + operate + ' ?';
             const sqlParam = [stage.times, stage.curTimes, stage.curOrder, stage.id, stage.id, filter];
             const result = await this.db.queryOne(sql, sqlParam);

+ 2 - 11
app/service/stage_bills_final.js

@@ -31,16 +31,7 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async getFinalData(tender, stageOrder) {
-            // const sql = 'SELECT * FROM ' + this.tableName + ' As Bills' +
-            //     '  INNER JOIN ( ' +
-            //     '    SELECT MAX(`sorder`) As `sorder`, `lid` From ' + this.tableName +
-            //     '      WHERE tid = ? AND sorder < ?' +
-            //     '      GROUP BY `lid`' +
-            //     '  ) As MaxFilter ' +
-            //     '  ON Bills.sorder = MaxFilter.sorder And Bills.lid = MaxFilter.lid';
-            // const sqlParam = [tender.id, stage.order, tender.id];
-            // return await this.db.query(sql, sqlParam);
-            return await this.getAllDataByCondition({
+            return await this.db.select(this.departTableName(tender.id), {
                 //columns: ['lid', 'contract_qty', 'qc_qty', 'contract_tp', 'qc_tp'],
                 where: {tid: tender.id, sorder: stageOrder},
             });
@@ -148,7 +139,7 @@ module.exports = app => {
         }
 
         async getSumTotalPrice(tenderId, stageOrder) {
-            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp` FROM ' + this.tableName +
+            const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp` FROM ' + this.departTableName(tenderId) +
                 '  WHERE sorder = ? and tid = ?';
             const sqlParam = [stageOrder, tenderId];
             const result = await this.db.queryOne(sql, sqlParam);

+ 8 - 11
app/service/tender.js

@@ -269,7 +269,6 @@ module.exports = app => {
          * @return {Promise<boolean>} - 结果
          */
         async deleteTenderNoBackup(id) {
-            this.ctx.query_tender = await this.ctx.service.tender.getDataById(id);
             const transaction = await this.db.beginTransaction();
             try {
                 const tenderMsg = await this.getDataById(id);
@@ -280,18 +279,18 @@ module.exports = app => {
                 await this.ctx.helper.delFiles(attList);
                 await transaction.delete(this.tableName, { id });
                 await transaction.delete(this.ctx.service.tenderInfo.tableName, { tid: id });
-                await transaction.delete(this.ctx.service.ledger.tableName, { tender_id: id });
+                await transaction.delete(this.ctx.service.ledger.departTableName(id), { tender_id: id });
                 await transaction.delete(this.ctx.service.ledgerAudit.tableName, { tender_id: id });
-                await transaction.delete(this.ctx.service.pos.tableName, { tid: id });
+                await transaction.delete(this.ctx.service.pos.departTableName(id), { tid: id });
                 await transaction.delete(this.ctx.service.pay.tableName, { tid: id });
 
                 await transaction.delete(this.ctx.service.stage.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.stageAudit.tableName, { tid: id });
-                await transaction.delete(this.ctx.service.stageBills.tableName, { tid: id });
-                await transaction.delete(this.ctx.service.stagePos.tableName, { tid: id });
+                await transaction.delete(this.ctx.service.stageBills.departTableName(id), { tid: id });
+                await transaction.delete(this.ctx.service.stagePos.departTableName(id), { tid: id });
                 await transaction.delete(this.ctx.service.stageBillsDgn.tableName, { tid: id });
-                await transaction.delete(this.ctx.service.stageBillsFinal.tableName, { tid: id });
-                await transaction.delete(this.ctx.service.stagePosFinal.tableName, { tid: id });
+                await transaction.delete(this.ctx.service.stageBillsFinal.departTableName(id), { tid: id });
+                await transaction.delete(this.ctx.service.stagePosFinal.departTableName(id), { tid: id });
                 await transaction.delete(this.ctx.service.stageDetail.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.stagePay.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.stageChange.tableName, { tid: id });
@@ -307,8 +306,8 @@ module.exports = app => {
 
                 await transaction.delete(this.ctx.service.ledgerRevise.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.reviseAudit.tableName, { tender_id: id });
-                await transaction.delete(this.ctx.service.reviseBills.tableName, { tender_id: id });
-                await transaction.delete(this.ctx.service.revisePos.tableName, { tid: id });
+                await transaction.delete(this.ctx.service.reviseBills.departTableName(id), { tender_id: id });
+                await transaction.delete(this.ctx.service.revisePos.departTableName(id), { tid: id });
 
                 await transaction.delete(this.ctx.service.material.tableName, { tid: id });
                 await transaction.delete(this.ctx.service.materialAudit.tableName, { tid: id });
@@ -332,12 +331,10 @@ module.exports = app => {
                 // 记录删除日志
                 await this.ctx.service.projectLog.addProjectLog(transaction, projectLogConst.type.tender, projectLogConst.status.delete, tenderMsg.name, id);
                 await transaction.commit();
-                this.ctx.query_tender = null;
                 return true;
             } catch (err) {
                 this.ctx.helper.log(err);
                 await transaction.rollback();
-                this.ctx.query_tender = null;
                 return false;
             }
         }

+ 8 - 8
app/view/change/information.ejs

@@ -128,19 +128,19 @@
                                 </div>
                                 <div class="form-group">
                                     <label><b class="text-danger">*&nbsp;</b>工程变更理由及内容</label>
-                                    <textarea class="form-control form-control-sm" name="content" rows="6"><%- change.content %></textarea>
+                                    <textarea class="form-control form-control-sm" name="content" rows="6"><%- ctx.helper.replaceStr(change.content, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>工程变更合同依据</label>
-                                    <textarea class="form-control form-control-sm" name="basis" rows="6"><%- change.basis %></textarea>
+                                    <textarea class="form-control form-control-sm" name="basis" rows="6"><%- ctx.helper.replaceStr(change.basis, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>变更工程量数量计算式</label>
-                                    <textarea class="form-control form-control-sm" name="expr" rows="2"><%- change.expr %></textarea>
+                                    <textarea class="form-control form-control-sm" name="expr" rows="2"><%- ctx.helper.replaceStr(change.expr, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>备注</label>
-                                    <textarea class="form-control form-control-sm" name="memo" rows="3"><%- change.memo %></textarea>
+                                    <textarea class="form-control form-control-sm" name="memo" rows="3"><%- ctx.helper.replaceStr(change.memo, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>变更类型</label>
@@ -236,19 +236,19 @@
                                 </div>
                                 <div class="form-group">
                                     <label>工程变更理由及内容</label>
-                                    <textarea class="form-control form-control-sm" rows="6" readonly><%- change.content %></textarea>
+                                    <textarea class="form-control form-control-sm" rows="6" readonly><%- ctx.helper.replaceStr(change.content, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>工程变更合同依据</label>
-                                    <textarea class="form-control form-control-sm" rows="6" readonly><%- change.basis %></textarea>
+                                    <textarea class="form-control form-control-sm" rows="6" readonly><%- ctx.helper.replaceStr(change.basis, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>变更工程量数量计算式</label>
-                                    <textarea class="form-control form-control-sm" rows="2" readonly><%- change.expr %></textarea>
+                                    <textarea class="form-control form-control-sm" rows="2" readonly><%- ctx.helper.replaceStr(change.expr, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>备注</label>
-                                    <textarea class="form-control form-control-sm" rows="3" readonly><%- change.memo %></textarea>
+                                    <textarea class="form-control form-control-sm" rows="3" readonly><%- ctx.helper.replaceStr(change.memo, /<br><br>/g, '\r\n') %></textarea>
                                 </div>
                                 <div class="form-group">
                                     <label>变更类型</label>

+ 99 - 58
app/view/schedule/index.ejs

@@ -19,10 +19,10 @@
                     <div class="col-12 mb-4">
                         <ul class="nav nav-tabs justify-content-center">
                             <li class="nav-item">
-                                <a class="nav-link px-5 py-2 active" href="#">金额模式</a>
+                                <a class="nav-link px-5 py-2 active" href="#tp" id="tp-tab" data-toggle="tab" role="tab" aria-controls="tp" aria-selected="true">金额模式</a>
                             </li>
                             <li class="nav-item">
-                                <a class="nav-link px-5 py-2" href="#">工程量模式</a>
+                                <a class="nav-link px-5 py-2" href="#gcl" id="gcl-tab" data-toggle="tab" role="tab" aria-controls="gcl" aria-selected="false">工程量模式</a>
                             </li>
                         </ul>
                     </div>
@@ -31,63 +31,71 @@
                         <div class="col-auto p-0">
                             <div class="card text-center">
                                 <div class="card-body">
-                                    <h5 class="card-title">163,000.00 <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占设计比例">20%</small></h5>
+                                    <h5 class="card-title"><%- scheduleInfo ? ctx.helper.formatNum(scheduleInfo.plan_tp, '#,##0.######') : '' %> <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占设计比例">20%</small></h5>
                                     <p class="card-text text-muted">计划完成金额</p>
                                 </div>
                             </div>
                         </div>
+                        <!--<div class="col-auto pr-0">-->
+                            <!--<div class="card text-center">-->
+                                <!--<div class="card-body">-->
+                                    <!--<h5 class="card-title">50,000.00 <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占计划比例">5%</small></h5>-->
+                                    <!--<p class="card-text text-muted">已完成计划金额</p>-->
+                                <!--</div>-->
+                            <!--</div>-->
+                        <!--</div>-->
                         <div class="col-auto pr-0">
                             <div class="card text-center">
                                 <div class="card-body">
-                                    <h5 class="card-title">50,000.00 <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占计划比例">5%</small></h5>
-                                    <p class="card-text text-muted">已完成计划金额</p>
+                                    <h5 class="card-title"><%- scheduleInfo ? ctx.helper.formatNum(scheduleInfo.sj_tp, '#,##0.######') : '' %> <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占计比例">15%</small></h5>
+                                    <p class="card-text text-muted">实际完成金额</p>
                                 </div>
                             </div>
                         </div>
-                        <div class="col-auto pr-0">
-                            <div class="card text-center">
+                    </div>
+                    <div class="tab-content">
+                        <div id="tp" class="tab-pane fade show active" role="tabpanel" aria-labelledby="tp-tab">
+                            <!--进度条-->
+                            <div class="mb-3">
+                                计划金额进度(元)
+                                <div class="progress">
+                                    <div class="progress-bar bg-success" style="width:24%;" data-placement="bottom" data-toggle="tooltip" data-original-title="计划完成金额:¥300.00">24%</div>
+                                    <div class="progress-bar bg-gray" style="width:76%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未计划:¥930.00">66%</div>
+                                </div>
+                                <p class="mt-2 mb-0">实际金额进度哦(元)</p>
+                                <div class="progress">
+                                    <div class="progress-bar bg-success" style="width: 18%;" data-placement="bottom" data-toggle="tooltip" data-original-title="实际完成金额:¥400.00">18%</div>
+                                    <div class="progress-bar bg-gray" style="width:82%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未完成:¥930.00">72%</div>
+                                </div>
+                            </div>
+                            <div class="card mb-3">
                                 <div class="card-body">
-                                    <h5 class="card-title">50,000.00 <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占设计比例">15%</small></h5>
-                                    <p class="card-text text-muted">实际完成金额</p>
+                                    <h5 class="card-title">完成金额进度表</h5>
+                                    <div id="chartContainer4" style="height: 300px; width: 100%;">
+                                    </div>
                                 </div>
                             </div>
                         </div>
-                    </div>
-                    <!--进度条-->
-                    <div class="mb-3">
-                        计划工程量进度
-                        <div class="progress">
-                            <div class="progress-bar bg-info" style="width:24%;" data-placement="bottom" data-toggle="tooltip" data-original-title="计划完成工程量:30,000.00">24%</div>
-                            <div class="progress-bar bg-gray" style="width:76%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未计划:930,00.00">66%</div>
-                        </div>
-                        <p class="mt-2 mb-0">实际工程量进度</p>
-                        <div class="progress">
-                            <div class="progress-bar bg-info" style="width: 18%;" data-placement="bottom" data-toggle="tooltip" data-original-title="实际完成工程量:40,000.00">18%</div>
-                            <div class="progress-bar bg-gray" style="width:82%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未完成:930,00.00">72%</div>
-                        </div>
-                        <p class="mt-2 mb-0">计划金额进度(万元)</p>
-                        <div class="progress">
-                            <div class="progress-bar bg-success" style="width:24%;" data-placement="bottom" data-toggle="tooltip" data-original-title="计划完成金额:¥300.00">24%</div>
-                            <div class="progress-bar bg-gray" style="width:76%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未计划:¥930.00">66%</div>
-                        </div>
-                        <p class="mt-2 mb-0">实际金额进度哦(万元)</p>
-                        <div class="progress">
-                            <div class="progress-bar bg-success" style="width: 18%;" data-placement="bottom" data-toggle="tooltip" data-original-title="实际完成金额:¥400.00">18%</div>
-                            <div class="progress-bar bg-gray" style="width:82%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未完成:¥930.00">72%</div>
-                        </div>
-                    </div>
-                    <!--图表-->
-                    <div class="card mb-3">
-                        <div class="card-body">
-                            <h5 class="card-title">工程量进度表</h5>
-                            <div id="chartContainer3" style="height: 300px; width: 100%;">
+                        <div id="gcl" class="tab-pane fade" role="tabpanel" aria-labelledby="gcl-tab">
+                            <div class="mb-3">
+                                计划工程量进度
+                                <div class="progress">
+                                    <div class="progress-bar bg-info" style="width:24%;" data-placement="bottom" data-toggle="tooltip" data-original-title="计划完成工程量:30,000.00">24%</div>
+                                    <div class="progress-bar bg-gray" style="width:76%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未计划:930,00.00">66%</div>
+                                </div>
+                                <p class="mt-2 mb-0">实际工程量进度</p>
+                                <div class="progress">
+                                    <div class="progress-bar bg-info" style="width: 18%;" data-placement="bottom" data-toggle="tooltip" data-original-title="实际完成工程量:40,000.00">18%</div>
+                                    <div class="progress-bar bg-gray" style="width:82%;" data-placement="bottom" data-toggle="tooltip" data-original-title="合同未完成:930,00.00">72%</div>
+                                </div>
                             </div>
-                        </div>
-                    </div>
-                    <div class="card mb-3">
-                        <div class="card-body">
-                            <h5 class="card-title">完成金额进度表</h5>
-                            <div id="chartContainer4" style="height: 300px; width: 100%;">
+                            <!--图表-->
+                            <div class="card mb-3">
+                                <div class="card-body">
+                                    <h5 class="card-title">工程量进度表</h5>
+                                    <div id="chartContainer3" style="height: 300px; width: 100%;">
+                                    </div>
+                                </div>
                             </div>
                         </div>
                     </div>
@@ -98,10 +106,11 @@
 </div>
 <script src="/public/js/echarts/echarts.min.js"></script>
 <script type="text/javascript">
+    var charts = new Array();
     //计划进度//
     // 基于准备好的dom,初始化echarts图表
-    var myChart = echarts.init(document.getElementById('chartContainer3'));
-    var option = {
+    var myChart2 = echarts.init(document.getElementById('chartContainer3'));
+    var option2 = {
         color: ['#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
             '#17a2b8','#28a745','#e4575a','#959eac','#6699FF',
             '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
@@ -123,7 +132,11 @@
             {
                 type : 'category',
                 splitLine : {show : true},
-                data : ['2020年1月','2020年2月','2020年3月','2020年4月','2020年5月','2020年6月','2020年7月']
+                data : [<% if (scheduleMonth.length > 0) { %>
+                    <% for (const sm of scheduleMonth) { %>
+                        '<%- sm.yearmonth.split('-')[0] %>年<%- parseInt(sm.yearmonth.split('-')[1]) %>月',
+                    <% } %>
+                <% } %>],
             }
         ],
         yAxis : [
@@ -152,26 +165,35 @@
                 type:'bar',
                 tooltip : {trigger: 'item',formatter: "{b}<br/>{a}:{c}"},
                 stack: '计划',
-                data:[320, 332, 301, 334, 390, 330, 320]
+                data:[<% if (scheduleMonth.length > 0) { %>
+                    <% for (const sm of scheduleMonth) { %>
+                    '<%- sm.plan_gcl  %>',
+                    <% } %>
+                    <% } %>]
             },
             {
                 name:'实际完成工程量',
                 type:'bar',
                 tooltip : {trigger: 'item',formatter: "{b}<br/>{a}:{c}"},
                 stack: '实际',
-                data:[310, 330, 301, 334, 390, 330, 320]
+                data:[<% if (scheduleMonth.length > 0) { %>
+                    <% for (const sm of scheduleMonth) { %>
+                    '<%- sm.sj_gcl  %>',
+                    <% } %>
+                    <% } %>]
             },
             {
                 name:'实际占设计比例',
                 type:'line',
                 tooltip : {trigger: 'axis',formatter: "{b}占合同比例<br/>{a}:{c} %"},
                 yAxisIndex: 1,
-                data:[10, 15, 20, 13, 11, 9, 5]
+                data:[10, 15, 20, 13, 11,]
             },
         ]
     };
     // 为echarts对象加载数据
-    myChart.setOption(option);
+    myChart2.setOption(option2);
+    charts.push(myChart2);
     //4 完成金额进度进度//
     var myChart = echarts.init(document.getElementById('chartContainer4'));
     var option = {
@@ -196,7 +218,11 @@
             {
                 type : 'category',
                 splitLine : {show : true},
-                data : ['2020年1月','2020年2月','2020年3月','2020年4月','2020年5月','2020年6月','2020年7月']
+                data : [<% if (scheduleMonth.length > 0) { %>
+                <% for (const sm of scheduleMonth) { %>
+                    '<%- sm.yearmonth.split('-')[0] %>年<%- parseInt(sm.yearmonth.split('-')[1]) %>月',
+                <% } %>
+            <% } %>]
             }
         ],
         yAxis : [
@@ -205,7 +231,7 @@
                 name : '金额',
                 position:'left',
                 axisLabel : {
-                    formatter: '{value} 元'
+                    formatter: '{value} 元'
                 },
                 splitArea : {show : true}
             },
@@ -223,29 +249,38 @@
             {
                 name:'计划完成金额',
                 type:'bar',
-                tooltip : {trigger: 'item',formatter: "{b}<br/>{a}:{c}元"},
+                tooltip : {trigger: 'item',formatter: "{b}<br/>{a}:{c}元"},
                 stack: '计划',
-                data:[320, 332, 301, 334, 390, 330, 320]
+                data:[<% if (scheduleMonth.length > 0) { %>
+                    <% for (const sm of scheduleMonth) { %>
+                    '<%- sm.plan_tp  %>',
+                    <% } %>
+                    <% } %>]
             },
             {
                 name:'实际完成金额',
                 type:'bar',
-                tooltip : {trigger: 'item',formatter: "{b}<br/>{a}:{c}元"},
+                tooltip : {trigger: 'item',formatter: "{b}<br/>{a}:{c}元"},
                 stack: '实际',
-                data:[310, 330, 301, 334, 390, 330, 320]
+                data:[<% if (scheduleMonth.length > 0) { %>
+                    <% for (const sm of scheduleMonth) { %>
+                    '<%- sm.sj_tp  %>',
+                    <% } %>
+                    <% } %>]
             },
             {
                 name:'实际占合同比例',
                 type:'line',
                 tooltip : {trigger: 'axis',formatter: "{b}占合同比例<br/>{a}:{c} %"},
                 yAxisIndex: 1,
-                data:[10, 15, 20, 13, 11, 9, 5]
+                data:[10, 15, 20, 13, 11,]
             },
         ]
     };
 
     // 为echarts对象加载数据
     myChart.setOption(option);
+    charts.push(myChart);
 </script>
 <!--sjs-->
 <script>
@@ -295,6 +330,12 @@
                 精度:3,
             }
         ];
+
+        $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
+            for(var i = 0; i < charts.length; i++) {
+                charts[i].resize();
+            }
+        });
         // const spread = new GC.Spread.Sheets.Workbook($('#option-spread1')[0], {
         //     sheetCount: 1
         // });

+ 19 - 35
app/view/schedule/stage_gcl.ejs

@@ -25,52 +25,34 @@
         <div class="c-body">
             <div class="sjs-height-1" style="overflow: auto;" id="ledger-spread">
             </div>
-            <div class="bcontent-wrap">
-                <div id="main-resize" class="resize-y" id="top-spr" r-Type="height" div1=".sjs-height-1" div2=".bcontent-wrap" title="调整大小"><!--调整上下高度条--></div>
+            <div class="bcontent-wrap" id="main-bottom">
+                <div id="main-resize" class="resize-y" r-Type="height" div1="#ledger-spread" div2="#main-bottom" title="调整大小"><!--调整上下高度条--></div>
                 <div class="bc-bar mb-1">
                     <ul class="nav nav-tabs">
                         <li class="nav-item">
                             <a class="nav-link active" data-toggle="tab" href="#huizong" role="tab">汇总</a>
                         </li>
                         <li class="nav-item">
-                            <div class="d-inline-block ml-2">
-                                <div class="dropdown">
-                                    <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                                        2020年
-                                    </button>
-                                    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" x-placement="bottom-start">
-                                        <a class="dropdown-item" href="#">2019年</a>
+                            <% if (scheduleStage.length > 0) { %>
+                                <div class="d-inline-block ml-2">
+                                    <div class="dropdown">
+                                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                            <%- curScheduleStage.yearmonth.split('-')[0] %>年<%- parseInt(curScheduleStage.yearmonth.split('-')[1]) %>月(第<%- curScheduleStage.order %>期)
+                                        </button>
+                                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 26px, 0px); top: 0px; left: 0px; will-change: transform;">
+                                            <% for (const s of scheduleStage) { %>
+                                                <% if (s.id !== curScheduleStage.id) { %>
+                                                    <a class="dropdown-item change-tp" data-order="<%- s.order %>" href="javascript:void(0);"><%- s.yearmonth.split('-')[0] %>年<%- parseInt(s.yearmonth.split('-')[1]) %>月(第<%- s.order %>期)</a>
+                                                <% } %>
+                                            <% } %>
+                                        </div>
                                     </div>
                                 </div>
-                            </div>
-                            <div class="d-inline-block">
-                                <div class="dropdown">
-                                    <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                                        1月
-                                    </button>
-                                    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" x-placement="bottom-start">
-                                        <a class="dropdown-item" href="#">2月</a>
-                                        <a class="dropdown-item" href="#">3月</a>
-                                        <a class="dropdown-item" href="#">4月</a>
-                                    </div>
-                                </div>
-                            </div>
+                            <% } %>
                         </li>
                     </ul>
                 </div>
-                <div class="tab-content">
-                    <div class="tab-pane active" id="huizong-spread">
-                        <table class="table table-bordered table-sm">
-                            <thead>
-                            <tr class="text-center"><th rowspan="2">项目节编号</th><th rowspan="2">名称</th><th rowspan="2">单位</th><th rowspan="2">经济指标</th><th colspan="2">总设计</th><th colspan="2">自开工至本月计划完成</th><th colspan="2">截止本月完成计量</th><th colspan="2">本年计划完成</th><th colspan="2">本年累计完成</th><th colspan="2">本月计划完成</th><th colspan="2">本月完成计量</th><th colspan="2">下月计划</th></tr>
-                            <tr class="text-center"><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th><th>工程量</th><th>金额(万元)</th></tr>
-                            </thead>
-                            <tr><td>1-2</td><td>路基工程</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
-                            <tr><td>1-2-2</td><td>挖方</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
-                            <tr><td>1-2-2-1</td><td>挖土方</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
-                            <tr><td>1-2-2-1-1</td><td>挖路基土方</td><td></td><td></td><td></td><td></td><td>11111</td><td>11111</td><td>22222</td><td>22222</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
-                        </table>
-                    </div>
+                <div class="sp-wrap" id="huizong-spread">
                 </div>
             </div>
         </div>
@@ -84,4 +66,6 @@
     const schedule = JSON.parse('<%- JSON.stringify(schedule) %>');
     const scheduleMonth = JSON.parse('<%- JSON.stringify(scheduleMonth) %>');
     const monthList = _.map(scheduleMonth, 'yearmonth');
+    const scheduleStage = JSON.parse('<%- JSON.stringify(scheduleStage) %>');
+    const curScheduleStage = JSON.parse('<%- JSON.stringify(curScheduleStage) %>');
 </script>

+ 8 - 8
app/view/tender/tender_sub_menu.ejs

@@ -43,14 +43,14 @@
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-line-chart"></i> <span>材料调差</span></a></li>
             </ul>
         </div>
-        <!--<div class="nav-box">-->
-            <!--<h3><i class="fa fa-bar-chart "></i> 形象进度</h3>-->
-            <!--<ul class="nav-list list-unstyled sub-list">-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>-->
-                <!--<li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/schedule/stage') !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>-->
-            <!--</ul>-->
-        <!--</div>-->
+        <div class="nav-box">
+            <h3><i class="fa fa-bar-chart "></i> 形象进度</h3>
+            <ul class="nav-list list-unstyled sub-list">
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>
+                <li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/schedule/stage') !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>
+            </ul>
+        </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/report') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/report"><i class="fa fa-file-text-o"></i> <span>报表</span></a></li>

+ 8 - 8
app/view/tender/tender_sub_mini_menu.ejs

@@ -41,14 +41,14 @@
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-line-chart"></i> <span>材料调差</span></a></li>
             </ul>
         </div>
-        <!--<div class="nav-box">-->
-            <!--<h3><i class="fa fa-bar-chart "></i> 形象进度</h3>-->
-            <!--<ul class="nav-list list-unstyled sub-list">-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>-->
-                <!--<li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage/gcl') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>-->
-            <!--</ul>-->
-        <!--</div>-->
+        <div class="nav-box">
+            <h3><i class="fa fa-bar-chart "></i> 形象进度</h3>
+            <ul class="nav-list list-unstyled sub-list">
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>
+                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/stage/gcl') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>
+            </ul>
+        </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/report') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/report"><i class="fa fa-file-text-o"></i> <span>报表</span></a></li>

+ 1 - 1
package.json

@@ -78,7 +78,7 @@
         "test-local": "set EGG_SERVER_ENV=local&& egg-bin test",
         "test-qa": "set EGG_SERVER_ENV=qa&&egg-bin test",
         "test-auto": "set EGG_SERVER_ENV=autotest&&egg-bin test",
-        "dev-docker": "egg-scripts start --port 7005",
+        "dev-docker": "egg-scripts start --env=local --port 7005",
         "cov": "egg-bin cov",
         "lint": "eslint .",
         "ci": "npm run lint && npm run cov",