Browse Source

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

Tony Kang 1 year ago
parent
commit
6eaed26f2c
41 changed files with 2205 additions and 74 deletions
  1. 3 0
      app/const/audit.js
  2. 9 0
      app/const/project_setting.js
  3. 24 0
      app/const/spread.js
  4. 53 2
      app/controller/advance_controller.js
  5. 25 2
      app/controller/datacollect_controller.js
  6. 15 4
      app/controller/setting_controller.js
  7. 1 1
      app/controller/stage_controller.js
  8. 3 1
      app/controller/tender_controller.js
  9. 3 1
      app/controller/wap_controller.js
  10. 1 1
      app/lib/revise_price.js
  11. 7 2
      app/lib/spread_setting.js
  12. 1 0
      app/middleware/advance_check.js
  13. 4 4
      app/middleware/change_apply_audit_check.js
  14. 3 3
      app/middleware/change_audit_check.js
  15. 4 4
      app/middleware/change_plan_audit_check.js
  16. 4 4
      app/middleware/change_project_audit_check.js
  17. BIN
      app/public/images/juecedaping06.png
  18. 8 1
      app/public/js/advance.js
  19. 14 3
      app/public/js/ledger_gather.js
  20. 38 5
      app/public/js/revise.js
  21. 74 0
      app/public/js/revise_gcl_compare.js
  22. 38 1
      app/public/js/shares/gcl_gather_compare.js
  23. 48 0
      app/public/js/stage_gather.js
  24. 2 0
      app/router.js
  25. 60 1
      app/service/advance_audit.js
  26. 14 3
      app/service/change.js
  27. 12 0
      app/service/project.js
  28. 3 1
      app/service/stage.js
  29. 4 0
      app/view/advance/audit_btn.ejs
  30. 8 0
      app/view/advance/detail.ejs
  31. 144 0
      app/view/advance/modal_audit.ejs
  32. 5 1
      app/view/datacollect/index.ejs
  33. 1228 0
      app/view/datacollect/index4GY18Y.ejs
  34. 26 24
      app/view/ledger/gather.ejs
  35. 37 1
      app/view/revise/gcl_compare.ejs
  36. 20 1
      app/view/setting/datacollect.ejs
  37. 151 0
      app/view/setting/datacollect_modal.ejs
  38. 42 1
      app/view/stage/gather.ejs
  39. 1 1
      app/view/tender/detail.ejs
  40. 57 0
      db_script/change_valuation.js
  41. 11 1
      sql/update.sql

+ 3 - 0
app/const/audit.js

@@ -569,6 +569,7 @@ const advance = (function() {
         checked: 3, // 审批通过
         checkNo: 4, // 审批退回原报
         checkNoPre: 5, // 审批退回上一人
+        checkAgain: 6, // 终审退回  --该状态仅可用于,终审退回时,修改原终审的审批状态,并同时新增一条新的终审审批中记录
     };
 
     const statusString = [];
@@ -577,6 +578,7 @@ const advance = (function() {
     statusString[status.checked] = '审批通过';
     statusString[status.checkNo] = '审批退回';
     statusString[status.checkNoPre] = '审批退回';
+    statusString[status.checkAgain] = '重新审批';
 
     const statusClass = [];
     statusClass[status.uncheck] = '';
@@ -584,6 +586,7 @@ const advance = (function() {
     statusClass[status.checked] = 'text-success';
     statusClass[status.checkNo] = 'text-warning';
     statusClass[status.checkNoPre] = 'text-warning';
+    statusClass[status.checkAgain] = 'text-warning';
 
     // 标段概况页
     // 描述文本

+ 9 - 0
app/const/project_setting.js

@@ -64,8 +64,17 @@ const defaultColSet = {
         { field: 'wf_tp', show: 0, alias: '' },
     ],
 };
+// 决策大屏06 报表数据统计值设置及保存
+const daPing06Set = {
+    sr: null,
+    sr_value: null,
+    cb: null,
+    cb_value: null,
+    cb_show: [],
+};
 module.exports = {
     noticeSetting: notice_setting,
     colSet,
     defaultColSet,
+    daPing06Set,
 };

+ 24 - 0
app/const/spread.js

@@ -1275,6 +1275,30 @@ const stageGather = {
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
         readOnly: true,
+    },
+    gatherLeafXmj: {
+        cols: [
+            {title: '单位工程', colSpan: '1', rowSpan: '2', field: 'dwgc', hAlign: 0, width: 80, formatter: '@', visible: false},
+            {title: '分部工程', colSpan: '1', rowSpan: '2', field: 'fbgc', hAlign: 0, width: 80, formatter: '@', visible: false},
+            {title: '分项工程', colSpan: '1', rowSpan: '2', field: 'fxgc', hAlign: 0, width: 80, formatter: '@', visible: false},
+            {title: '细目', colSpan: '1', rowSpan: '2', field: 'jldy', hAlign: 0, width: 80, formatter: '@', visible: false},
+            {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 80, formatter: '@'},
+            {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|完成', colSpan: '|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        headColWidth: [30],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
     }
 };
 // 期 -- 审核比较

+ 53 - 2
app/controller/advance_controller.js

@@ -149,7 +149,7 @@ module.exports = app => {
             const advancePayTotal = ctx.tender.info.deal_param[`${typeConsts.typeColMap[ctx.advance.type].value}Advance`];
             try {
                 await this._checkCanEntry(ctx);
-                const { uncheck, checkNo } = auditConst.status;
+                const { uncheck, checkNo, checked } = auditConst.status;
                 const { status } = ctx.advance;
                 const isEdited = ctx.session.sessionUser.accountId === ctx.advance.uid && (status === uncheck || status === checkNo);
                 const renderData = await this._getDefaultRenderData(ctx);
@@ -175,6 +175,11 @@ module.exports = app => {
                     prev_total_amount = ctx.helper.formatMoney(ctx.advance.prev_total_amount, ',', isLimitMax ? s2.length : 2);
                 }
 
+                ctx.advance.finalAuditorId = status === checked && ctx.advance.auditors && ctx.advance.auditors.length > 0 ? ctx.advance.auditors[ctx.advance.auditors.length - 1].audit_id : false;
+                // 获取用户人验证手机号
+                const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                const auth_mobile = pa.auth_mobile;
+                renderData.authMobile = auth_mobile;
                 renderData.isEdited = isEdited;
                 renderData.advance = ctx.advance;
                 renderData.cur_amount = cur_amount;
@@ -361,7 +366,7 @@ module.exports = app => {
         async checkAudit(ctx) {
             try {
                 if (!ctx.advance || ctx.advance.status !== auditConst.status.checking) {
-                    throw '当前材料调差期数据有误';
+                    throw '当前预付款数据有误';
                 }
                 if (!ctx.advance.curAuditor || ctx.advance.curAuditor.audit_id !== ctx.session.sessionUser.accountId) {
                     throw '您无权进行该操作';
@@ -389,6 +394,52 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 重新审批
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async checkAgain(ctx) {
+            try {
+                if (!ctx.advance || ctx.advance.status !== auditConst.status.checked) {
+                    throw '当前预付款数据有误';
+                }
+                const finalAuditorId = ctx.advance.auditors && ctx.advance.auditors.length > 0 ? ctx.advance.auditors[ctx.advance.auditors.length - 1].audit_id : false;
+                if (!finalAuditorId || finalAuditorId !== ctx.session.sessionUser.accountId) {
+                    throw '您无权进行该操作';
+                }
+                if (ctx.session.sessionUser.loginStatus === 0) {
+                    const code = ctx.request.body.code;
+                    const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                    if (!pa.auth_mobile) {
+                        throw '未绑定手机号';
+                    }
+                    const cacheKey = 'smsCode:' + ctx.session.sessionUser.accountId;
+                    const cacheCode = await app.redis.get(cacheKey);
+                    // console.log(cacheCode);
+                    if (cacheCode === null || code === undefined || cacheCode !== (code + pa.auth_mobile)) {
+                        throw '验证码不正确!';
+                    }
+                }
+                // 重新审批
+                const result = await ctx.service.advanceAudit.checkAgain(ctx.advance);
+                if (!result) {
+                    throw '重新审批失败';
+                }
+                ctx.body = {
+                    err: 0,
+                    url: ctx.request.header.referer,
+                    msg: '',
+                };
+            } catch (err) {
+                console.log(err);
+                ctx.body = {
+                    err: 1,
+                    msg: err,
+                };
+            }
+        }
+
         _checkAdvanceFileCanModify(ctx) {
             // 检查登录用户,是否可操作
             const accountId = ctx.session.sessionUser.accountId;

+ 25 - 2
app/controller/datacollect_controller.js

@@ -23,6 +23,7 @@ const sendToWormhole = require('stream-wormhole');
 const scheduleConst = require('../const/schedule');
 const changeConst = require('../const/change');
 const tenderInfoModel = require('../lib/tender_info');
+const projectSettingConst = require('../const/project_setting');
 const mapConst = require('../const/map');
 
 module.exports = app => {
@@ -73,6 +74,11 @@ module.exports = app => {
                         map_json.lat = mapInfo.lat;
                     }
                 }
+                if (ctx.params.index) {
+                    ctx.session.sessionProject.dataCollect = parseInt(ctx.params.index);
+                }
+                const is_dz2 = ['P0505', 'P0506', 'P1201', 'P1202', 'GY18Y'].indexOf(ctx.session.sessionProject.code) !== -1
+                    && projectData.data_collect_pages.includes('6') && ctx.session.sessionProject.dataCollect === 6;
                 const renderData = {
                     projectData,
                     noticeList,
@@ -87,8 +93,21 @@ module.exports = app => {
                     pushType: auditConst.pushType,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.datacollect.index),
                 };
-                await this.layout('datacollect/index.ejs', renderData);
+                if (is_dz2) {
+                    const commonJson = projectData.common_json ? JSON.parse(projectData.common_json) : null;
+                    renderData.daping06Set = commonJson && commonJson.daPing06_set ? commonJson.daPing06_set : ctx.helper._.cloneDeep(projectSettingConst.daPing06Set);
+                    const glCategory = categoryData.find(item => item.name === '管理类别');
+                    const dpCategory = [];
+                    for (const d of renderData.daping06Set.cb_show) {
+                        dpCategory.push(glCategory.value.find(item => item.id === d));
+                    }
+                    renderData.dpCategory = dpCategory;
+                    await this.layout('datacollect/index4GY18Y.ejs', renderData);
+                } else {
+                    await this.layout('datacollect/index.ejs', renderData);
+                }
             } catch (err) {
+                console.log(err);
                 this.log(err);
                 ctx.redirect(this.menu.menu.dashboard.url);
             }
@@ -132,7 +151,7 @@ module.exports = app => {
                     // 用标段管理的方法获取t数据
                     await this.ctx.service.tenderCache.loadTenderCache(t, '');
                     t.total_price = t.ledger_tp && t.ledger_tp.total_price ? t.ledger_tp.total_price : 0;
-                    [t.change_tp, t.change_p_tp, t.change_n_tp] = await ctx.service.change.getChangeTp(t.id);
+                    [t.change_tp, t.change_p_tp, t.change_n_tp, t.change_valuation_tp, t.change_unvaluation_tp] = await ctx.service.change.getChangeTp(t.id);
                     // t.material_tp = await ctx.service.material.getSumMaterial(t.id);
                     // 获取本标段 本月计量期审批通过数目,变更令审批通过数目,台账修订通过数目,材料调差通过数目
                     t.month_stage_num = await ctx.service.stageAudit.getNumByMonth(t.id, startMonth, endMonth);
@@ -148,11 +167,15 @@ module.exports = app => {
                         const monthOneStage = ctx.app._.find(month_stage, { yearmonth: s.s_time });
                         if (monthOneStage) {
                             monthOneStage.tp = ctx.helper.add(monthOneStage.tp, s.tp);
+                            monthOneStage.end_yf_tp = ctx.helper.add(monthOneStage.end_yf_tp, s.end_yf_tp);
+                            monthOneStage.end_sf_tp = ctx.helper.add(monthOneStage.end_sf_tp, s.end_sf_tp);
                         } else {
                             const data = {
                                 yearmonth: s.s_time,
                                 tp: s.tp,
                                 end_tp: s.end_tp,
+                                end_yf_tp: s.end_yf_tp,
+                                end_sf_tp: s.end_sf_tp,
                             };
                             month_stage.push(data);
                         }

+ 15 - 4
app/controller/setting_controller.js

@@ -987,7 +987,6 @@ module.exports = app => {
                     throw '没有访问权限';
                 }
                 const fun_set = await ctx.service.project.getFunSet(projectData.fun_set);
-                console.log(fun_set);
                 await this.layout('setting/fun.ejs', {
                     projectData,
                     funRela,
@@ -1139,6 +1138,7 @@ module.exports = app => {
                 const projectData = await ctx.service.project.getDataById(projectId);
                 if (projectData === null) throw '没有对应的项目数据';
                 projectData.data_collect_pages = projectData.data_collect_pages ? projectData.data_collect_pages.split(',') : [];
+                ctx.session.sessionProject.dataCollect = projectData.data_collect;
                 if (ctx.session.sessionUser.is_admin === 0) throw '没有访问权限';
                 const dataCollectAudits = await ctx.service.datacollectAudit.getList(projectId);
                 // 获取所有项目参与者
@@ -1158,7 +1158,8 @@ module.exports = app => {
                 const categoryData = await ctx.service.category.getAllCategory(ctx.session.sessionProject.id);
                 const tenders = await ctx.service.tender.getList('', null, 1);
                 const dcTenders = await ctx.service.datacollectTender.getList(projectId);
-                await this.layout('setting/datacollect.ejs', {
+                const is_dz2 = ['P0505', 'P0506', 'P1201', 'P1202', 'GY18Y'].indexOf(ctx.session.sessionProject.code) !== -1 ? 6 : false;
+                const renderData = {
                     projectData,
                     dataCollectAudits,
                     accountList,
@@ -1167,7 +1168,14 @@ module.exports = app => {
                     tenders,
                     dcTenders,
                     is_dz1: ['P0505', 'MI22U'].indexOf(ctx.session.sessionProject.code) !== -1 ? 5 : false,
-                }, 'setting/datacollect_modal.ejs');
+                    is_dz2,
+                };
+                if (is_dz2) {
+                    // 获取分类及对应值
+                    const commonJson = projectData.common_json ? JSON.parse(projectData.common_json) : null;
+                    renderData.daPing06Set = commonJson && commonJson.daPing06_set ? commonJson.daPing06_set : ctx.helper._.cloneDeep(projectSettingConst.daPing06Set);
+                }
+                await this.layout('setting/datacollect.ejs', renderData, 'setting/datacollect_modal.ejs');
             } catch (error) {
                 ctx.helper.log(error);
                 ctx.session.postError = error.toString();
@@ -1191,7 +1199,7 @@ module.exports = app => {
                     case 'show':
                         responseData.data = await ctx.service.project.update({
                             data_collect: data.data_collect,
-                            data_collect_pages: data.data_collect_pages.join(',')
+                            data_collect_pages: data.data_collect_pages.join(','),
                         }, {id: projectId});
                         ctx.session.sessionProject.dataCollect = data.data_collect;
                         ctx.session.sessionProject.showDataCollect = data.data_collect ? 1 : 0;
@@ -1256,6 +1264,9 @@ module.exports = app => {
                             addDatacollect: ctx.session.sessionProject.page_show.addDataCollect,
                         };
                         break;
+                    case 'save-dp06':
+                        responseData.data = await ctx.service.project.saveCommonJson(projectId, 'daPing06_set', data.daPing06Set);
+                        break;
                     default:
                         throw '参数有误';
                 }

+ 1 - 1
app/controller/stage_controller.js

@@ -1460,7 +1460,7 @@ module.exports = app => {
             try {
                 await this._getStageAuditViewData(ctx);
                 const renderData = await this._getDefaultRenderData(ctx);
-                [renderData.gclSpread, renderData.leafXmjSpread] = await spreadSetting.getStageGatherSpreadSetting(ctx);
+                [renderData.gclSpread, renderData.leafXmjSpread, renderData.gatherLeafXmjSpread] = await spreadSetting.getStageGatherSpreadSetting(ctx);
                 const projectFunInfo = await this.ctx.service.project.getFunRela(ctx.session.sessionProject.id);
                 renderData.hintOver = projectFunInfo.hintOver && ctx.tender.info.fun_rela.hintOver;
 

+ 3 - 1
app/controller/tender_controller.js

@@ -372,10 +372,12 @@ module.exports = app => {
                     tender.ledger_status === auditConst.ledger.status.checkNo || tender.ledger_status === auditConst.ledger.status.uncheck);
                 const stages = await ctx.service.stage.getValidStages(ctx.tender.id);
                 const lastStage = stages.length > 0 ? stages[0] : null; // await ctx.service.stage.getLastestStage(ctx.tender.id);
-                const [change_tp, change_p_tp, change_n_tp] = await ctx.service.change.getChangeTp(tender.id);
+                const [change_tp, change_p_tp, change_n_tp, change_valuation_tp, change_unvaluation_tp] = await ctx.service.change.getChangeTp(tender.id);
                 tender.change_tp = change_tp;
                 tender.change_p_tp = change_p_tp;
                 tender.change_n_tp = change_n_tp;
+                tender.change_valuation_tp = change_valuation_tp;
+                tender.change_unvaluation_tp = change_unvaluation_tp;
                 if (lastStage) {
                     await this.ctx.service.stage.checkStageGatherData(lastStage, this.ctx.session.sessionUser.is_admin);
 

+ 3 - 1
app/controller/wap_controller.js

@@ -210,10 +210,12 @@ module.exports = app => {
                     tender.total_price = sum.total_price;
                     tender.deal_tp = sum.deal_tp;
                 }
-                const [change_tp, change_p_tp, change_n_tp] = await ctx.service.change.getChangeTp(ctx.tender.id);
+                const [change_tp, change_p_tp, change_n_tp, change_valuation_tp, change_unvaluation_tp] = await ctx.service.change.getChangeTp(ctx.tender.id);
                 tender.change_tp = change_tp;
                 tender.change_p_tp = change_p_tp;
                 tender.change_n_tp = change_n_tp;
+                tender.change_valuation_tp = change_valuation_tp;
+                tender.change_unvaluation_tp = change_unvaluation_tp;
                 const stages = await ctx.service.stage.getValidStages(ctx.tender.id);
                 const lastStage = stages.length > 0 ? stages[0] : null; //await ctx.service.stage.getLastestStage(ctx.tender.id);
                 if (lastStage) {

+ 1 - 1
app/lib/revise_price.js

@@ -503,7 +503,7 @@ class revisePriceCalc {
         if (pos.length > 0) await transaction.insert(this.ctx.service.pos.tableName, pos);
 
         // 应用到未审完成期
-        const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: revise.tid }, order: ['order', 'asc'] });
+        const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: revise.tid }, orders: [['order', 'asc']] });
         const latestStage = stages[stages.length - 1];
         let pcTp;
         if (latestStage && latestStage.status !== audit.stage.status.checked) {

+ 7 - 2
app/lib/spread_setting.js

@@ -142,16 +142,21 @@ const getStageGatherSpreadSetting = async function (ctx, tid) {
     const tender = tid ? await getCtxTender(ctx, tid) : ctx.tender;
     const gcl = JSON.parse(JSON.stringify(spreadConst.stageGather.gcl));
     const leafXmj = JSON.parse(JSON.stringify(spreadConst.stageGather.leafXmj));
+    const gatherLeafXmj = JSON.parse(JSON.stringify(spreadConst.stageGather.gatherLeafXmj));
 
     // if (tender.data.measure_type === measureType.tz.value && !tender.info.display.ledger.deal)
     //     removeFieldCols(gcl, spreadConst.filterCols.dealCols);
     if (!tender.info.display.stage.priceDiff) {
         removeFieldCols(gcl, spreadConst.filterCols.priceDiffCols);
         hiddenFieldCols(leafXmj, spreadConst.filterCols.priceDiffCols);
+        hiddenFieldCols(gatherLeafXmj, spreadConst.filterCols.priceDiffCols);
     }
 
-    if (tender.data.measure_type === measureType.gcl.value) removeFieldCols(leafXmj, ['quantity']);
-    return [gcl, leafXmj];
+    if (tender.data.measure_type === measureType.gcl.value) {
+        removeFieldCols(leafXmj, ['quantity']);
+        removeFieldCols(gatherLeafXmj, ['quantity']);
+    }
+    return [gcl, leafXmj, gatherLeafXmj];
 };
 
 module.exports = {

+ 1 - 0
app/middleware/advance_check.js

@@ -34,6 +34,7 @@ module.exports = () => {
     return function* advanceCheck(next) {
         try {
             // 读取预付款id
+            const cid = this.params.cid || this.request.body.cid;
             const id = parseInt(this.params.order);
             if (!id || id <= 0) {
                 throw '您访问的预付款期不存在';

+ 4 - 4
app/middleware/change_apply_audit_check.js

@@ -47,12 +47,12 @@ module.exports = options => {
                         change.sp_group = group ? group.id : 0;
                         yield this.service.changeApply.defaultUpdate({ id: change.id, sp_group: change.sp_group });
                     }
-                    if (change.sp_group === 0) {
+                    const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
+                    yield this.service.shenpiAudit.noYbShenpiList(change.uid, shenpiList);
+                    if (change.sp_group === 0 && shenpiList.length === 0) {
                         this.tender.info.shenpi.change = shenpiConst.sp_status.sqspr;
                     } else {
-                        const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
-                        const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
-                        yield this.service.shenpiAudit.noYbShenpiList(change.uid, shenpiList);
                         // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
                         let sameAudit = auditList.length === shenpiList.length;
                         if (sameAudit) {

+ 3 - 3
app/middleware/change_audit_check.js

@@ -49,11 +49,11 @@ module.exports = options => {
                         change.sp_group = group ? group.id : 0;
                         yield this.service.change.defaultUpdate({ sp_group: change.sp_group }, { where: { cid: change.cid } });
                     }
-                    if (change.sp_group === 0) {
+                    const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
+                    if (change.sp_group === 0 && shenpiList.length === 0) {
                         this.tender.info.shenpi.change = shenpiConst.sp_status.sqspr;
                     } else {
-                        const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
-                        const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition });
                         // const shenpiIdList = _.map(shenpiList, 'audit_id');
                         // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
                         let sameAudit = auditList.length === shenpiList.length;

+ 4 - 4
app/middleware/change_plan_audit_check.js

@@ -47,12 +47,12 @@ module.exports = options => {
                         change.sp_group = group ? group.id : 0;
                         yield this.service.changePlan.defaultUpdate({ id: change.id, sp_group: change.sp_group });
                     }
-                    if (change.sp_group === 0) {
+                    const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
+                    yield this.service.shenpiAudit.noYbShenpiList(change.uid, shenpiList);
+                    if (change.sp_group === 0 && shenpiList.length === 0) {
                         this.tender.info.shenpi.change = shenpiConst.sp_status.sqspr;
                     } else {
-                        const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
-                        const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
-                        yield this.service.shenpiAudit.noYbShenpiList(change.uid, shenpiList);
                         // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
                         let sameAudit = auditList.length === shenpiList.length;
                         if (sameAudit) {

+ 4 - 4
app/middleware/change_project_audit_check.js

@@ -47,12 +47,12 @@ module.exports = options => {
                         change.sp_group = group ? group.id : 0;
                         yield this.service.changeProject.defaultUpdate({ id: change.id, sp_group: change.sp_group });
                     }
-                    if (change.sp_group === 0) {
+                    const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
+                    const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
+                    yield this.service.shenpiAudit.noYbShenpiList(change.uid, shenpiList);
+                    if (change.sp_group === 0 && shenpiList.length === 0) {
                         this.tender.info.shenpi.change = shenpiConst.sp_status.sqspr;
                     } else {
-                        const condition = { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status, sp_group: change.sp_group };
-                        const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
-                        yield this.service.shenpiAudit.noYbShenpiList(change.uid, shenpiList);
                         // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
                         let sameAudit = auditList.length === shenpiList.length;
                         if (sameAudit) {

BIN
app/public/images/juecedaping06.png


+ 8 - 1
app/public/js/advance.js

@@ -155,6 +155,10 @@ $(document).ready(function () {
                                 historyHTML += `<div class="timeline-item-icon bg-warning text-light">
                                     <i class="fa fa-level-up"></i>
                                 </div>`
+                            } else if(auditor.status === auditConst.status.checkAgain) {
+                                historyHTML += `<div class="timeline-item-icon bg-warning text-light">
+                                    <i class="fa fa-check"></i>
+                                </div>`
                             } else if(auditor.status === auditConst.status.checking) {
                                 historyHTML += `<div class="timeline-item-icon bg-warning text-light">
                                     <i class="fa fa-ellipsis-h"></i>
@@ -196,7 +200,10 @@ $(document).ready(function () {
                             historyHTML += `<div class="timeline-item-icon bg-warning text-light">
                                 <i class="fa fa-level-up"></i>
                             </div>`
-
+                        } else if(auditor.status === auditConst.status.checkAgain) {
+                            historyHTML += `<div class="timeline-item-icon bg-warning text-light">
+                                    <i class="fa fa-check"></i>
+                                </div>`
                         } else if(auditor.status === auditConst.status.checking) {
                             historyHTML += `<div class="timeline-item-icon bg-warning text-light">
                                 <i class="fa fa-ellipsis-h"></i>

+ 14 - 3
app/public/js/ledger_gather.js

@@ -66,8 +66,8 @@ $(document).ready(() => {
             return data
                 ? $('#compare-tag')[0].checked && data.compare_differ
                     ? spreadColor.gcl.calc_differ
-                    : (data.differ ? spreadColor.gcl.differ : defaultColor)
-                : defaultColor;
+                    : (data.differ ? spreadColor.gcl.differ : '#FFFFFF')
+                : '#FFFFFF';
         }
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gclSpreadSetting);
@@ -127,7 +127,6 @@ $(document).ready(() => {
             colWidth: true,
         },
     };
-    if (!isTz) gatherLeafXmjSpreadSetting.cols.splice(1, 1);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherLeafXmjSpreadSetting);
     const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
     SpreadJsObj.initSheet(gatherLeafXmjSheet, gatherLeafXmjSpreadSetting);
@@ -296,6 +295,18 @@ $(document).ready(() => {
         gatherLeafXmjSpread.refresh();
     });
 
+    // 下部设置显示相关
+    $('a', '[name=pos-tab]').click(function() {
+        const relaTab = this.getAttribute('href');
+        const optionTab = $('#optionTab').children();
+        for (const ot of optionTab) {
+            if (ot.getAttribute('rela-tab') === relaTab) {
+                $(ot).show();
+            } else {
+                $(ot).hide();
+            }
+        }
+    });
     $('[name=gather-xmj]').change(function() {
         const checkOption = $('[name=gather-xmj]:checked');
         if (checkOption.length === 0) {

+ 38 - 5
app/public/js/revise.js

@@ -16,13 +16,13 @@ const invalidFields = {
     posCalc: ['sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp'],
     posXmj: ['code'],
 };
-function getExprInfo (field) {
+function getExprInfo (field, converse = false) {
     const exprField = [
         {qty: 'sgfh_qty', expr: 'sgfh_expr'},
         {qty: 'sjcl_qty', expr: 'sjcl_expr'},
         {qty: 'qtcl_qty', expr: 'qtcl_expr'},
     ];
-    return _.find(exprField, {qty: field});
+    return converse ?  _.find(exprField, {expr: field}) : _.find(exprField, {qty: field});
 }
 function transExpr(expr) {
     return $.trim(expr).replace('\t', '').replace('=', '').replace('%', '/100');
@@ -1708,6 +1708,23 @@ $(document).ready(() => {
                         return;
                     }
                 }
+            } else if (col.field.indexOf('_expr') > 0) {
+                const exprInfo = getExprInfo(col.field, true);
+                if (!exprInfo) return;
+
+                if (newText) {
+                    try {
+                        data.postData[exprInfo.qty] = math.evaluate(transExpr(newText));
+                        data.postData[exprInfo.expr] = newText;
+                    } catch(err) {
+                        toastr.error('输入的表达式非法');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                } else {
+                    data.postData[exprInfo.qty] = 0;
+                    data.postData[exprInfo.expr] = '';
+                }
             } else {
                 data.postData[col.field] = newText;
             }
@@ -1746,10 +1763,15 @@ $(document).ready(() => {
                         const style = sheet.getStyle(iRow, iCol);
                         if (!style.locked) {
                             const colSetting = sheet.zh_setting.cols[iCol];
-                            data[colSetting.field] = null;
-                            const exprInfo = getExprInfo(colSetting.field);
-                            if (exprInfo) {
+                            if (colSetting.field.indexOf('_expr') > 0) {
+                                const exprInfo = getExprInfo(colSetting.field, true);
+                                if (!exprInfo) continue;
                                 data[exprInfo.expr] = '';
+                                data[exprInfo.qty] = 0;
+                            } else {
+                                data[colSetting.field] = null;
+                                const exprInfo = getExprInfo(colSetting.field);
+                                if (exprInfo) data[exprInfo.expr] = '';
                             }
                             bDel = true;
                         }
@@ -1901,6 +1923,17 @@ $(document).ready(() => {
                                 bPaste = false;
                             }
                         }
+                    } else if (colSetting.field.indexOf('_expr') > 0) {
+                        try {
+                            const exprInfo = getExprInfo(colSetting.field, true);
+                            posData[exprInfo.expr] = trimInvalidChar(info.sheet.getText(curRow, curCol));
+                            posData[exprInfo.qty] = math.evaluate(transExpr(posData[exprInfo.expr]));
+                            bPaste = true;
+                        } catch (err) {
+                            toastMessageUniq(hint.expr);
+                        }
+                    } else {
+                        bPaste = true;
                     }
                 }
                 if (bPaste) {

+ 74 - 0
app/public/js/revise_gcl_compare.js

@@ -106,6 +106,34 @@ $(document).ready(() => {
     SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);
     const leafXmjSheet = leafXmjSpread.getActiveSheet();
 
+    const gatherLeafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-gather-spread')[0]);
+    const gatherLeafXmjSpreadSetting = {
+        cols: [
+            {title: '单位工程', colSpan: '1', rowSpan: '1', field: 'dwgc', hAlign: 0, width: 100, formatter: '@', visible: false},
+            {title: '分部工程', colSpan: '1', rowSpan: '1', field: 'fbgc', hAlign: 0, width: 100, formatter: '@', visible: false},
+            {title: '分项工程', colSpan: '1', rowSpan: '1', field: 'fxgc', hAlign: 0, width: 100, formatter: '@', visible: false},
+            {title: '细目', colSpan: '1', rowSpan: '1', field: 'jldy', hAlign: 0, width: 100, formatter: '@', visible: false},
+            {title: '计量单元', colSpan: '1', rowSpan: '1', field: 'bwmx', hAlign: 0, width: 100, formatter: '@'},
+            {title: '修订台账', colSpan: '1', rowSpan: '1', field: 'new_quantity', hAlign: 2, width: 80, type: 'Number'},
+            {title: '原台账', colSpan: '1', rowSpan: '1', field: 'org_quantity', hAlign: 2, width: 80, type: 'Number'},
+        ],
+        emptyRows: 0,
+        headRows: 1,
+        headRowHeight: [32],
+        headColWidth: [30],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+        localCache: {
+            key: 'ledger-gather-leafXmj',
+            colWidth: true,
+        },
+    };
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherLeafXmjSpreadSetting);
+    const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
+    SpreadJsObj.initSheet(gatherLeafXmjSheet, gatherLeafXmjSpreadSetting);
+
     let gclData = [];
     // 获取项目节数据
     function loadLeafXmjData(iGclRow) {
@@ -117,11 +145,21 @@ $(document).ready(() => {
             SpreadJsObj.loadSheetData(leafXmjSheet, SpreadJsObj.DataType.Data, []);
         }
     }
+    function loadGatherLeafXmjData(iGclRow) {
+        const gcl = iGclRow ? gclData[iGclRow] : SpreadJsObj.getSelectObject(gclSheet);
+        SpreadJsObj.resetTopAndSelect(gatherLeafXmjSheet);
+        if (gcl) {
+            SpreadJsObj.loadSheetData(gatherLeafXmjSheet, SpreadJsObj.DataType.Data, gcl.gatherLeafXmjs);
+        } else {
+            SpreadJsObj.loadSheetData(gatherLeafXmjSheet, SpreadJsObj.DataType.Data, []);
+        }
+    }
     // 切换清单行,读取所属项目节数据
     gclSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
         const iNewRow = info.newSelections[0].row;
         if (!info.oldSelections || iNewRow !== info.oldSelections[0].row) {
             loadLeafXmjData(iNewRow);
+            loadGatherLeafXmjData(iNewRow);
         }
     });
 
@@ -173,8 +211,10 @@ $(document).ready(() => {
         gclCompareModel.gatherLedgerData(data.bills, data.pos, setting);
         gclCompareModel.gatherDealBills(data.dealBills);
         gclCompareModel.checkDiffer();
+        gclCompareModel.reGatherLeafXmj();
         SpreadJsObj.loadSheetData(gclSheet, SpreadJsObj.DataType.Data, gclData);
         loadLeafXmjData(0);
+        loadGatherLeafXmjData(0);
 
         const chapterData = gclCompareModel.chapterData();
         generateChapterHtml(chapterData);
@@ -196,6 +236,38 @@ $(document).ready(() => {
         }
         gclSpread.refresh();
         leafXmjSpread.refresh();
+        gatherLeafXmjSpread.refresh();
+    });
+    // 下部设置显示相关
+    $('a', '[name=pos-tab]').click(function() {
+        const relaTab = this.getAttribute('href');
+        const optionTab = $('#optionTab').children();
+        for (const ot of optionTab) {
+            if (ot.getAttribute('rela-tab') === relaTab) {
+                $(ot).show();
+            } else {
+                $(ot).hide();
+            }
+        }
+    });
+    $('[name=gather-xmj]').change(function() {
+        const checkOption = $('[name=gather-xmj]:checked');
+        if (checkOption.length === 0) {
+            toastr.warning('请至少选择一个汇总条件');
+            return;
+        }
+
+        const fields = [];
+        for (const co of checkOption) {
+            fields.push(co.value);
+        }
+        for (const col of gatherLeafXmjSpreadSetting.cols) {
+            if (col.formatter !== '@') continue;
+            col.visible = col.type === 'Number' || fields.indexOf(col.field) >= 0;
+        }
+        gclCompareModel.reGatherLeafXmj(fields);
+        SpreadJsObj.refreshColumnVisible(gatherLeafXmjSheet);
+        loadGatherLeafXmjData();
     });
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
@@ -213,6 +285,7 @@ $(document).ready(() => {
             autoFlashHeight();
             gclSpread.refresh();
             leafXmjSpread.refresh();
+            gatherLeafXmjSpread.refresh();
         }
     });
     $.divResizer({
@@ -222,6 +295,7 @@ $(document).ready(() => {
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
             $(".sp-wrap").height(bcontent-30);
             leafXmjSpread.refresh();
+            gatherLeafXmjSpread.refresh();
         }
     });
     $('input[name=compareTag]').change(() => {

+ 38 - 1
app/public/js/shares/gcl_gather_compare.js

@@ -498,9 +498,46 @@ const gclCompareModel = (function () {
         return gclChapter.concat([otherChapter.qd, otherChapter.fqd, otherChapter.zlj, otherChapter.hj]);
     }
 
+    function _gatherLeafXmj(gcl, fields = ['bwmx']) {
+        gcl.gatherLeafXmjs = [];
+        for (const lx of gcl.leafXmjs) {
+            const condition = {};
+            for (const f of fields) {
+                condition[f] = lx[f];
+            }
+            let glx = _.find(gcl.gatherLeafXmjs, condition);
+            if (!glx) {
+                glx = JSON.parse(JSON.stringify(lx));
+                gcl.gatherLeafXmjs.push(glx);
+            } else {
+                gatherfields(glx, lx, ['new_quantity', 'org_quantity']);
+            }
+        }
+        for (const xmj of gcl.gatherLeafXmjs) {
+            xmj.pre_gather_qty = ZhCalc.add(xmj.pre_contract_qty, xmj.pre_qc_qty);
+            xmj.gather_qty = ZhCalc.add(xmj.contract_qty, xmj.qc_qty);
+            xmj.end_contract_qty = ZhCalc.add(xmj.pre_contract_qty, xmj.contract_qty);
+            xmj.end_qc_qty = ZhCalc.add(xmj.pre_qc_qty, xmj.qc_qty);
+            xmj.end_gather_qty = ZhCalc.add(xmj.pre_gather_qty, xmj.gather_qty);
+            xmj.end_final_qty = ZhCalc.add(xmj.end_qc_qty, xmj.quantity);
+            xmj.end_qc_minus_qty = ZhCalc.add(xmj.pre_qc_minus_qty, xmj.qc_minus_qty);
+            xmj.final_1_qty = ZhCalc.add(xmj.quantity, xmj.end_qc_minus_qty);
+            xmj.end_final_1_qty = ZhCalc.add(xmj.final_1_qty, xmj.end_qc_qty);
+            xmj.end_gather_percent = ZhCalc.mul(ZhCalc.div(xmj.end_gather_qty, xmj.end_final_qty), 100, 2);
+            xmj.end_final_1_percent = ZhCalc.mul(ZhCalc.div(xmj.end_gather_qty, xmj.end_final_1_qty), 100, 2);
+        }
+    }
+
+    function reGatherLeafXmj(fields) {
+        gclList.forEach(g => {
+            _gatherLeafXmj(g, fields);
+        });
+    }
+
     return {
         init,
         gatherLedgerData, gatherReviseLedgerData, gatherDealBills, checkDiffer,
-        chapterData
+        chapterData,
+        reGatherLeafXmj,
     };
 })();

+ 48 - 0
app/public/js/stage_gather.js

@@ -70,6 +70,11 @@ $(document).ready(function () {
     if (thousandth) sjsSettingObj.setTpThousandthFormat(leafXmjSpreadSetting);
     SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);
 
+    const gatherLeafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-gather-spread')[0]);
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherLeafXmjSpreadSetting);
+    const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
+    SpreadJsObj.initSheet(gatherLeafXmjSheet, gatherLeafXmjSpreadSetting);
+
     let gclGatherData;
     // 获取项目节数据
     function loadLeafXmjData(iGclRow) {
@@ -81,6 +86,15 @@ $(document).ready(function () {
             SpreadJsObj.loadSheetData(leafXmjSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
         }
     }
+    function loadGatherLeafXmjData(iGclRow) {
+        const gcl = iGclRow ? gclGatherData[iGclRow] : SpreadJsObj.getSelectObject(gclSheet);
+        SpreadJsObj.resetTopAndSelect(gatherLeafXmjSheet);
+        if (gcl) {
+            SpreadJsObj.loadSheetData(gatherLeafXmjSheet, SpreadJsObj.DataType.Data, gcl.gatherLeafXmjs);
+        } else {
+            SpreadJsObj.loadSheetData(gatherLeafXmjSheet, SpreadJsObj.DataType.Data, []);
+        }
+    }
     // 超计显示
     function checkOverRange(data) {
         const billsGatherOver = function (data, qtyField, tpField, per) {
@@ -112,6 +126,7 @@ $(document).ready(function () {
         const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
         if (iNewRow !== iOldRow) {
             loadLeafXmjData(iNewRow);
+            loadGatherLeafXmjData(iNewRow);
         }
     });
     $('.custom-radio').click(() => {
@@ -137,10 +152,12 @@ $(document).ready(function () {
         gclGatherModel.loadChangeBillsData(result.changeBills);
         gclGatherData = gclGatherModel.gatherGclData();
         gclGatherModel.checkDiffer(gclGatherData);
+        gclGatherModel.reGatherLeafXmj();
         checkOverRange(gclGatherData);
         // 加载清单数据
         SpreadJsObj.loadSheetData(gclSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gclGatherData);
         loadLeafXmjData(0);
+        loadGatherLeafXmjData(0);
         // 章节合计
         const chapterData = gclGatherModel.gatherChapterData(chapter, result.spec, ['total_price', 'contract_tp', 'qc_tp', 'pre_contract_tp', 'pre_qc_tp', 'contract_pc_tp', 'qc_pc_tp', 'pc_tp']);
         for (const c of chapterData) {
@@ -193,8 +210,38 @@ $(document).ready(function () {
         }
         gclSpread.refresh();
         leafXmjSpread.refresh();
+        gatherLeafXmjSpread.refresh();
     });
+    // 下部设置显示相关
+    $('a', '[name=pos-tab]').click(function() {
+        const relaTab = this.getAttribute('href');
+        const optionTab = $('#optionTab').children();
+        for (const ot of optionTab) {
+            if (ot.getAttribute('rela-tab') === relaTab) {
+                $(ot).show();
+            } else {
+                $(ot).hide();
+            }
+        }
+    });
+    $('[name=gather-xmj]').change(function() {
+        const checkOption = $('[name=gather-xmj]:checked');
+        if (checkOption.length === 0) {
+            toastr.warning('请至少选择一个汇总条件');
+            return;
+        }
 
+        const fields = [];
+        for (const co of checkOption) {
+            fields.push(co.value);
+        }
+        for (const col of gatherLeafXmjSpreadSetting.cols) {
+            col.visible = col.type === 'Number' || fields.indexOf(col.field) >= 0;
+        }
+        gclGatherModel.reGatherLeafXmj(fields);
+        SpreadJsObj.refreshColumnVisible(gatherLeafXmjSheet);
+        loadGatherLeafXmjData();
+    });
     // 上下窗口resizer
     $.divResizer({
         select: '#main-resize',
@@ -229,6 +276,7 @@ $(document).ready(function () {
             autoFlashHeight();
             gclSpread.refresh();
             leafXmjSpread.refresh();
+            gatherLeafXmjSpread.refresh();
         }
     });
     $('#exportExcel').click(function () {

+ 2 - 0
app/router.js

@@ -222,6 +222,7 @@ module.exports = app => {
     app.get('/tender/:id/advance/:order/file/:fid/download', sessionAuth, tenderCheck, 'advanceController.downloadFile');
     app.post('/tender/:id/advance/:order/file/del', sessionAuth, tenderCheck, advanceCheck, 'advanceController.deleteFile');
     app.post('/tender/:id/advance/:type/:order/auditors', sessionAuth, tenderCheck, advanceCheck, 'advanceController.getAuditors');
+    app.post('/tender/:id/advance/:order/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, advanceCheck, 'advanceController.checkAgain');
 
     // 标段协作办公
     app.get('/tender/:id/cooperation', sessionAuth, tenderCheck, 'tenderController.tenderCooperation');
@@ -793,6 +794,7 @@ module.exports = app => {
 
     // 决策大屏
     app.get('/datacollect', sessionAuth, 'datacollectController.index');
+    app.get('/datacollect/index/:index', sessionAuth, 'datacollectController.index');
     app.post('/datacollect/load', sessionAuth, 'datacollectController.loadData');
 
     app.get('/subproj', sessionAuth, 'subProjController.index');

+ 60 - 1
app/service/advance_audit.js

@@ -175,7 +175,7 @@ module.exports = app => {
          */
         async getAuditors(vid, times = 1) {
             const sql =
-                'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`create_time`, la.`end_time`, g.`sort` ' +
+                'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`type`, la.`order`, la.`status`, la.`opinion`, la.`create_time`, la.`end_time`, g.`sort` ' +
                 'FROM ?? AS la, ?? AS pa, (SELECT t1.`audit_id`,(@i:=@i+1) as `sort` FROM (SELECT t.`audit_id`, t.`order` FROM (select `audit_id`, `order` from ?? WHERE `vid` = ? AND `times` = ? ORDER BY `order` LIMIT 200) t GROUP BY t.`audit_id` ORDER BY t.`order`) t1, (select @i:=0) as it) as g ' +
                 'WHERE la.`vid` = ? and la.`times` = ? and la.`audit_id` = pa.`id` and g.`audit_id` = la.`audit_id` order by la.`order`';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.tableName, vid, times, vid, times];
@@ -530,6 +530,65 @@ module.exports = app => {
         }
 
         /**
+         * 重新审批
+         * @param { string } cid - 查询的清单
+         * @return {Promise<*>} - 可用的变更令列表
+         */
+        async checkAgain(advance) {
+            const accountId = this.ctx.session.sessionUser.accountId;
+            // 初始化事务
+            const time = new Date();
+            const transaction = await this.db.beginTransaction();
+            let result = false;
+            try {
+                const maxOrder = advance.auditors[advance.auditors.length - 1].order;
+                const audits = advance.auditors.filter(x => { return x.order === maxOrder; });
+                if (!audits || audits.length === 0 || maxOrder < 1) throw '审核数据错误';
+                const selfAudit = audits.find(x => { return x.audit_id === accountId; });
+                if (!selfAudit) throw '当前标段您无权审批';
+                // 当前审批人2次添加至流程中
+                const checkAgainAuditors = [];
+                audits.forEach(x => {
+                    checkAgainAuditors.push({
+                        tid: advance.tid, vid: advance.id, audit_id: x.audit_id, type: x.type,
+                        times: x.times, order: maxOrder + 1,
+                        status: auditConst.status.checkAgain,
+                        create_time: time, end_time: time, opinion: '',
+                    });
+                });
+                const checkingAuditors = [];
+                audits.forEach(x => {
+                    checkingAuditors.push({
+                        tid: advance.tid, vid: advance.id, audit_id: x.audit_id, type: x.type,
+                        times: x.times, order: maxOrder + 2,
+                        status: auditConst.status.checking,
+                        create_time: time,
+                    });
+                });
+                await transaction.insert(this.tableName, checkAgainAuditors);
+                const checkingAuditors_result = await transaction.insert(this.tableName, checkingAuditors);
+                // 获取刚批量添加的所有list
+                // for (let j = 0; j < checkingAuditors.length; j++) {
+                //     checkingAuditors[j].id = checkingAuditors_result.insertId + j;
+                // }
+
+                // 设置审批中
+                await transaction.update(this.ctx.service.advance.tableName, {
+                    id: advance.id,
+                    status: auditConst.status.checking,
+                    end_time: null,
+                });
+                await transaction.commit();
+                result = true;
+            } catch (error) {
+                console.log(error);
+                await transaction.rollback();
+                result = false;
+            }
+            return result;
+        }
+
+        /**
          * 用于添加推送所需的content内容
          * @param {Number} pid 项目id
          * @param {Number} tid 台账id

+ 14 - 3
app/service/change.js

@@ -593,10 +593,10 @@ module.exports = app => {
          * @return {void}
          */
         async getChangeTp(tenderId) {
-            const sql = 'SELECT SUM(`total_price`) AS tp, SUM(`positive_tp`) AS p_tp, SUM(`negative_tp`) AS n_tp FROM ?? WHERE tid = ? AND status = ?';
+            const sql = 'SELECT SUM(`total_price`) AS tp, SUM(`positive_tp`) AS p_tp, SUM(`negative_tp`) AS n_tp, SUM(`valuation_tp`) AS v_tp, SUM(`unvaluation_tp`) AS uv_tp FROM ?? WHERE tid = ? AND status = ?';
             const sqlParam = [this.tableName, tenderId, audit.change.status.checked];
             const result = await this.db.queryOne(sql, sqlParam);
-            return result ? [result.tp, result.p_tp, result.n_tp] : [0, 0, 0];
+            return result ? [result.tp, result.p_tp, result.n_tp, result.v_tp, result.uv_tp] : [0, 0, 0, 0, 0];
         }
 
         /**
@@ -948,6 +948,8 @@ module.exports = app => {
                     // 清单数据更新
                     const bills_list = await this.ctx.service.changeAuditList.getList(changeData.cid, changeData.order_by);
                     let total_price = 0;
+                    let valuation_tp = 0;
+                    let unvaluation_tp = 0;
                     const tp_decimal = changeData.tp_decimal ? changeData.tp_decimal : this.ctx.tender.info.decimal.tp;
                     const updateList = [];
                     for (const bl of bills_list) {
@@ -962,6 +964,9 @@ module.exports = app => {
                             list_update.samount = bl.spamount;
                             list_update.checked_amount = bl.spamount;
                             list_update.checked_price = this.ctx.helper.mul(bl.unit_price, list_update.checked_amount, tp_decimal);
+                            // 统计计价和不计价金额
+                            valuation_tp = bl.is_valuation ? this.ctx.helper.add(valuation_tp, list_update.checked_price) : valuation_tp;
+                            unvaluation_tp = !bl.is_valuation ? this.ctx.helper.add(unvaluation_tp, list_update.checked_price) : unvaluation_tp;
                         }
                         updateList.push(list_update);
                     }
@@ -1040,9 +1045,11 @@ module.exports = app => {
                         }
                     }
                     change_update.total_price = total_price;
+                    change_update.valuation_tp = valuation_tp;
+                    change_update.unvaluation_tp = unvaluation_tp;
                     const options = {
                         where: {
-                            cid: postData.change_id,
+                            cid: changeData.cid,
                         },
                     };
                     await this.transaction.update(this.tableName, change_update, options);
@@ -1631,6 +1638,8 @@ module.exports = app => {
                     up_decimal: null,
                     is_revise: 1,
                     final_auditor_str: '',
+                    valuation_tp: 0,
+                    unvaluation_tp: 0,
                 };
                 const options = {
                     where: {
@@ -1799,6 +1808,8 @@ module.exports = app => {
                     sin_time: null,
                     total_price,
                     final_auditor_str: '',
+                    valuation_tp: 0,
+                    unvaluation_tp: 0,
                 };
                 const options = {
                     where: {

+ 12 - 0
app/service/project.js

@@ -295,6 +295,18 @@ module.exports = app => {
             const result = await this.db.update(this.tableName, updateData);
             return result.affectedRows === 1;
         }
+
+        async saveCommonJson(id, field, datas) {
+            const projectData = await this.getDataById(id);
+            projectData.common_json = projectData.common_json ? JSON.parse(projectData.common_json) : {};
+            const updateData = {
+                id,
+            };
+            projectData.common_json[field] = datas;
+            updateData.common_json = JSON.stringify(projectData.common_json);
+            const result = await this.db.update(this.tableName, updateData);
+            return result.affectedRows === 1;
+        }
     }
 
     return Project;

+ 3 - 1
app/service/stage.js

@@ -922,7 +922,7 @@ module.exports = app => {
 
         async getStageByDataCollect(tenderId, stage_tp) {
             const allStages = await this.db.select(this.tableName, {
-                columns: ['id', 'user_id', 'times', 'status', 's_time', 'contract_tp', 'qc_tp', 'pc_tp', 'pre_contract_tp', 'pre_qc_tp', 'tp_history'],
+                columns: ['id', 'user_id', 'times', 'status', 's_time', 'contract_tp', 'qc_tp', 'pc_tp', 'pre_contract_tp', 'pre_qc_tp', 'pre_yf_tp', 'yf_tp', 'pre_sf_tp', 'sf_tp', 'tp_history'],
                 where: { tid: tenderId },
                 orders: [['order', 'desc']],
             });
@@ -946,6 +946,8 @@ module.exports = app => {
                 s.tp = this.ctx.helper.sum([s.contract_tp, s.qc_tp, s.pc_tp]);
                 s.pre_tp = this.ctx.helper.add(s.pre_contract_tp, s.pre_qc_tp);
                 s.end_tp = this.ctx.helper.add(s.pre_tp, s.tp);
+                s.end_yf_tp = this.ctx.helper.add(s.pre_yf_tp, s.yf_tp);
+                s.end_sf_tp = this.ctx.helper.add(s.pre_sf_tp, s.sf_tp);
             }
             return stages;
         }

+ 4 - 0
app/view/advance/audit_btn.ejs

@@ -14,6 +14,10 @@
     <% } %>
 <% } else if (ctx.advance.status === auditConst.status.checked) { %>
     <a href="#sp-list" data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm sp-list-btn">审批完成</a>
+    <% if (ctx.advance.finalAuditorId && ctx.advance.finalAuditorId === ctx.session.sessionUser.accountId) { %>
+        <!--重新审批-->
+        <a href="#sp-down-back" data-toggle="modal" data-target="#sp-down-back" class="btn btn-warning btn-sm ml-2">重新审批</a>
+    <% } %>
 <% } else if (ctx.advance.status === auditConst.status.checkNo) { %>
     <a href="#sp-list" data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted sp-list-btn">审批退回</a>
     <% if (ctx.session.sessionUser.accountId === ctx.advance.uid) { %>

+ 8 - 0
app/view/advance/detail.ejs

@@ -266,6 +266,10 @@
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-level-up"></i>
                                                     </div>
+                                                    <% } else if(auditor.status === auditConst.status.checkAgain) {%>
+                                                        <div class="timeline-item-icon bg-warning text-light">
+                                                            <i class="fa fa-check"></i>
+                                                        </div>
                                                     <% } else if(auditor.status === auditConst.status.checking) { %>
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-ellipsis-h"></i>
@@ -310,6 +314,10 @@
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-level-up"></i>
                                                     </div>
+                                                    <% } else if(auditor.status === auditConst.status.checkAgain) {%>
+                                                        <div class="timeline-item-icon bg-warning text-light">
+                                                            <i class="fa fa-check"></i>
+                                                        </div>
                                                     <% } else if(auditor.status === auditConst.status.checking) { %>
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-ellipsis-h"></i>

+ 144 - 0
app/view/advance/modal_audit.ejs

@@ -643,7 +643,151 @@
         </div>
     <% } %>
 <% } %>
+<% if (ctx.advance.finalAuditorId && ctx.advance.finalAuditorId === ctx.session.sessionUser.accountId) { %>
+    <% if (!authMobile && ctx.session.sessionUser.loginStatus === 0) { %>
+        <!--终审重新审批-->
+        <div class="modal fade" id="sp-down-back" data-backdrop="static">
+            <div class="modal-dialog" role="document">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h5 class="modal-title">重新审批</h5>
+                    </div>
+                    <div class="modal-body">
+                        <h5>重新审批需要您的手机短信验证</h5>
+                        <h5>您目前还没设置认证手机,请先设置。</h5>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                        <a href="/profile/sms" class="btn btn-sm btn-primary">去设置</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    <% } else { %>
+        <!--重新审批-->
+        <div class="modal fade" id="sp-down-back" data-backdrop="static">
+            <div class="modal-dialog" role="document">
+                <form id="againForm" class="modal-content" method="post" action="/tender/<%- ctx.tender.id %>/advance/<%- advance.id %>/check/again" onsubmit="return false;">
+                    <div class="modal-header">
+                        <h5 class="modal-title">重新审批</h5>
+                    </div>
+                    <div class="modal-body">
+                        <h5>确认由「终审」重新审批「第<%= advance.order %>期」?</h5>
+                        <% if (ctx.session.sessionUser.loginStatus === 0) { %>
+                            <div class="form-group">
+                                <label>重审需要验证码确认,验证码将发送至尾号<%- authMobile.slice(-4) %>的手机</label>
+                                <div class="input-group input-group-sm mb-3">
+                                    <input class="form-control" type="text" readonly="readonly" name="code" placeholder="输入短信中的6位验证码" />
+                                    <div class="input-group-append">
+                                        <button class="btn btn-outline-secondary get-code" type="button">获取验证码</button>
+                                    </div>
+                                </div>
+                            </div>
+                        <% } %>
+                    </div>
+                    <div class="modal-footer">
+                        <input type="hidden" name="vid" value="<%= advance.id %>">
+                        <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                        <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                        <button type="button" id="re-shenpi-btn" class="btn btn-warning btn-sm" <% if (ctx.session.sessionUser.loginStatus === 0) { %>disabled<% } %>>确定重审</button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    <% } %>
+<script>
+    const csrf = '<%= ctx.csrf %>';
+    const authMobile = '<%= authMobile %>';
+    $(function () {
+        $('#re-shenpi-btn').click(function () {
+            const data = {
+            };
+            <% if (ctx.session.sessionUser.loginStatus === 0) { %>
+            const code = $("#againForm input[name='code']").val();
+            if ($(this).hasClass('disabled')) {
+                return false;
+            }
+            if (code.length < 6) {
+                // alert('请填写正确的验证码');
+                toastr.error('请填写正确的验证码');
+                return false;
+            }
+            data.code = code;
+            <% } %>
+            $.ajax({
+                url: '/tender/<%- ctx.tender.id %>/advance/<%- advance.id %>/check/again?_csrf_j=' + csrf,
+                type: 'post',
+                data: data,
+                dataTye: 'json',
+                success: function(response) {
+                    if (response.err === 0) {
+                        window.location.href = response.url;
+                    } else {
+                        toastr.error(response.msg);
+                    }
+                }
+            });
+        });
+        // 重新审批获取手机验证码
+        // 获取验证码
+        let isPosting = false;
+        $(".get-code").on('click', function() {
+            if (isPosting) {
+                return false;
+            }
+            const btn = $(this);
+
+            $.ajax({
+                url: '/profile/code?_csrf_j=' + csrf,
+                type: 'post',
+                data: { mobile: authMobile, type: 'shenpi' },
+                dataTye: 'json',
+                error: function() {
+                    isPosting = false;
+                },
+                beforeSend: function() {
+                    isPosting = true;
+                },
+                success: function(response) {
+                    isPosting = false;
+                    if (response.err === 0) {
+                        codeSuccess(btn);
+                        $("input[name='code']").removeAttr('readonly');
+                        $("#re-shenpi-btn").removeAttr('disabled');
+                    } else {
+                        toastr.error(response.msg);
+                    }
+                }
+            });
+        });
+    });
+    /**
+     * 获取成功后的操作
+     *
+     * @param {Object} btn - 点击的按钮
+     * @return {void}
+     */
+    function codeSuccess(btn) {
+        let counter = 60;
+        btn.addClass('disabled').text('重新获取 ' + counter + 'S');
+        btn.parent().siblings('input').removeAttr('readonly').attr('placeholder', '输入短信中的6位验证码');
+        const bindBtn = $("#bind-btn");
+        bindBtn.removeClass('btn-secondary disabled').addClass('btn-primary');
 
+        const countDown = setInterval(function() {
+            const countString = counter - 1 <= 0 ? '' : ' ' + (counter - 1) + 'S';
+            // 倒数结束后
+            if (countString === '') {
+                clearInterval(countDown);
+                btn.removeClass('disabled');
+            }
+            const text = '重新获取' + countString;
+            btn.text(text);
+            counter -= 1;
+        }, 1000);
+    }
+</script>
+<% } %>
 <script>
     $('.sp-list-btn').click(function () {
         const type = $(this).data('type')

+ 5 - 1
app/view/datacollect/index.ejs

@@ -43,7 +43,11 @@
                     <button type="button" class="btn btn-sm btn-outline-dark text-white dropdown-toggle" data-toggle="dropdown" id="zhankai">决策大屏<span><%- ctx.session.sessionProject.dataCollect %></span></button>
                     <div class="dropdown-menu" aria-labelledby="zhankai">
                         <% for (const i of projectData.data_collect_pages) { %>
-                        <a class="dropdown-item change-collect" href="javascript:void(0)" data-collect="<%- i %>">决策大屏<%- i %></a>
+                        <% if (i === '6') { %>
+                            <a class="dropdown-item" href="/datacollect/index/<%- i %>">决策大屏<%- i %></a>
+                        <% } else { %>
+                            <a class="dropdown-item change-collect" href="javascript:void(0)" data-collect="<%- i %>">决策大屏<%- i %></a>
+                        <% } %>
                         <% } %>
                     </div>
                 </div>

File diff suppressed because it is too large
+ 1228 - 0
app/view/datacollect/index4GY18Y.ejs


+ 26 - 24
app/view/ledger/gather.ejs

@@ -25,36 +25,38 @@
                 <div class="bcontent-wrap" id="main-bottom">
                     <div id="main-resize" class="resize-y" r-Type="height" div1="#gcl-spread" div2="#main-bottom" store-id="ledger-gather" store-version="1.0.0" min="100"></div>
                     <div class="bc-bar mb-1">
-                        <ul class="nav nav-tabs">
+                        <ul class="nav nav-tabs" name="pos-tab">
                             <li class="nav-item">
                                 <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">所属项目节</a>
                             </li>
                             <li class="nav-item">
                                 <a class="nav-link" data-toggle="tab" href="#xmjGather" role="tab">项目节汇总</a>
                             </li>
-                            <li class="nav-item">
-                                <div class="d-inline-block ml-2 mt-1">
-                                    <span>汇总条件:</span>
-                                    <div class="d-inline-block" style="vertical-align: middle">
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input pt-1" type="checkbox" id="gather-xmj-dwgc" value="dwgc" name="gather-xmj">
-                                            <label class="form-check-label" for="gather-xmj-dwgc">单位工程</label>
-                                        </div>
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input" type="checkbox" id="gather-xmj-fbgc" value="fbgc" name="gather-xmj">
-                                            <label class="form-check-label" for="gather-xmj-fbgc">分部工程</label>
-                                        </div>
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input" type="checkbox" id="gather-xmj-fxgc" value="fxgc" name="gather-xmj">
-                                            <label class="form-check-label" for="gather-xmj-fxgc">分项工程</label>
-                                        </div>
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input" type="checkbox" id="gather-xmj-xm" value="jldy" name="gather-xmj">
-                                            <label class="form-check-label" for="gather-xmj-xm">细目</label>
-                                        </div>
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input" type="checkbox" id="gather-xmj-jldy" value="bwmx" checked name="gather-xmj">
-                                            <label class="form-check-label" for="gather-xmj-jldy">计量单元</label>
+                            <li class="nav-item" id="optionTab">
+                                <div rela-tab="#xmjGather" style="display: none;">
+                                    <div class="d-inline-block ml-2 mt-1">
+                                        <span>汇总条件:</span>
+                                        <div class="d-inline-block" style="vertical-align: middle">
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input pt-1" type="checkbox" id="gather-xmj-dwgc" value="dwgc" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-dwgc">单位工程</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-fbgc" value="fbgc" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-fbgc">分部工程</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-fxgc" value="fxgc" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-fxgc">分项工程</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-xm" value="jldy" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-xm">细目</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-jldy" value="bwmx" checked name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-jldy">计量单元</label>
+                                            </div>
                                         </div>
                                     </div>
                                 </div>

+ 37 - 1
app/view/revise/gcl_compare.ejs

@@ -33,10 +33,42 @@
                 <div class="bcontent-wrap" id="main-bottom">
                     <div id="main-resize" class="resize-y" r-Type="height" div1="#gcl-spread" div2="#main-bottom" store-id="ledger-gather" store-version="1.0.0" min="100"></div>
                     <div class="bc-bar mb-1">
-                        <ul class="nav nav-tabs">
+                        <ul class="nav nav-tabs" name="pos-tab">
                             <li class="nav-item">
                                 <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">所属项目节</a>
                             </li>
+                            <li class="nav-item">
+                                <a class="nav-link" data-toggle="tab" href="#xmjGather" role="tab">项目节汇总</a>
+                            </li>
+                            <li class="nav-item" id="optionTab">
+                                <div rela-tab="#xmjGather" style="display: none;">
+                                    <div class="d-inline-block ml-2 mt-1">
+                                        <span>汇总条件:</span>
+                                        <div class="d-inline-block" style="vertical-align: middle">
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input pt-1" type="checkbox" id="gather-xmj-dwgc" value="dwgc" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-dwgc">单位工程</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-fbgc" value="fbgc" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-fbgc">分部工程</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-fxgc" value="fxgc" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-fxgc">分项工程</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-xm" value="jldy" name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-xm">细目</label>
+                                            </div>
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="gather-xmj-jldy" value="bwmx" checked name="gather-xmj">
+                                                <label class="form-check-label" for="gather-xmj-jldy">计量单元</label>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </li>
                         </ul>
                     </div>
                     <div class="tab-content">
@@ -44,6 +76,10 @@
                             <div class="sp-wrap" id="leaf-xmj-spread">
                             </div>
                         </div>
+                        <div class="tab-pane active" id="xmjGather">
+                            <div class="sp-wrap" id="leaf-xmj-gather-spread">
+                            </div>
+                        </div>
                     </div>
                 </div>
             </div>

+ 20 - 1
app/view/setting/datacollect.ejs

@@ -20,6 +20,10 @@
                         <a class="nav-item nav-link<% if (ctx.session.sessionProject.dataCollect === is_dz1) { %> active<% } %>" data-datacollect="<%- is_dz1 %>" data-toggle="tab" href="#shujudaping-<%- is_dz1 %>" role="tab">
                             决策大屏<%- ctx.helper.transFormToChinese(is_dz1) %><% if (ctx.helper._.indexOf(projectData.data_collect_pages, is_dz1.toString()) !== -1) { %>(已开启<% if (ctx.session.sessionProject.dataCollect === is_dz1) { %>、默认<% } %>)<% } %></a>
                     <% } %>
+                    <% if (is_dz2) { %>
+                        <a class="nav-item nav-link<% if (ctx.session.sessionProject.dataCollect === is_dz2) { %> active<% } %>" data-datacollect="<%- is_dz2 %>" data-toggle="tab" href="#shujudaping-<%- is_dz2 %>" role="tab">
+                            决策大屏<%- ctx.helper.transFormToChinese(is_dz2) %><% if (ctx.helper._.indexOf(projectData.data_collect_pages, is_dz2.toString()) !== -1) { %>(已开启<% if (ctx.session.sessionProject.dataCollect === is_dz2) { %>、默认<% } %>)<% } %></a>
+                    <% } %>
                     <div class="ml-auto">
                         <!--<div class="form-check form-check-inline">-->
                             <!--<input class="form-check-input" type="checkbox" id="show-datacollect" value="option1" <% if (ctx.session.sessionProject.dataCollect) { %>checked<% } %>>-->
@@ -44,7 +48,14 @@
                         <div id="shujudaping-<%- i %>" class="tab-pane<% if ((ctx.session.sessionProject.dataCollect === 0 && i === 1) || ctx.session.sessionProject.dataCollect === i) { %> active<% } %>"><img src="/public/images/juecedaping0<%- i %>.png" width="100%"></div>
                     <% } %>
                     <% if (is_dz1) { %>
-                        <div id="shujudaping-<%- is_dz1 %>" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === is_dz1) { %> active<% } %>"><img src="/public/images/juecedaping0<%- is_dz1 %>.png" width="100%"></div>
+                        <div id="shujudaping-<%- is_dz1 %>" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === is_dz1) { %> active<% } %>">
+                            山东济邹项目定制(MI22U)<img src="/public/images/juecedaping0<%- is_dz1 %>.png" width="100%">
+                        </div>
+                    <% } %>
+                    <% if (is_dz2) { %>
+                        <div id="shujudaping-<%- is_dz2 %>" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === is_dz2) { %> active<% } %>">
+                            <span>四川广元路桥集团计量内控管理云平台定制(GY18Y)</span><a class="nav-link" style="display: inline-block;" data-toggle="modal" href="#dpsix-set" data-target="#dpsix-set" title="决策大屏六设置"><i class="fa fa-cog"></i></a><img src="/public/images/juecedaping0<%- is_dz2 %>.png" width="100%">
+                        </div>
                     <% } %>
                 </div>
             </div>
@@ -63,6 +74,7 @@
     let dcTenders = JSON.parse(unescape('<%- escape(JSON.stringify(dcTenders)) %>'));
     let addDataCollect = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.session.sessionProject.page_show.addDataCollect)) %>'));
     let is_dz1 = <% if (is_dz1) { %>parseInt('<%- is_dz1 %>');<% } else { %>false;<% } %>
+    let is_dz2 = <% if (is_dz2) { %>parseInt('<%- is_dz2 %>');<% } else { %>false;<% } %>
     $(function () {
         autoFlashHeight();
         // 开启及关闭展示
@@ -132,6 +144,13 @@
                 }
                 $('#tablist a').eq(is_dz1-3).text('决策大屏' + transFormToChinese(is_dz1) + msg);
             }
+            if (is_dz2) {
+                let msg = '';
+                if (_.indexOf(dataCollectPages, is_dz2.toString()) !== -1) {
+                    msg = '(已开启' + (is_dz2=== dataCollect ? '、默认' : '') + ')' ;
+                }
+                $('#tablist a').eq(is_dz2-3).text('决策大屏' + transFormToChinese(is_dz2) + msg);
+            }
         }
         $('#tablist a').click(function () {
             const page = parseInt($(this).data('datacollect'));

+ 151 - 0
app/view/setting/datacollect_modal.ejs

@@ -118,6 +118,157 @@
         </div>
     </div>
 </div>
+<% if (is_dz2) { %>
+<!--决策大屏六设置-->
+<div class="modal fade" id="dpsix-set" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">数据统计设置</h5>
+            </div>
+            <div class="modal-body">
+                <ul class="list-unstyled">
+                    <li class="d-flex justify-content-start align-items-center mb-3">
+                        <span class="col-auto">工程收入:</span>
+                        <span class="mr-2">
+                            <select class="form-control form-control-sm" id="sr_cate_select">
+                                <option value="0">请选择分类</option>
+                                <% for (const c of categoryData) { %>
+                                    <option value="<%- c.id %>"><%- c.name %></option>
+                                <% } %>
+                            </select>
+                          </span>
+                        <span>
+                            <select class="form-control form-control-sm" id="sr_cate_value_select">
+                                <option value="0">请选择值</option>
+                            </select>
+                          </span>
+                    </li>
+                    <li class="d-flex justify-content-start align-items-center mb-3">
+                        <span class="col-auto">工程成本:</span>
+                        <span class="mr-2">
+                            <select class="form-control form-control-sm" id="cb_cate_select">
+                                <option value="0">请选择分类</option>
+                                <% for (const c of categoryData) { %>
+                                    <option value="<%- c.id %>"><%- c.name %></option>
+                                <% } %>
+                            </select>
+                          </span>
+                        <span>
+                            <select class="form-control form-control-sm" id="cb_cate_value_select">
+                                <option value="0">请选择值</option>
+                            </select>
+                          </span>
+                    </li>
+                    <li class="d-flex justify-content-start align-items-center mb-3">
+                        <span class="col-auto">工程成本费用分类(最多只能选择4个,界面只有4个):</span>
+                        <span class="mr-2">
+                            <div class="dropdown show">
+                                <button class="btn btn-sm  dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">请选择值</button>
+                                <div class="dropdown-menu pb-1" aria-labelledby="dropdownMenuButton" x-placement="bottom-start" >
+                                    <div class="px-3" id="cb_show_select">
+                                        <% const xmgl = categoryData.find(item => item.name === '管理类别'); %>
+                                        <% if (xmgl && xmgl.value && xmgl.value.length !== 0) { %>
+                                        <% for (const v of xmgl.value) { %>
+                                        <div class="form-check py-1">
+                                            <input class="form-check-input" type="checkbox" id="xmgl_value_<%- v.id %>" value="<%- v.id %>">
+                                            <label class="form-check-label" for="xmgl_value_<%- v.id %>"><%- v.value %></label>
+                                        </div>
+                                        <% } %>
+                                        <% } %>
+                                    </div>
+                                </div>
+                            </div>
+                        </span>
+                    </li>
+                </ul>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-primary" id="dp06_save_btn">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const daPing06Set = JSON.parse(unescape('<%- escape(JSON.stringify(daPing06Set)) %>'));
+    $(function () {
+        $('#sr_cate_select').change(function () {
+            const val = $(this).val()
+            const cate = category.find(item => item.id === parseInt(val))
+            $('#sr_cate_value_select').html(cate ? cate.value.map(item => `<option value="${item.id}">${item.value}</option>`).join('') : '<option value="0">请选择值</option>');
+        })
+        $('#cb_cate_select').change(function () {
+            const val = $(this).val()
+            const cate = category.find(item => item.id === parseInt(val))
+            $('#cb_cate_value_select').html(cate ? cate.value.map(item => `<option value="${item.id}">${item.value}</option>`).join('') : '<option value="0">请选择值</option>');
+        });
+        $('#dpsix-set').on('show.bs.modal', function (e) {
+            if (daPing06Set.sr) {
+                $('#sr_cate_select').val(daPing06Set.sr);
+                $('#sr_cate_value_select').html(category.find(item => item.id === parseInt(daPing06Set.sr)).value.map(item => `<option value="${item.id}" ${daPing06Set.sr_value === item.id ? 'selected' : ''}>${item.value}</option>`).join(''));
+            } else {
+                $('#sr_cate_value_select').html('<option value="0">请选择值</option>')
+            }
+            if (daPing06Set.cb) {
+                $('#cb_cate_select').val(daPing06Set.cb);
+                $('#cb_cate_value_select').html(category.find(item => item.id === parseInt(daPing06Set.cb)).value.map(item => `<option value="${item.id}" ${daPing06Set.cb_value === item.id ? 'selected' : ''}>${item.value}</option>`).join(''));
+            } else {
+                $('#cb_cate_value_select').html('<option value="0">请选择值</option>')
+            }
+            $('#cb_show_select').find('input').prop('checked', false);
+            $('#cb_show_select').find('input').each(function () {
+                if (daPing06Set.cb_show && daPing06Set.cb_show.length > 0 && daPing06Set.cb_show.includes(parseInt($(this).val()))) {
+                    $(this).prop('checked', true);
+                }
+            });
+        });
+        $('#cb_show_select').on('click', function (e) {
+            e.stopPropagation();
+        });
+        $('#cb_show_select input').on('click', function () {
+            const checked = $('#cb_show_select input:checked');
+            if (checked.length > 4) {
+                $(this).prop('checked', false);
+                toastr.warning('最多只能选择4个');
+                return;
+            }
+        });
+        $('#dp06_save_btn').click(function () {
+            if ($('#sr_cate_select').val() === '0') {
+                toastr.warning('请选择工程收入分类');
+                return;
+            }
+            if ($('#sr_cate_value_select').val() === '0') {
+                toastr.warning('请选择工程收入分类值');
+                return;
+            }
+            if ($('#cb_cate_select').val() === '0') {
+                toastr.warning('请选择工程成本费用分类');
+                return;
+            }
+            if ($('#cb_cate_value_select').val() === '0') {
+                toastr.warning('请选择工程成本费用分类值');
+                return;
+            }
+            // if ($('#cb_show_select input:checked').length === 0) {
+            //     toastr.warning('请选择要展示的列');
+            //     return;
+            // }
+            daPing06Set.sr = parseInt($('#sr_cate_select').val());
+            daPing06Set.sr_value = parseInt($('#sr_cate_value_select').val());
+            daPing06Set.cb = parseInt($('#cb_cate_select').val());
+            daPing06Set.cb_value = parseInt($('#cb_cate_value_select').val());
+            daPing06Set.cb_show = $('#cb_show_select input:checked').map((index, item) => parseInt($(item).val())).get();
+            console.log(daPing06Set);
+            postData('/setting/datacollect/save', { type: 'save-dp06', daPing06Set }, function (result) {
+                toastr.success('设置成功');
+                $('#dpsix-set').modal('hide');
+            })
+        });
+    })
+</script>
+<% } %>
 <script>
     $(function () {
         let timer = null

+ 42 - 1
app/view/stage/gather.ejs

@@ -61,13 +61,45 @@
             <div class="bcontent-wrap" id="main-bottom">
                 <div id="main-resize" class="resize-y" r-Type="height" div1="#gcl-spread" div2="#main-bottom" store-id="stage-gather" store-version="1.0.0" min="100"></div>
                 <div class="bc-bar mb-1">
-                    <ul class="nav nav-tabs">
+                    <ul class="nav nav-tabs" name="pos-tab">
                         <li class="nav-item">
                             <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">所属项目节</a>
                         </li>
                         <!--<li class="nav-item">-->
                         <!--<a class="nav-link " data-toggle="tab" href="#biangeng" role="tab">相关变更令</a>-->
                         <!--</li>-->
+                        <li class="nav-item">
+                            <a class="nav-link" data-toggle="tab" href="#xmjGather" role="tab">项目节汇总</a>
+                        </li>
+                        <li class="nav-item" id="optionTab">
+                            <div rela-tab="#xmjGather" style="display: none;">
+                                <div class="d-inline-block ml-2 mt-1">
+                                    <span>汇总条件:</span>
+                                    <div class="d-inline-block" style="vertical-align: middle">
+                                        <div class="form-check form-check-inline">
+                                            <input class="form-check-input pt-1" type="checkbox" id="gather-xmj-dwgc" value="dwgc" name="gather-xmj">
+                                            <label class="form-check-label" for="gather-xmj-dwgc">单位工程</label>
+                                        </div>
+                                        <div class="form-check form-check-inline">
+                                            <input class="form-check-input" type="checkbox" id="gather-xmj-fbgc" value="fbgc" name="gather-xmj">
+                                            <label class="form-check-label" for="gather-xmj-fbgc">分部工程</label>
+                                        </div>
+                                        <div class="form-check form-check-inline">
+                                            <input class="form-check-input" type="checkbox" id="gather-xmj-fxgc" value="fxgc" name="gather-xmj">
+                                            <label class="form-check-label" for="gather-xmj-fxgc">分项工程</label>
+                                        </div>
+                                        <div class="form-check form-check-inline">
+                                            <input class="form-check-input" type="checkbox" id="gather-xmj-xm" value="jldy" name="gather-xmj">
+                                            <label class="form-check-label" for="gather-xmj-xm">细目</label>
+                                        </div>
+                                        <div class="form-check form-check-inline">
+                                            <input class="form-check-input" type="checkbox" id="gather-xmj-jldy" value="bwmx" checked name="gather-xmj">
+                                            <label class="form-check-label" for="gather-xmj-jldy">计量单元</label>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </li>
                     </ul>
                 </div>
                 <div class="tab-content">
@@ -75,6 +107,10 @@
                         <div class="sp-wrap" id="leaf-xmj-spread">
                         </div>
                     </div>
+                    <div class="tab-pane active" id="xmjGather">
+                        <div class="sp-wrap" id="leaf-xmj-gather-spread">
+                        </div>
+                    </div>
                     <div class="tab-pane" id="biangeng">
                         <div class="sp-wrap">
                             <table class="table table-sm table-bordered">
@@ -101,6 +137,11 @@
         key: 'stage-gather-leafXmj',
         colWidth: true,
     }
+    const gatherLeafXmjSpreadSetting = JSON.parse('<%- JSON.stringify(gatherLeafXmjSpread) %>');
+    leafXmjSpreadSetting.localCache = {
+        key: 'stage-gather-gatherLeafXmj',
+        colWidth: true,
+    }
     const chapter = JSON.parse('<%- JSON.stringify(ctx.tender.info.chapter) %>');
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
     const hintOver = <%- hintOver %>;

+ 1 - 1
app/view/tender/detail.ejs

@@ -114,7 +114,7 @@
                                     </style>
                                     <div class="col-auto pl-0">
                                         <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
-                                            <div class="card-body" data-toggle="tooltip" data-placement="bottom" data-html="true" data-original-title="<p style='text-align:left;'>批复正变更:<%- ctx.helper.formatMoney(tender.change_p_tp) %></p>批复负变更:<%- ctx.helper.formatMoney(tender.change_n_tp) %>">
+                                            <div class="card-body" data-toggle="tooltip" data-placement="bottom" data-html="true" data-original-title="<p style='text-align:left;'>计价金额:<%- ctx.helper.formatMoney(tender.change_valuation_tp) %></p>不计价金额:<%- ctx.helper.formatMoney(tender.change_unvaluation_tp) %>">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.change_tp) %></h5>
                                                 <p class="card-text text-muted">已批复变更金额</p>
                                             </div>

+ 57 - 0
db_script/change_valuation.js

@@ -0,0 +1,57 @@
+// 计算变更令,计价不计价金额数
+
+const defaultInfo = require('../app/const/tender_info');
+const BaseUtil = require('./baseUtils');
+const status = require('../app/const/audit').change.status;
+const querySql = BaseUtil.querySql;
+const ZhCalc = BaseUtil.ZhCalc;
+
+const checkChange = async function(change) {
+    const changeBills = await querySql('Select * From zh_change_audit_list where cid = ?', [change.cid]);
+    let valuation_tp = 0;
+    let unvaluation_tp = 0;
+    for (const cb of changeBills) {
+        valuation_tp = cb.is_valuation ? ZhCalc.add(valuation_tp, cb.checked_price) : valuation_tp;
+        unvaluation_tp = !cb.is_valuation ? ZhCalc.add(unvaluation_tp, cb.checked_price) : unvaluation_tp;
+    }
+    await querySql('Update zh_change Set valuation_tp = ?, unvaluation_tp = ? Where cid = ?', [valuation_tp, unvaluation_tp, change.cid]);
+    console.log(`Update Change ${change.cid}`);
+};
+
+const doComplete = async function() {
+    try {
+        const tender = await querySql('Select * From zh_tender');
+        for (const t of tender) {
+            console.log(`Update Tender ${t.id}:`);
+            const changes = await querySql('Select * From zh_change where tid = ? AND status = ?', [t.id, status.checked]);
+            for (const c of changes) {
+                await checkChange(c);
+            }
+        }
+    } catch (err) {
+        console.log(err);
+    }
+    BaseUtil.closePool();
+};
+const doCompleteTest = async function(tid) {
+    try {
+        const tender = await querySql('Select * From zh_tender where id = ?', [tid]);
+        for (const t of tender) {
+            console.log(`Update Tender ${t.id}:`);
+            const changes = await querySql('Select * From zh_change where tid = ? AND status = ?', [t.id, status.checked]);
+            for (const c of changes) {
+                await checkChange(c);
+            }
+        }
+    } catch (err) {
+        console.log(err);
+    }
+    BaseUtil.closePool();
+};
+
+const tenderId = process.argv[3];
+if (tenderId) {
+    doCompleteTest(tenderId);
+} else {
+    doComplete();
+}

+ 11 - 1
sql/update.sql

@@ -1,2 +1,12 @@
+ALTER TABLE `zh_project`
+ADD COLUMN `common_json` json NULL COMMENT '通用json,没有sql查询值必要的可放这' AFTER `notice_setting`;
 ALTER TABLE `zh_ledger_tag`
-ADD COLUMN `pos_id` varchar(36) NOT NULL DEFAULT '' COMMENT '关联计量单元id(zh_pos表中的id)' AFTER `id`;
+ADD COLUMN `pos_id` varchar(36) NOT NULL DEFAULT '' COMMENT '关联计量单元id(zh_pos表中的id)' AFTER `id`;
+
+ALTER TABLE `zh_change`
+ADD COLUMN `valuation_tp` decimal(30, 8) NULL DEFAULT 0 COMMENT '计价金额(审批完成后统计)' AFTER `negative_tp`,
+ADD COLUMN `unvaluation_tp` decimal(30, 8) NULL DEFAULT 0 COMMENT '不计价金额(审批完成后统计)' AFTER `valuation_tp`;
+
+ALTER TABLE `zh_change`
+MODIFY COLUMN `positive_tp` decimal(30, 8) NOT NULL DEFAULT 0.00000000 COMMENT '正变更金额' AFTER `order_by`,
+MODIFY COLUMN `negative_tp` decimal(30, 8) NOT NULL DEFAULT 0.00000000 COMMENT '负变更金额' AFTER `positive_tp`,