소스 검색

Merge branch 'dev' into uat

MaiXinRong 3 년 전
부모
커밋
ea41547743
100개의 변경된 파일3929개의 추가작업 그리고 964개의 파일을 삭제
  1. 3 0
      app/const/page_show.js
  2. 2 1
      app/const/tender_info.js
  3. 6 1
      app/controller/budget_controller.js
  4. 96 2
      app/controller/datacollect_controller.js
  5. 28 2
      app/controller/material_controller.js
  6. 5 2
      app/controller/revise_controller.js
  7. 23 3
      app/controller/setting_controller.js
  8. 0 1
      app/controller/stage_controller.js
  9. 33 14
      app/controller/tender_controller.js
  10. 36 1
      app/extend/helper.js
  11. 19 0
      app/lib/ledger.js
  12. 1 1
      app/middleware/advance_check.js
  13. 4 1
      app/middleware/change_check.js
  14. 1 1
      app/middleware/ledger_audit_check.js
  15. 6 1
      app/middleware/material_check.js
  16. 1 1
      app/middleware/revise_audit_check.js
  17. 11 1
      app/middleware/revise_check.js
  18. 1 1
      app/middleware/stage_check.js
  19. 159 6
      app/public/css/main.css
  20. BIN
      app/public/images/juecedaping01.png
  21. BIN
      app/public/images/juecedaping02.png
  22. BIN
      app/public/images/juecedaping03.png
  23. BIN
      app/public/images/juecedaping04.png
  24. BIN
      app/public/images/not_Approve.png
  25. 2 1
      app/public/js/advance.js
  26. 2 1
      app/public/js/advance_audit.js
  27. 122 61
      app/public/js/budget_compare.js
  28. 5 3
      app/public/js/budget_detail.js
  29. 89 31
      app/public/js/budget_list.js
  30. 4 4
      app/public/js/change_information.js
  31. 4 2
      app/public/js/change_revise.js
  32. 95 0
      app/public/js/datacollect_scroll.js
  33. 42 30
      app/public/js/ledger.js
  34. 9 5
      app/public/js/ledger_check.js
  35. 91 46
      app/public/js/material.js
  36. 3 3
      app/public/js/material_file.js
  37. 2 0
      app/public/js/material_list.js
  38. 1 0
      app/public/js/path_tree.js
  39. 100 21
      app/public/js/revise.js
  40. 190 0
      app/public/js/setting_datacollect_tender.js
  41. 234 1
      app/public/js/shares/cs_tools.js
  42. 4 3
      app/public/js/shares/tenders2tree.js
  43. 18 4
      app/public/js/spreadjs_rela/spreadjs_zh.js
  44. 3 3
      app/public/js/sr_detail.js
  45. 27 6
      app/public/js/stage.js
  46. 3 3
      app/public/js/tender_list_progress.js
  47. 3 2
      app/public/report/js/rpt_jspdf.js
  48. 2 0
      app/router.js
  49. 25 0
      app/service/category.js
  50. 15 0
      app/service/change.js
  51. 16 0
      app/service/change_audit.js
  52. 4 1
      app/service/change_audit_list.js
  53. 100 0
      app/service/datacollect_tender.js
  54. 2 2
      app/service/ledger_tag.js
  55. 71 6
      app/service/material.js
  56. 10 0
      app/service/material_audit.js
  57. 26 9
      app/service/material_bills.js
  58. 6 2
      app/service/material_list.js
  59. 12 4
      app/service/material_month.js
  60. 22 0
      app/service/notice_push.js
  61. 7 0
      app/service/project.js
  62. 11 0
      app/service/report.js
  63. 51 2
      app/service/report_memory.js
  64. 7 0
      app/service/revise_audit.js
  65. 14 0
      app/service/stage.js
  66. 23 1
      app/service/stage_audit.js
  67. 1 1
      app/service/stage_bills.js
  68. 2 6
      app/service/stage_detail_att.js
  69. 2 2
      app/service/stage_shoufang.js
  70. 7 0
      app/service/tender.js
  71. 3 0
      app/view/advance/detail.ejs
  72. 5 1
      app/view/budget/compare.ejs
  73. 2 18
      app/view/budget/compare_modal.ejs
  74. 2 22
      app/view/budget/detail.ejs
  75. 4 1
      app/view/budget/list.ejs
  76. 3 10
      app/view/budget/list_modal.ejs
  77. 2 2
      app/view/change/information.ejs
  78. 2 22
      app/view/change/revise.ejs
  79. 1501 391
      app/view/datacollect/index.ejs
  80. 2 22
      app/view/ledger/explode.ejs
  81. 7 1
      app/view/ledger/explode_modal.ejs
  82. 54 22
      app/view/material/exponent.ejs
  83. 11 7
      app/view/material/index.ejs
  84. 39 3
      app/view/material/info.ejs
  85. 1 1
      app/view/measure/stage.ejs
  86. 3 0
      app/view/report/index.ejs
  87. 7 22
      app/view/revise/info.ejs
  88. 8 1
      app/view/revise/info_modal.ejs
  89. 92 69
      app/view/setting/datacollect.ejs
  90. 32 6
      app/view/setting/datacollect_modal.ejs
  91. 30 0
      app/view/setting/fun.ejs
  92. 74 28
      app/view/tender/detail.ejs
  93. 15 5
      app/view/tender/detail_modal.ejs
  94. 1 0
      app/view/tender/info.ejs
  95. 3 0
      app/view/wap/dashboard.ejs
  96. 12 0
      app/view/wap/shenpi_stage.ejs
  97. 12 0
      app/view/wap/tender.ejs
  98. 76 2
      builder_report_index_define.js
  99. 2 2
      config/config.default.js
  100. 0 0
      config/config.local.js

+ 3 - 0
app/const/page_show.js

@@ -34,6 +34,9 @@ const defaultSetting = {
     openSign: 0,
     openNetCaSign: 0,
     openChangeRevise: 0,
+    openMaterialTax: 0,
+    addDataCollect: 1,
+    closeWapYfSf: 0,
 };
 
 

+ 2 - 1
app/const/tender_info.js

@@ -113,7 +113,8 @@ const defaultInfo = {
         stage: {
             realComplete: false,
             correct: true,
-        }
+        },
+        dayMode: false,
     },
     chapter: [
         {code: '100', name: '总则'},

+ 6 - 1
app/controller/budget_controller.js

@@ -50,6 +50,7 @@ module.exports = app => {
                     return { groupName: item, groupList };
                 });
                 renderData.permissionConst = ctx.service.budgetPermission.PermissionConst;
+                renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 await this.layout('budget/list.ejs', renderData, 'budget/list_modal.ejs');
             } catch (err) {
                 ctx.log(err);
@@ -111,7 +112,7 @@ module.exports = app => {
                     err: 0,
                     msg: '',
                     data: tenderList.filter(x => { return otherRela.indexOf(x.id) === -1})
-                        .map(y => { return {id: y.id, name: y.name, lastStageOrder: y.lastStage.order, lastStageStatus: auditConst.stage.statusString[y.lastStage.status]}}),
+                        .map(y => { return {id: y.id, name: y.name, lastStageOrder: y.lastStage.order, lastStageStatus: auditConst.stage.statusString[y.lastStage.status], category: y.category}}),
                 };
             } catch (err) {
                 ctx.log(err);
@@ -153,6 +154,10 @@ module.exports = app => {
                 renderData.tenderList = relaTenderId.length > 0 ? tenderList.filter(x => {
                     return relaTenderId.indexOf(x.id) >= 0;
                 }) : tenderList;
+                renderData.tenderList = renderData.tenderList.map(y => {
+                    return { id: y.id, name: y.name, lastStageOrder: y.lastStage.order, lastStageStatus: auditConst.stage.statusString[y.lastStage.status], category: y.category };
+                });
+                renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 await this.layout('budget/compare.ejs', renderData, 'budget/compare_modal.ejs');
             } catch (err) {
                 ctx.log(err);

+ 96 - 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 mapConst = require('../const/map');
 
 module.exports = app => {
     class DatacollectController extends app.BaseController {
@@ -45,11 +46,38 @@ module.exports = app => {
          */
         async index(ctx) {
             try {
+                if (!ctx.session.sessionProject.showDataCollect) {
+                    throw '该功能已关闭或无法查看';
+                }
                 // 获取标段审批信息
-                const noticeList = await ctx.service.noticePush.getNotice(ctx.session.sessionProject.id);
-                console.log(noticeList);
+                const tenderidList = [];
+                const noticeList = await ctx.service.noticePush.getNoticeByDataCollect(ctx.session.sessionProject.id, tenderidList);
+                // 获取分类
+                const categoryData = await this.ctx.service.category.getListByCategoryLevel(ctx.session.sessionProject.id);
+                // 默认坐标,否则则取办事处坐标
+                const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
+                projectData.data_collect_pages = projectData.data_collect_pages ? projectData.data_collect_pages.split(',') : [];
+                let map_json = {
+                    province: mapConst.map[0].province,
+                    lng: mapConst.map[0].lng,
+                    lat: mapConst.map[0].lat,
+                    level: 15,
+                };
+                if (projectData.map_json) {
+                    map_json = JSON.parse(projectData.map_json);
+                } else {
+                    const mapInfo = ctx.helper._.find(mapConst.map, { office: projectData.manager_office });
+                    if (mapInfo) {
+                        map_json.province = mapInfo.province;
+                        map_json.lng = mapInfo.lng;
+                        map_json.lat = mapInfo.lat;
+                    }
+                }
                 const renderData = {
+                    projectData,
                     noticeList,
+                    categoryData,
+                    map_json,
                     acLedger: auditConst.ledger,
                     acStage: auditConst.stage,
                     acChange: auditConst.flow,
@@ -65,6 +93,72 @@ module.exports = app => {
                 ctx.redirect(this.menu.menu.dashboard.url);
             }
         }
+
+        async loadData(ctx) {
+            try {
+                const responseData = { err: 0, msg: '', data: {} };
+                // const tenderidList = [];
+                // const noticeList = await ctx.service.noticePush.getNoticeByDataCollect(ctx.session.sessionProject.id, tenderidList);
+                const dcTenders = await ctx.service.datacollectTender.getList(ctx.session.sessionProject.id);
+                const noTids = ctx.app._.map(dcTenders, 'tid');
+                let tenderList = await ctx.service.tender.getList('', null, 1);
+                tenderList = ctx.app._.filter(tenderList, function(item) {
+                    return ctx.app._.indexOf(noTids, item.id) === -1;
+                });
+                const thisMonth = new Date();
+                const [startMonth, endMonth] = ctx.helper.getStartEndMonth(thisMonth);
+                for (const t of tenderList) {
+                    const tenderInfo = await ctx.service.tenderInfo.getTenderInfo(t.id);
+                    t.contract_price = tenderInfo.deal_param.contractPrice;
+
+                    if (t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck) {
+                        const sum = await ctx.service.ledger.addUp({ tender_id: t.id/* , is_leaf: true*/ });
+                        t.total_price = sum.total_price;
+                        t.deal_tp = sum.deal_tp;
+                    }
+                    t.advance_tp = await ctx.service.advance.getSumAdvance(t.id);
+
+                    if (t.ledger_status === auditConst.ledger.status.checked) {
+                        t.lastStage = await ctx.service.stage.getLastestStage(t.id, true);
+                        if (t.lastStage && t.lastStage.status === auditConst.stage.status.uncheck &&
+                            t.lastStage.user_id !== ctx.session.sessionUser.accountId) {
+                            t.lastStage = await ctx.service.stage.getLastestStage(t.id);
+                        }
+                        if (t.lastStage) await ctx.service.stage.checkStageGatherData(t.lastStage);
+                        t.completeStage = await ctx.service.stage.getLastestCompleteStage(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);
+                    t.month_change_num = await ctx.service.changeAudit.getNumByMonth(t.id, startMonth, endMonth);
+                    t.month_revise_num = await ctx.service.reviseAudit.getNumByMonth(t.id, startMonth, endMonth);
+                    t.month_material_num = await ctx.service.materialAudit.getNumByMonth(t.id, startMonth, endMonth);
+                    // 获取标段计量月统计及截止月累计计量
+                    const stageList = await ctx.service.stage.getStageByDataCollect(t.id);
+                    const month_stage = [];
+                    for (const s of stageList) {
+                        const monthOneStage = ctx.app._.find(month_stage, { yearmonth: s.s_time });
+                        if (monthOneStage) {
+                            monthOneStage.tp = ctx.helper.add(monthOneStage.tp, s.tp);
+                        } else {
+                            const data = {
+                                yearmonth: s.s_time,
+                                tp: s.tp,
+                                end_tp: s.end_tp,
+                            };
+                            month_stage.push(data);
+                        }
+                    }
+                    t.month_stage = month_stage;
+                }
+                // const tenderMapList = await ctx.service.tenderMap.getAllDataByCondition({ where: { tid: tender.id } });
+                responseData.data.tenderList = tenderList;
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
     }
 
     return DatacollectController;

+ 28 - 2
app/controller/material_controller.js

@@ -52,7 +52,14 @@ module.exports = app => {
                     auditConst,
                     auditConst2: JSON.stringify(auditConst),
                 };
+                let openMaterialTax = ctx.session.sessionProject.page_show.openMaterialTax;
+                let allMaterialTax = true;
                 renderData.materials = await ctx.service.material.getValidMaterials(ctx.tender.id);
+                const lastMaterial = renderData.materials.length > 0 ? renderData.materials[0] : null;
+                if (lastMaterial && (lastMaterial.status === auditConst.status.uncheck || lastMaterial.status === auditConst.status.checkNo) && lastMaterial.material_tax !== openMaterialTax) {
+                    await ctx.service.material.updateMaterialTax(lastMaterial.id, openMaterialTax);
+                    lastMaterial.material_tax = openMaterialTax;
+                }
                 // 获取未选中和已完成的计量期
                 const stages = await ctx.service.stage.getAllDataByCondition({ where: { tid: ctx.tender.id, status: auditStageConst.status.checked } });
                 for (const s of renderData.materials) {
@@ -66,8 +73,16 @@ module.exports = app => {
                         });
                         stages.splice(index, 1);
                     }
+                    if (allMaterialTax && s.material_tax === 0) {
+                        allMaterialTax = false;
+                    }
+                    if (!openMaterialTax && s.material_tax === 1) {
+                        openMaterialTax = 1;
+                    }
                 }
                 renderData.stages = stages;
+                renderData.openMaterialTax = openMaterialTax;
+                renderData.allMaterialTax = allMaterialTax;
                 await this.layout('material/index.ejs', renderData, 'material/modal.ejs');
             } catch (err) {
                 this.log(err);
@@ -342,14 +357,18 @@ module.exports = app => {
                 // }
 
                 // 取当前期截止上期含税金额
+                renderData.material.m_tax_tp = renderData.material.m_tax_tp ? renderData.material.m_tax_tp : renderData.material.m_tp;
                 renderData.pre_tp_hs = await ctx.service.material.getPreTpHs(ctx.tender.id, ctx.material.order);
                 renderData.ex_pre_tp_hs = await ctx.service.material.getExPreTpHs(ctx.tender.id, ctx.material.order);
+                // renderData.tax_pre_tp_hs = await ctx.service.material.getTaxPreTpHs(ctx.tender.id, ctx.material.order);
 
                 renderData.months = ctx.material.months ? ctx.material.months.split(',') : [];
                 renderData.monthsList = await this._getMaterialMonthsData(ctx, renderData.materialBillsData);
 
                 renderData.materialType = JSON.stringify(materialConst);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.material.info);
+                // 判断之前期有无调用过材料税
+                renderData.old_had_tax = await ctx.service.material.getOldMaterialTax(ctx.tender.id, ctx.params.order);
                 await this.layout('material/info.ejs', renderData, 'material/info_modal.ejs');
             } catch (err) {
                 this.log(err);
@@ -487,6 +506,8 @@ module.exports = app => {
                 renderData.ex_pre_tp_hs = await ctx.service.material.getExPreTpHs(ctx.tender.id, ctx.material.order);
                 renderData.materialType = materialConst;
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.material.exponent);
+                // 判断之前期有无调用过材料税
+                renderData.old_had_tax = await ctx.service.material.getOldMaterialTax(ctx.tender.id, ctx.params.order);
                 await this.layout('material/exponent.ejs', renderData, 'material/exponent_modal.ejs');
             } catch (err) {
                 this.log(err);
@@ -615,7 +636,7 @@ module.exports = app => {
                         responseData.data.m_tp = await ctx.service.materialBills.del(data.id);
                         break;
                     case 'changeOrder':
-                        responseData.data = await ctx.service.materialBills.changeOrder(data.id1, data.id2);
+                        await ctx.service.materialBills.changeOrder(data.id1, data.id2);
                         break;
                     case 'update':
                         if (data.updateData.code === '' || data.updateData.code === null) {
@@ -670,7 +691,9 @@ module.exports = app => {
                         break;
                     default: throw '参数有误';
                 }
-
+                if (ctx.material.material_tax) {
+                    responseData.data.m_tax_tp = await ctx.service.material.getMaterialTaxTp(ctx.material.id);
+                }
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);
@@ -732,6 +755,9 @@ module.exports = app => {
                         break;
                     default: throw '参数有误';
                 }
+                if (ctx.material.material_tax) {
+                    responseData.data.m_tax_tp = await ctx.service.material.getMaterialTaxTp(ctx.material.id);
+                }
                 responseData.data.materialBillsData = await this._getMaterialBillsData(ctx);
                 ctx.body = responseData;
             } catch (err) {

+ 5 - 2
app/controller/revise_controller.js

@@ -461,7 +461,8 @@ module.exports = app => {
                         }
                     }
                 }
-                ctx.body = { err: 0, msg: '', data: { bills: reviseBills, pos: revisePos } };
+                const ledgerTags = await this.ctx.service.ledgerTag.getDatas(ctx.tender.id);
+                ctx.body = { err: 0, msg: '', data: { bills: reviseBills, pos: revisePos, tags: ledgerTags } };
             } catch (err) {
                 ctx.helper.log(err);
                 this.ajaxErrorBody(err, '加载台账修订数据错误');
@@ -1011,8 +1012,10 @@ module.exports = app => {
                 case 'dealBills': return await ctx.service.dealBills.getAllDataByCondition({where: {tender_id: ctx.tender.id}});
                 case 'spec':
                     const spec = {zlj: stdConst.zlj, jrg: stdConst.jrg};
-                    spec.zlj.deal_bills_tp = ctx.tender.info.deal_param.zanLiePrice;;
+                    spec.zlj.deal_bills_tp = ctx.tender.info.deal_param.zanLiePrice;
                     return spec;
+                case 'tags':
+                    return await this.ctx.service.ledgerTag.getDatas(ctx.tender.id);
             }
         }
 

+ 23 - 3
app/controller/setting_controller.js

@@ -763,9 +763,13 @@ module.exports = app => {
 
                 const result = await ctx.service.project.updateFunRela(projectId, ctx.request.body);
                 if (!result) throw '保存数据失败';
+                this.ctx.session.sessionProject.page_show.openChangeRevise = data.openChangeRevise ? 1 : 0;
+                this.ctx.session.sessionProject.page_show.openMaterialTax = data.openMaterialTax ? 1 : 0;
+                const result2 = await ctx.service.project.updatePageshow(projectId);
+                if (!result2) throw '保存数据失败';
 
-                ctx.body = {err: 0, msg: '', data: null};
-            } catch(error) {
+                ctx.body = { err: 0, msg: '', data: null };
+            } catch (error) {
                 ctx.helper.log(error);
                 this.ajaxErrorBody(error, '保存数据失败');
             }
@@ -855,6 +859,7 @@ module.exports = app => {
                 await this._checkMenu(projectId);
                 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(',') : [];
                 if (ctx.session.sessionUser.is_admin === 0) throw '没有访问权限';
                 const dataCollectAudits = await ctx.service.datacollectAudit.getList(projectId);
                 // 获取所有项目参与者
@@ -867,12 +872,16 @@ module.exports = app => {
                     return { groupName: item, groupList };
                 });
                 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', {
                     projectData,
                     dataCollectAudits,
                     accountList,
                     accountGroup: accountGroupList,
                     categoryData,
+                    tenders,
+                    dcTenders,
                 }, 'setting/datacollect_modal.ejs');
             } catch (error) {
                 ctx.helper.log(error);
@@ -894,7 +903,7 @@ module.exports = app => {
                 }
                 switch (data.type) {
                     case 'show':
-                        responseData.data = await ctx.service.project.update({ data_collect: data.data_collect }, { id: projectId });
+                        responseData.data = await ctx.service.project.update({ data_collect: data.data_collect, 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;
                         break;
@@ -936,6 +945,17 @@ module.exports = app => {
                         await ctx.service.datacollectAudit.delAudit(data.id);
                         responseData.data = await ctx.service.datacollectAudit.getList(projectId);
                         break;
+                    case 'tender':
+                        if (ctx.session.sessionProject.page_show.addDataCollect !== parseInt(data.add_datacollect)) {
+                            ctx.session.sessionProject.page_show.addDataCollect = parseInt(data.add_datacollect);
+                            await ctx.service.project.updatePageshow(projectId);
+                        }
+                        await ctx.service.datacollectTender.updateList(projectId, data.tids);
+                        responseData.data = {
+                            dcTenders: await ctx.service.datacollectTender.getList(projectId),
+                            addDatacollect: ctx.session.sessionProject.page_show.addDataCollect,
+                        };
+                        break;
                     default: throw '参数有误';
                 }
                 ctx.body = responseData;

+ 0 - 1
app/controller/stage_controller.js

@@ -787,7 +787,6 @@ module.exports = app => {
                 const result = await ctx.service.stageDetailAtt.addFiles(this.ctx.stage, baseInfo, uploadFiles);
                 ctx.body = { err: 0, mgs: '', data: result };
             } catch (err) {
-                console.log(err);
                 // 失败需要消耗掉stream 以防卡死
                 if (stream) await sendToWormhole(stream);
                 ctx.log(err);

+ 33 - 14
app/controller/tender_controller.js

@@ -130,14 +130,9 @@ module.exports = app => {
                     const tenderInfo = await this.ctx.service.tenderInfo.getTenderInfo(t.id);
                     t.contract_price = tenderInfo.deal_param.contractPrice;
 
-                    if (t.user_id === this.ctx.session.sessionUser.accountId && (
-                        t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck)) {
-                        const sum = await this.ctx.service.ledger.addUp({ tender_id: t.id/* , is_leaf: true*/ });
-                        t.total_price = sum.total_price;
-                        t.deal_tp = sum.deal_tp;
-                    }
+                    let bCalcTp = t.user_id === this.ctx.session.sessionUser.accountId && (
+                        t.ledger_status === auditConst.ledger.status.checkNo || t.ledger_status === auditConst.ledger.status.uncheck);
                     t.advance_tp = await this.ctx.service.advance.getSumAdvance(t.id);
-
                     if (t.ledger_status === auditConst.ledger.status.checked) {
                         t.lastStage = await this.ctx.service.stage.getLastestStage(t.id, true);
                         if (t.lastStage && t.lastStage.status === auditConst.stage.status.uncheck &&
@@ -146,6 +141,15 @@ module.exports = app => {
                         }
                         if (t.lastStage) await this.ctx.service.stage.checkStageGatherData(t.lastStage);
                         t.completeStage = await this.ctx.service.stage.getLastestCompleteStage(t.id);
+                        if ((!bCalcTp) && t.measure_type === measureType.gcl.value) {
+                            bCalcTp = t.lastStage && t.lastStage.status !== auditConst.stage.status.checked && !t.lastStage.readOnly;
+                        }
+                    }
+
+                    if (bCalcTp) {
+                        const sum = await this.ctx.service.ledger.addUp({ tender_id: t.id/* , is_leaf: true*/ });
+                        t.total_price = sum.total_price;
+                        t.deal_tp = sum.deal_tp;
                     }
 
                     if (t.lastStage) {
@@ -390,16 +394,22 @@ module.exports = app => {
         async tenderInfo(ctx) {
             try {
                 const tender = ctx.tender.data;
-                if (tender.user_id === this.ctx.session.sessionUser.accountId && (
-                    tender.ledger_status === auditConst.ledger.status.checkNo || tender.ledger_status === auditConst.ledger.status.uncheck)) {
-                    const sum = await this.ctx.service.ledger.addUp({ tender_id: tender.id/* , is_leaf: true*/ });
-                    tender.total_price = sum.total_price;
-                    tender.deal_tp = sum.deal_tp;
-                }
+                let bCalcTp = tender.user_id === this.ctx.session.sessionUser.accountId && (
+                    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);
                 if (lastStage) {
                     await this.ctx.service.stage.checkStageGatherData(lastStage);
+
+                    if ((!bCalcTp) && tender.measure_type === measureType.gcl.value) {
+                        bCalcTp = lastStage.status !== auditConst.stage.status.checked && !lastStage.readOnly;
+                    }
+                    if (bCalcTp) {
+                        const sum = await this.ctx.service.ledger.addUp({ tender_id: tender.id/* , is_leaf: true*/ });
+                        tender.total_price = sum.total_price;
+                        tender.deal_tp = sum.deal_tp;
+                    }
+
                     tender.gather_tp = ctx.helper.add(lastStage.contract_tp, lastStage.qc_tp);
                     tender.end_contract_tp = ctx.helper.add(lastStage.contract_tp, lastStage.pre_contract_tp);
                     tender.end_qc_tp = ctx.helper.add(lastStage.qc_tp, lastStage.pre_qc_tp);
@@ -436,6 +446,12 @@ module.exports = app => {
                         lastStage.auditors = await ctx.service.stageAudit.getFinalAuditGroup(lastStage.id, times);
                     }
                 } else {
+                    if (bCalcTp) {
+                        const sum = await this.ctx.service.ledger.addUp({ tender_id: tender.id/* , is_leaf: true*/ });
+                        tender.total_price = sum.total_price;
+                        tender.deal_tp = sum.deal_tp;
+                    }
+
                     if (tender.ledger_status !== auditConst.ledger.status.uncheck) {
                         const status_name = await this.ctx.service.ledgerAudit.getStatusName(tender.id, tender.ledger_times);
                         tender.status_users = status_name ? status_name.name : '';
@@ -446,6 +462,7 @@ module.exports = app => {
                         tender.status_users = status_name ? status_name.name : '';
                     }
                 }
+
                 const tiModel = new tenderInfoModel(ctx);
                 const gclChapter = await tiModel.gatherChapter();
 
@@ -974,7 +991,6 @@ module.exports = app => {
                     await ctx.service.ledgerCooperation.changeAllStatus(status);
                 }
                 // }
-                // console.log(postData);
                 await ctx.service.tenderInfo.saveTenderInfo(ctx.tender.id, { shenpi: postData });
                 let auditList = [];
                 if (data.status === shenpiConst.sp_status.gdspl) {
@@ -1137,6 +1153,9 @@ module.exports = app => {
                 if (ctx.stage) {
                     const isAuditor = ctx.stage.users.indexOf(this.ctx.session.sessionUser.accountId) >= 0;
                     if (!isAuditor && !isValidTourist) throw '您无权进行该操作';
+                } else if (ctx.revise) {
+                    const isAuditor = ctx.revise.reviseUsers.indexOf(this.ctx.session.sessionUser.accountId) >= 0;
+                    if (!isAuditor && !isValidTourist) throw '您无权进行该操作';
                 } else {
                     const isAuditor = ctx.tender.ledgerUsers.indexOf(this.ctx.session.sessionUser.accountId) >= 0;
                     if (!isAuditor && !isValidTourist) throw '您无权进行该操作';

+ 36 - 1
app/extend/helper.js

@@ -889,7 +889,8 @@ module.exports = {
         for (let i = 0; i < l.length; i++) {
             t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? dot : '');
         }
-        return t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r);
+        const num = t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r);
+        return num.replace('-,', '-');
     },
 
     transFormToChinese(num) {
@@ -1290,6 +1291,31 @@ module.exports = {
         return result;
     },
 
+    filterLastestData2(data, keyFields, timesField = 'times', orderField = 'order') {
+        const dataIndex = {};
+        for (const d of data) {
+            let key = 'd';
+            for (const kf of keyFields) {
+                key = key + '.' + (d[kf] || '');
+            }
+
+            if (!dataIndex[key]) dataIndex[key] = { index: 0, source: [] };
+            const di = dataIndex[key];
+            const curIndex = d[timesField] * timesLen + d[orderField];
+            if (curIndex === di.index) {
+                di.source.push(d);
+            } else if (curIndex > di.index) {
+                di.index = curIndex;
+                di.source = [d];
+            }
+        }
+        const result = [];
+        for (const prop in dataIndex) {
+            result.push(...dataIndex[prop].source);
+        }
+        return result;
+    },
+
     calcExpr(expr) {
         const validExpr = expr.replace('=', '').replace('%', '/100');
         return math.eval(validExpr);
@@ -1430,4 +1456,13 @@ module.exports = {
         }
         return result.content;
     },
+
+    getStartEndMonth(month) {
+        // month = new Date('2021-10-03');
+        // const startMonth = new Date(month.getFullYear(), month.getMonth(), 1);
+        // const endMonth = new Date(month.getFullYear(), month.getMonth() + 1, 1);
+        const startMonth = moment(month).startOf('month').format('YYYY-MM-DD HH:mm:ss');
+        const endMonth = moment(month).endOf('month').format('YYYY-MM-DD HH:mm:ss');
+        return [startMonth, endMonth];
+    },
 };

+ 19 - 0
app/lib/ledger.js

@@ -749,6 +749,25 @@ class checkData {
 
             addXmjCheck(topLevel);
         }
+        const xmjPart = {}, xmjIndex = [];
+        for (const x of xmj) {
+            if (!xmjPart[x.code]) {
+                xmjPart[x.code] = [];
+                xmjIndex.push(x.code);
+            }
+            xmjPart[x.code].push(x);
+        }
+        for (const x of xmjIndex) {
+            if (xmjPart[x].length <= 1) continue;
+            for (const xp of xmjPart[x]) {
+                this.checkResult.error.push({
+                    ledger_id: xp.ledger_id,
+                    b_code: xp.b_code,
+                    name: xp.name,
+                    errorType: 'same_code',
+                })
+            }
+        }
         let check = null;
         while (xmj.length > 0) {
             [check, xmj] = this.ctx.helper._.partition(xmj, x => { return x.code === xmj[0].code; });

+ 1 - 1
app/middleware/advance_check.js

@@ -56,7 +56,7 @@ module.exports = () => {
             if ((advance.status === status.uncheck || advance.status === status.checkNo) && this.tender.info.shenpi.advance !== shenpiConst.sp_status.sqspr) {
                 const shenpi_status = this.tender.info.shenpi.advance;
                 // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
-                const auditList = yield this.service.advanceAudit.getAllDataByCondition({ where: { vid: advance.id, times: advance.times } });
+                const auditList = yield this.service.advanceAudit.getAllDataByCondition({ where: { vid: advance.id, times: advance.times }, orders: [['order', 'asc']] });
                 const auditIdList = _.map(auditList, 'audit_id');
                 if (shenpi_status === shenpiConst.sp_status.gdspl) {
                     const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: advance.tid, sp_type: shenpiConst.sp_type.advance, sp_status: shenpi_status } });

+ 4 - 1
app/middleware/change_check.js

@@ -61,8 +61,11 @@ module.exports = options => {
             } else { // 其他不可见
                 throw '您无权查看该数据';
             }
-
             this.change = change;
+            if ((change.status === status.uncheck || change.status === status.back || change.status === status.revise) && change.tp_decimal !== this.tender.info.decimal.tp) {
+                this.change.tp_decimal = this.tender.info.decimal.tp;
+                yield this.service.change.updateDecimalAndTp();
+            }
             yield next;
         } catch (err) {
             console.log(err);

+ 1 - 1
app/middleware/ledger_audit_check.js

@@ -26,7 +26,7 @@ module.exports = options => {
             if ((this.tender.data.ledger_status === status.uncheck || this.tender.data.ledger_status === status.checkNo) && this.tender.info.shenpi.ledger !== shenpiConst.sp_status.sqspr) {
                 const shenpi_status = this.tender.info.shenpi.ledger;
                 // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
-                const auditList = yield this.service.ledgerAudit.getAllDataByCondition({ where: { tender_id: this.tender.id, times: this.tender.data.ledger_times } });
+                const auditList = yield this.service.ledgerAudit.getAllDataByCondition({ where: { tender_id: this.tender.id, times: this.tender.data.ledger_times }, orders: [['audit_order', 'asc']] });
                 const auditIdList = _.map(auditList, 'audit_id');
                 if (shenpi_status === shenpiConst.sp_status.gdspl) {
                     const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: this.tender.id, sp_type: shenpiConst.sp_type.ledger, sp_status: shenpi_status } });

+ 6 - 1
app/middleware/material_check.js

@@ -45,6 +45,11 @@ module.exports = options => {
             if (!material) {
                 throw '材料调差期数据错误';
             }
+            const openMaterialTax = this.session.sessionProject.page_show.openMaterialTax;
+            if ((material.status === status.uncheck || material.status === status.checkNo) && material.material_tax !== openMaterialTax) {
+                yield this.service.material.updateMaterialTax(material.id, openMaterialTax);
+                material.material_tax = openMaterialTax;
+            }
             // 读取原报、审核人数据
             material.auditors = yield this.service.materialAudit.getAuditors(material.id, material.times);
             // if (material.status > 1) {
@@ -123,7 +128,7 @@ module.exports = options => {
             if ((material.status === status.uncheck || material.status === status.checkNo) && this.tender.info.shenpi.material !== shenpiConst.sp_status.sqspr) {
                 const shenpi_status = this.tender.info.shenpi.material;
                 // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
-                const auditList = yield this.service.materialAudit.getAllDataByCondition({ where: { mid: material.id, times: material.times } });
+                const auditList = yield this.service.materialAudit.getAllDataByCondition({ where: { mid: material.id, times: material.times }, orders: [['order', 'asc']] });
                 const auditIdList = _.map(auditList, 'aid');
                 if (shenpi_status === shenpiConst.sp_status.gdspl) {
                     const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: material.tid, sp_type: shenpiConst.sp_type.material, sp_status: shenpi_status } });

+ 1 - 1
app/middleware/revise_audit_check.js

@@ -29,7 +29,7 @@ module.exports = options => {
             if ((revise.status === status.uncheck || revise.status === status.checkNo) && this.tender.info.shenpi.revise !== shenpiConst.sp_status.sqspr) {
                 const shenpi_status = this.tender.info.shenpi.revise;
                 // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
-                const auditList = yield this.service.reviseAudit.getAllDataByCondition({ where: { rid: revise.id, times: revise.times } });
+                const auditList = yield this.service.reviseAudit.getAllDataByCondition({ where: { rid: revise.id, times: revise.times }, orders: [['audit_order', 'asc']] });
                 const auditIdList = _.map(auditList, 'audit_id');
                 if (shenpi_status === shenpiConst.sp_status.gdspl) {
                     const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: this.tender.id, sp_type: shenpiConst.sp_type.revise, sp_status: shenpi_status } });

+ 11 - 1
app/middleware/revise_check.js

@@ -8,6 +8,7 @@
  * @version
  */
 
+const auditConst = require('../const/audit').revise;
 module.exports = options => {
     /**
      * 标段校验 中间件
@@ -20,7 +21,16 @@ module.exports = options => {
     return function* reviseAuditCheck(next) {
         try {
             // 获取revise
-            this.revise = yield this.service.ledgerRevise.getLastestRevise(this.tender.id);
+            const revise = yield this.service.ledgerRevise.getLastestRevise(this.tender.id);
+            if (!revise) throw '台账修订数据有误';
+            revise.reviseUsers = [revise.uid];
+            if (revise.status !== auditConst.status.uncheck) {
+                const times = revise.status === auditConst.status.checkNo ? revise.times - 1 : revise.times;
+                const auditors = yield this.service.reviseAudit.getAuditors(revise.id, times);
+                const auditorsId = this.helper._.map(auditors, 'audit_id');
+                revise.reviseUsers.push(...auditorsId);
+            }
+            this.revise = revise;
             yield next;
         } catch (err) {
             // 输出错误到日志

+ 1 - 1
app/middleware/stage_check.js

@@ -138,7 +138,7 @@ module.exports = options => {
             if ((stage.status === status.uncheck || stage.status === status.checkNo) && this.tender.info.shenpi.stage !== shenpiConst.sp_status.sqspr) {
                 const shenpi_status = this.tender.info.shenpi.stage;
                 // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
-                const auditList = yield this.service.stageAudit.getAllDataByCondition({ where: { sid: stage.id, times: stage.times } });
+                const auditList = yield this.service.stageAudit.getAllDataByCondition({ where: { sid: stage.id, times: stage.times }, orders: [['order', 'asc']] });
                 const auditIdList = _.map(auditList, 'aid');
                 if (shenpi_status === shenpiConst.sp_status.gdspl) {
                     const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: stage.tid, sp_type: shenpiConst.sp_type.stage, sp_status: shenpi_status } });

+ 159 - 6
app/public/css/main.css

@@ -506,6 +506,17 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   border:none ;
   border-bottom:2px solid #fff;
 }
+.nav-tabs.nav-white-tabs.panel-card-tabs .nav-link{
+  color:#495057;
+}
+.nav-tabs.nav-white-tabs.panel-card-tabs .nav-link.active{
+  color:#495057;
+  border-bottom:2px solid #007bff;
+}
+.nav-tabs.nav-white-tabs.panel-card-tabs .nav-link:hover{
+  color:#007bff;
+  border-bottom:2px solid #007bff;
+}
 .panel-card-header {
   background-image: linear-gradient(to top, #586579, #2c3237 );
 }
@@ -785,6 +796,9 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   padding:1px;
   background:#fff;
 }
+.c-body-white{
+  background: #e4e7ea;
+}
 .right-nav{
   width:36px
 }
@@ -1048,7 +1062,11 @@ label{
   width:120px;
 }
 .panel-sidebar .scrollbar-auto{
-  padding-top:0;
+  padding-top: 0;
+  /*padding-top:35px;*/
+}
+.panel-sidebar .show-back{
+  padding-top: 35px;
 }
 .nav-list li a{
   padding-right:0px;
@@ -1528,7 +1546,7 @@ overflow-y: auto;
   line-height: 200%;
 }
 .border-bottom-grey-1{
-  border-bottom: 1px solid #464647;
+  border-bottom: 1px solid rgba(0,0,0,.125);
 }
 .height-100{
   height: 100%;
@@ -1551,7 +1569,7 @@ overflow-y: auto;
 .height-20{
   height: 19%;
 }
-#review_box{
+#review_box,#review_box2{
   height: 100%;
   overflow: hidden;
 }
@@ -1564,7 +1582,7 @@ overflow-y: auto;
   height: -moz-calc(100% - 53px);
   height: calc(100% - 53px);
 }
-#comment1, #comment2{
+#comment1, #comment2, #comment3, #comment4{
   margin: 0;
   padding: 0;
 }
@@ -1577,16 +1595,17 @@ overflow-y: auto;
   width:100%;
 }
 .tablebox table th,.tablebox table td {
-  padding: 5px 0;
+  padding: 5px 10px;
 }
 .tablebox table th {
   color:#fff;
+  /*background-color:#fff;*/
   background-color:#2C3034;
 }
 .tablebox table tbody tr{
   background-color:#2C3034;
   color: #fff;
-  border-bottom: 1px solid #464647;
+  border-bottom: 1px solid rgba(0,0,0,.125);
 }
 .left-small-card-content,.right-small-card-content{
   height: 12%;
@@ -1719,4 +1738,138 @@ overflow-y: auto;
   font-size: 14px;
   line-height: 18px;
   color: rgba(0, 0, 0, 0.6);
+}
+.card-icon{
+  display: inline-block;
+  width: 4px;
+  height: 12px;
+  background: rgba(51, 119, 255, 1);
+}
+.agency-partheight{
+  height: calc((100vh - 155px) / 2);
+  /*background:rgba(82, 196, 26, 1);*/
+}
+.contant-height-one{
+  height: calc(((100vh - 165px) / 2) - 65px);
+  overflow-y: auto;
+}
+.contant-height-two{
+  height: calc(((100vh - 165px) / 2) - 178px);
+  overflow-y: auto;
+}
+.contant-height-three{
+  height: calc(((100vh - 165px) / 2) - 118px);
+  overflow-y: auto;
+}
+.btn-table{
+  width: 70px;
+  text-align: center;
+}
+.bg-new-red{
+  background: rgba(241, 82, 91, 0.08) !important;
+}
+.bg-new-orange{
+  background: rgba(250, 140, 22, 0.08) !important;
+}
+.bg-new-yellow{
+  background: rgba(251, 182, 45, 0.08) !important;
+}
+.bg-new-green{
+  background: rgba(82, 196, 26, 0.08) !important;
+}
+.bg-new-blue{
+  background: rgba(51, 119, 255, 0.08) !important;
+}
+.text-new-red{
+  color: rgba(241, 82, 91, 1) !important;
+}
+.text-new-orange{
+  color: rgba(250, 140, 22, 1) !important;
+}
+.text-new-yellow{
+  color: rgba(251, 182, 45, 1) !important;
+}
+.text-new-green{
+  color: rgba(82, 196, 26, 1) !important;
+}
+.text-new-blue{
+  color: rgba(51, 119, 255, 1) !important;
+}
+.text-width{
+  width: 66px;
+  text-align: center;
+}
+.table-middle td, .table-middle th{
+  padding: 0.6rem;
+}
+.table-middle .thead-light th {
+  color: #495057;
+  background-color: rgba(250, 250, 250, 1);
+  border-color: #dee2e6;
+}
+.table-middle thead th{
+  border-bottom: none;
+}
+.card-big-htext{
+  font-size: 18px;
+}
+.card-white{
+  background: rgba(255, 255, 255, 1) !important;
+  border-bottom: none;
+}
+.canyu-width{
+  height: 98px;
+}
+.canyu-bg-blue{
+  background: url(bg_participate_blue.png) no-repeat;
+  background-size: 100% 100%;
+}
+.canyu-bg-yellow{
+  background: url(bg_participate_orange.png) no-repeat;
+  background-size: 100% 100%;
+}
+.canyu-text{
+  font-size: 36px;
+}
+.list-text-vertical{
+  overflow:hidden; 
+  text-overflow:ellipsis; 
+  white-space:nowrap;
+}
+.about-text i{
+  margin-top: -5px;
+  display: inline-block;
+  width: 24px;
+  height: 24px;
+  vertical-align:middle;
+}
+.about-text i.about-qq{
+  background: url(about.png) no-repeat -8px -10px;
+}
+.about-text i.about-phone{
+  background: url(about.png) no-repeat -8px -40px;
+}
+.about-text i.about-tel{
+  background: url(about.png) no-repeat -8px -70px;
+}
+.about-text span{
+  font-size: 1.2rem;
+}
+/*@media (min-width: 768px){
+  .weixin-erweima img{
+    width:90%; 
+    height:auto;
+  }
+}*/
+.weixin-erweima img{
+  width:75%; 
+  height:auto;
+}
+.weixin-erweima span{
+  display: inline-block;
+  width: 75%;
+}
+.small-text{
+  font-size: 0.75rem !important;
+  font-weight: 400;
 }

BIN
app/public/images/juecedaping01.png


BIN
app/public/images/juecedaping02.png


BIN
app/public/images/juecedaping03.png


BIN
app/public/images/juecedaping04.png


BIN
app/public/images/not_Approve.png


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

@@ -262,7 +262,8 @@ $(document).ready(function () {
         for (let i = 0; i < l.length; i++) {
             t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? dot : '');
         }
-        return t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r);
+        const num = t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r);
+        return num.replace('-,', '-');
     }
 
     function transFormToChinese(num) {

+ 2 - 1
app/public/js/advance_audit.js

@@ -442,5 +442,6 @@ function formatMoney(s, dot = ',', decimal = 2) {
     for (let i = 0; i < l.length; i++) {
         t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? dot : '');
     }
-    return t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r);
+    const num = t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r);
+    return num.replace('-,', '-');
 }

+ 122 - 61
app/public/js/budget_compare.js

@@ -47,7 +47,6 @@ $(document).ready(() => {
         rootId: -1,
     });
 
-
     function compareCode(str1, str2, symbol = '-') {
         if (!str1) {
             return 1;
@@ -152,66 +151,6 @@ $(document).ready(() => {
             compareSpread.refresh();
         }
     });
-
-    $('#sf-select-all').click(function() {
-        $('[name=sf-tender]').prop("checked", this.checked);
-    });
-    $('#select-final-ok').click(() => {
-        const rela = [];
-        const select = $('[name=sf-tender]:checked');
-        for (const s of select) {
-            rela.push(parseInt(s.getAttribute('tid')));
-        }
-        if (rela.length === 0) return;
-        postData(window.location.pathname + '/final', {id: rela}, function(result) {
-            if (spreadSetting.cols.length < 13) {
-                spreadSetting.cols.push(...[
-                    {title: '台账|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'dgn_qty', hAlign: 2, width: 80},
-                    {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'dgn_price', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '决算|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'final_dgn_qty', hAlign: 2, width: 80},
-                    {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'final_dgn_price', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'final_tp', hAlign: 2, width: 80, type: 'Number'},
-                    {title: '增幅%|数量1/数量2', colSpan: '2|1', rowSpan: '1|1', field: 'grow_dgn_qty', hAlign: 2, width: 80},
-                    {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'grow_tp', hAlign: 2, width: 80, type: 'Number'},
-                ]);
-            }
-            const setting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price', 'end_gather_tp'] };
-            compareTree.clearFinal();
-            for (const r of result) {
-                const tree = createNewPathTree('ledger', setting);
-                tree.loadDatas(r);
-                treeCalc.calculateAll(tree);
-                compareTree.loadTree(tree, function (cur, source) {
-                    cur.total_price = ZhCalc.add(cur.total_price, source.total_price);
-                    cur.dgn_qty1 = ZhCalc.add(cur.dgn_qty1, source.dgn_qty1);
-                    cur.dgn_qty2 = ZhCalc.add(cur.dgn_qty2, source.dgn_qty2);
-                    cur.final_dgn_qty1 = ZhCalc.sum([cur.final_dgn_qty1, source.deal_dgn_qty1, source.c_dgn_qty1]);
-                    cur.final_dgn_qty2 = ZhCalc.sum([cur.final_dgn_qty2, source.deal_dgn_qty2, source.c_dgn_qty2]);
-                    cur.final_tp = ZhCalc.add(cur.final_tp, source.end_gather_tp);
-                });
-            }
-            compareTree.afterLoad(node => {
-                node.dgn_price = ZhCalc.div(node.total_price, node.dgn_qty1, 2);
-                node.dgn_qty = node.dgn_qty1
-                    ? (node.dgn_qty2 ? node.dgn_qty1 + '/' + node.dgn_qty2 : node.dgn_qty1)
-                    : (node.dgn_qty2 ? '/' + node.dgn_qty2 : '');
-                node.final_dgn_price = ZhCalc.div(node.final_tp, node.final_dgn_qty1, 2);
-                node.final_dgn_qty = node.final_dgn_qty1
-                    ? (node.final_dgn_qty2 ? node.final_dgn_qty1 + '/' + node.final_dgn_qty2 : node.final_dgn_qty1)
-                    : (node.final_dgn_qty2 ? '/' + node.final_dgn_qty2 : '');
-                node.grow_dgn_qty1 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty1, node.gai_dgn_qty1), node.gai_dgn_qty1, 4), 100);
-                node.grow_dgn_qty2 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty2, node.gai_dgn_qty2), node.gai_dgn_qty2, 4), 100);
-                node.grow_dgn_qty = node.grow_dgn_qty1
-                    ? (node.grow_dgn_qty2 ? node.grow_dgn_qty1 + '/' + node.grow_dgn_qty2 : node.grow_dgn_qty1)
-                    : (node.grow_dgn_qty2 ? '/' + node.grow_dgn_qty2 : '');
-                node.grow_tp = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_tp, node.gai_tp), node.gai_tp, 4), 100);
-            });
-            SpreadJsObj.reLoadSheetHeader(compareSheet);
-            SpreadJsObj.reLoadSheetData(compareSheet);
-            $('#select-final').modal('hide');
-        });
-    });
     // 显示层次
     (function (select, sheet) {
         $(select).click(function () {
@@ -238,4 +177,126 @@ $(document).ready(() => {
             }, 100);
         });
     })('a[name=showLevel]', compareSheet);
+
+
+    class sfObject {
+        constructor() {
+            const self = this;
+            this.selectTree = Tender2Tree.convert(category, tenderList, null, null, function (node, source) {
+                node.lastStageOrder =`第${source.lastStageOrder}期`;
+                node.lastStageStatus = source.lastStageStatus;
+            });
+            const sfSpreadSetting = {
+                cols: [
+                    {title: '选择', field: 'selected', hAlign: 1, width: 40, formatter: '@', cellType: 'checkbox'},
+                    {title: '名称', field: 'name', hAlign: 0, width: 180, formatter: '@', cellType: 'tree'},
+                    {title: '期数', field: 'lastStageOrder', hAlign: 1, width: 60, formatter: '@'},
+                    {title: '审批状态', field: 'lastStageStatus', hAlign: 1, width: 60, formatter: '@'},
+                ],
+                emptyRows: 0,
+                headRows: 1,
+                headRowHeight: [32],
+                defaultRowHeight: 21,
+                headerFont: '12px 微软雅黑',
+                font: '12px 微软雅黑',
+                headColWidth: [30],
+                selectedBackColor: '#fffacd',
+                readOnly: true,
+            };
+            this.spread = SpreadJsObj.createNewSpread($('#sf-spread')[0]);
+            this.sheet = this.spread.getActiveSheet();
+            SpreadJsObj.initSheet(this.sheet, sfSpreadSetting);
+            SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.selectTree);
+
+            this.spread.bind(spreadNS.Events.ButtonClicked, function (e, info) {
+                if (!info.sheet.zh_setting) return;
+
+                const col = info.sheet.zh_setting.cols[info.col];
+                if (col.field !== 'selected') return;
+
+                const node = SpreadJsObj.getSelectObject(info.sheet);
+                self.selectNode(node, !node[col.field]);
+                SpreadJsObj.reloadColData(info.sheet, 0);
+            });
+
+
+            $('#sf-select-all').click(function() {
+                for (const n of self.selectTree.nodes) {
+                    n.selected = this.checked;
+                }
+                SpreadJsObj.reloadColData(self.sheet, 0);
+            });
+            $('#select-final-ok').click(() => {
+                const rela = self.getSelects();
+                if (rela.length === 0) return;
+                postData(window.location.pathname + '/final', {id: rela}, function(result) {
+                    if (spreadSetting.cols.length < 13) {
+                        spreadSetting.cols.push(...[
+                            {title: '台账|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'dgn_qty', hAlign: 2, width: 80},
+                            {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'dgn_price', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '决算|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'final_dgn_qty', hAlign: 2, width: 80},
+                            {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'final_dgn_price', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'final_tp', hAlign: 2, width: 80, type: 'Number'},
+                            {title: '增幅%|数量1/数量2', colSpan: '2|1', rowSpan: '1|1', field: 'grow_dgn_qty', hAlign: 2, width: 80},
+                            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'grow_tp', hAlign: 2, width: 80, type: 'Number'},
+                        ]);
+                    }
+                    const setting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price', 'end_gather_tp'] };
+                    compareTree.clearFinal();
+                    for (const r of result) {
+                        const tree = createNewPathTree('ledger', setting);
+                        tree.loadDatas(r);
+                        treeCalc.calculateAll(tree);
+                        compareTree.loadTree(tree, function (cur, source) {
+                            cur.total_price = ZhCalc.add(cur.total_price, source.total_price);
+                            cur.dgn_qty1 = ZhCalc.add(cur.dgn_qty1, source.dgn_qty1);
+                            cur.dgn_qty2 = ZhCalc.add(cur.dgn_qty2, source.dgn_qty2);
+                            cur.final_dgn_qty1 = ZhCalc.sum([cur.final_dgn_qty1, source.deal_dgn_qty1, source.c_dgn_qty1]);
+                            cur.final_dgn_qty2 = ZhCalc.sum([cur.final_dgn_qty2, source.deal_dgn_qty2, source.c_dgn_qty2]);
+                            cur.final_tp = ZhCalc.add(cur.final_tp, source.end_gather_tp);
+                        });
+                    }
+                    compareTree.afterLoad(node => {
+                        node.dgn_price = ZhCalc.div(node.total_price, node.dgn_qty1, 2);
+                        node.dgn_qty = node.dgn_qty1
+                            ? (node.dgn_qty2 ? node.dgn_qty1 + '/' + node.dgn_qty2 : node.dgn_qty1)
+                            : (node.dgn_qty2 ? '/' + node.dgn_qty2 : '');
+                        node.final_dgn_price = ZhCalc.div(node.final_tp, node.final_dgn_qty1, 2);
+                        node.final_dgn_qty = node.final_dgn_qty1
+                            ? (node.final_dgn_qty2 ? node.final_dgn_qty1 + '/' + node.final_dgn_qty2 : node.final_dgn_qty1)
+                            : (node.final_dgn_qty2 ? '/' + node.final_dgn_qty2 : '');
+                        node.grow_dgn_qty1 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty1, node.gai_dgn_qty1), node.gai_dgn_qty1, 4), 100);
+                        node.grow_dgn_qty2 = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_dgn_qty2, node.gai_dgn_qty2), node.gai_dgn_qty2, 4), 100);
+                        node.grow_dgn_qty = node.grow_dgn_qty1
+                            ? (node.grow_dgn_qty2 ? node.grow_dgn_qty1 + '/' + node.grow_dgn_qty2 : node.grow_dgn_qty1)
+                            : (node.grow_dgn_qty2 ? '/' + node.grow_dgn_qty2 : '');
+                        node.grow_tp = ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node.final_tp, node.gai_tp), node.gai_tp, 4), 100);
+                    });
+                    SpreadJsObj.reLoadSheetHeader(compareSheet);
+                    SpreadJsObj.reLoadSheetData(compareSheet);
+                    $('#select-final').modal('hide');
+                });
+            });
+        }
+        selectNode(node, select) {
+            const posterity = this.selectTree.getPosterity(node);
+            posterity.unshift(node);
+            for (const p of posterity) {
+                p.selected = select;
+            }
+        }
+        getSelects() {
+            const select = [];
+            for (const n of this.selectTree.nodes) {
+                if ((!n.children || n.children.length === 0) && n.selected) select.push(n.tid);
+            }
+            return select;
+        }
+    }
+
+    let sfSelect;
+    $('#select-final').on('shown.bs.modal', () => {
+        if (!sfSelect) sfSelect = new sfObject();
+    });
 });

+ 5 - 3
app/public/js/budget_detail.js

@@ -625,7 +625,7 @@ $(document).ready(() => {
             budgetTreeOpr.refreshTree(budgetSheet, refreshNode);
             if (refreshNode.create && refreshNode.create.length > 0) {
                 budgetSheet.setSelection(refreshNode.create[refreshNode.create.length - 1].index, sel.col, sel.rowCount, sel.colCount);
-                SpreadJsObj.reloadRowsBackColor(budgetSheet, [sel.row, refreshNode.create[refreshNode.create.length - 1].index]);
+                SpreadJsObj.reloadRowsBackColor(budgetSheet, [sel.row, budgetTree.nodes.indexOf(mainNode), refreshNode.create[refreshNode.create.length - 1].index]);
             } else {
                 const node = _.find(budgetTree.nodes, {code: stdNode.code, name: stdNode.name});
                 if (node) {
@@ -640,6 +640,7 @@ $(document).ready(() => {
     const stdXmjSetting = {
         selector: '#std-xmj',
         stdType: 'xmj',
+        libs: stdChapters,
         treeSetting: {
             id: 'chapter_id',
             pid: 'pid',
@@ -672,6 +673,7 @@ $(document).ready(() => {
     const stdGclSetting = {
         selector: '#std-gcl',
         stdType: 'gcl',
+        libs: stdBills,
         treeSetting: {
             id: 'bill_id',
             pid: 'pid',
@@ -714,10 +716,10 @@ $(document).ready(() => {
             tabPanel.addClass('active');
             showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#std-xmj') {
-                if (!stdXmj) stdXmj = new stdLib(stdXmjSetting);
+                if (!stdXmj) stdXmj = $.stdLib(stdXmjSetting);
                 stdXmj.spread.refresh();
             } else if (tab.attr('content') === '#std-gcl') {
-                if (!stdGcl) stdGcl = new stdLib(stdGclSetting);
+                if (!stdGcl) stdGcl = $.stdLib(stdGclSetting);
                 stdGcl.spread.refresh();
             } else if (tab.attr('content') === '#search') {
                 if (!searchBudget) {

+ 89 - 31
app/public/js/budget_list.js

@@ -48,19 +48,6 @@ const delBudget = function () {
     });
 };
 
-const relaTender = function () {
-    // todo 选择标段
-    const rela = [];
-    const select = $('[name=select-rela-check]:checked');
-    for (const s of select) {
-        rela.push(s.getAttribute('tid'));
-    }
-    postData('/budget/save', { id: curBudget.id, rela_tender: rela.join(',') }, function () {
-        $(`[bid=${curBudget.id}]`)[0].setAttribute('rela-tender', rela.join(','));
-        $('#select-rela').modal('hide');
-    });
-};
-
 
 $(document).ready(() => {
     autoFlashHeight();
@@ -70,24 +57,6 @@ $(document).ready(() => {
     $('#del-budget').on('show.bs.modal', () => {
         $('#del-budget-name').text(curBudget.name);
     });
-    $('#sr-select-all').click(function () {
-        $('[name=select-rela-check]').prop("checked", this.checked);
-    });
-    $('#select-rela').on('show.bs.modal', () => {
-        $('#sr-select-all')[0].checked = false;
-        $('#valid-rela-tender').html('');
-        postData(`/budget/rela?id=${curBudget.id}`, {}, tenders => {
-            const rela = curBudget.rela_tender ? curBudget.rela_tender.split(',') : [];
-            const html = [];
-            for (const t of tenders) {
-                html.push(`<tr><td class="text-center"><input type="checkbox" name="select-rela-check" tid="${t.id}"></td><td>${t.name}</td><td>第${t.lastStageOrder}期</td><td>${t.lastStageStatus}</td></tr>`);
-            }
-            $('#valid-rela-tender').html(html.join(''));
-            for (const r of rela) {
-                $(`[tid=${r}]`).attr("checked", "checked");
-            }
-        });
-    });
 
     let timer = null;
     let oldSearchVal = null;
@@ -214,4 +183,93 @@ $(document).ready(() => {
             mem.permission.splice(mem.permission.indexOf(permissionConst[this.getAttribute('ptype')].value), 1);
         }
     });
+
+    class srObject {
+        constructor() {
+            const self = this;
+            this.selectTree = null;
+            const srSpreadSetting = {
+                cols: [
+                    {title: '选择', field: 'selected', hAlign: 1, width: 40, formatter: '@', cellType: 'checkbox'},
+                    {title: '名称', field: 'name', hAlign: 0, width: 180, formatter: '@', cellType: 'tree'},
+                    {title: '期数', field: 'lastStageOrder', hAlign: 1, width: 60, formatter: '@'},
+                    {title: '审批状态', field: 'lastStageStatus', hAlign: 1, width: 60, formatter: '@'},
+                ],
+                emptyRows: 0,
+                headRows: 1,
+                headRowHeight: [32],
+                defaultRowHeight: 21,
+                headerFont: '12px 微软雅黑',
+                font: '12px 微软雅黑',
+                headColWidth: [30],
+                selectedBackColor: '#fffacd',
+                readOnly: true,
+            };
+            this.spread = SpreadJsObj.createNewSpread($('#sr-spread')[0]);
+            this.sheet = this.spread.getActiveSheet();
+            SpreadJsObj.initSheet(this.sheet, srSpreadSetting);
+
+            this.spread.bind(spreadNS.Events.ButtonClicked, function (e, info) {
+                if (!info.sheet.zh_setting) return;
+
+                const col = info.sheet.zh_setting.cols[info.col];
+                if (col.field !== 'selected') return;
+
+                const node = SpreadJsObj.getSelectObject(info.sheet);
+                self.selectNode(node, !node[col.field]);
+                SpreadJsObj.reloadColData(info.sheet, 0);
+            });
+
+
+
+            $('#sr-select-all').click(function () {
+                if (!self.selectTree) return;
+                for (const n of self.selectTree.nodes) {
+                    n.selected = this.checked;
+                }
+                SpreadJsObj.reloadColData(self.sheet, 0);
+            });
+            $('#select-rela-ok').click(() => {
+                const rela = self.getSelects();
+                postData('/budget/save', { id: curBudget.id, rela_tender: rela.join(',') }, function () {
+                    $(`[bid=${curBudget.id}]`)[0].setAttribute('rela-tender', rela.join(','));
+                    $('#select-rela').modal('hide');
+                });
+            });
+        }
+        selectNode(node, select) {
+            const posterity = this.selectTree.getPosterity(node);
+            posterity.unshift(node);
+            for (const p of posterity) {
+                p.selected = select;
+            }
+        }
+        getSelects() {
+            const select = [];
+            for (const n of this.selectTree.nodes) {
+                if ((!n.children || n.children.length === 0) && n.selected) select.push(n.tid);
+            }
+            return select;
+        }
+        init() {
+            $('#sr-select-all')[0].checked = false;
+            const self = this;
+            postData(`/budget/rela?id=${curBudget.id}`, {}, tenders => {
+                const rela = curBudget.rela_tender ? curBudget.rela_tender.split(',') : [];
+                self.selectTree = Tender2Tree.convert(category, tenders, null, null, function (node, source) {
+                    node.lastStageOrder = `第${source.lastStageOrder}期`;
+                    node.lastStageStatus = source.lastStageStatus;
+                });
+                for (const node of self.selectTree.nodes) {
+                    node.selected = rela.indexOf(node.tid + '') >= 0;
+                }
+                SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.selectTree);
+            });
+        }
+    }
+    let srSelect;
+    $('#select-rela').on('shown.bs.modal', () => {
+        if (!srSelect) srSelect = new srObject();
+        srSelect.init();
+    });
 });

+ 4 - 4
app/public/js/change_information.js

@@ -180,8 +180,8 @@ $(document).ready(() => {
             // const cid = $('#changeId').val();
             // $('#downloadZip').attr('href', `/tender/${tid}/change/${cid}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
             // $('#downloadZip')[0].click();
-            if (fileIds.length > 10) {
-              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`);
+            if (fileIds.length > 20) {
+              return toastr.warning(`最大允许20个文件(当前${fileIds.length}个)`);
             }
             const tid = $('#tenderId').val();
             const cid = $('#changeId').val();
@@ -297,7 +297,7 @@ function findDecimal(unit) {
 // 生成附件列表
 function getAllList(currPageNum = 1) {
     // 每页最多几个附件
-    const pageCount = 15;
+    const pageCount = 20;
     // 附件总数
     const total = attData.length;
     // 总页数
@@ -312,7 +312,7 @@ function getAllList(currPageNum = 1) {
     for(const [index,att] of currPageAttData.entries()) {
         html += `<tr>
         <td width="25"><input type="checkbox" class="check-file" file-id=${att.id}></td>
-        <td>${((currPageNum-1)*15)+index+1}</td>
+        <td>${((currPageNum-1)*pageCount)+index+1}</td>
         <td><a href="javascript:void(0)" class="pl-0 col-11 att-file-name" file-id=${att.id}>${att.filename}${att.fileext}</a></td>
         <td>${moment(att.in_time * 1000).format('YYYY-MM-DD')}<br>${bytesToSize(att.filesize)}</td>
         <td>

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

@@ -2378,6 +2378,7 @@ $(document).ready(() => {
     const stdXmjSetting = {
         selector: '#std-xmj',
         stdType: 'xmj',
+        libs: stdChapters,
         treeSetting: {
             id: 'chapter_id',
             pid: 'pid',
@@ -2409,6 +2410,7 @@ $(document).ready(() => {
     const stdGclSetting = {
         selector: '#std-gcl',
         stdType: 'gcl',
+        libs: stdBills,
         treeSetting: {
             id: 'bill_id',
             pid: 'pid',
@@ -2451,12 +2453,12 @@ $(document).ready(() => {
             showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#std-xmj') {
                 if (!stdXmj) {
-                    stdXmj = new stdLib(stdXmjSetting);
+                    stdXmj = $.stdLib(stdXmjSetting);
                 }
                 stdXmj.spread.refresh();
             } else if (tab.attr('content') === '#std-gcl') {
                 if (!stdGcl) {
-                    stdGcl = new stdLib(stdGclSetting);
+                    stdGcl = $.stdLib(stdGclSetting);
                 }
                 stdGcl.spread.refresh();
             } else if (tab.attr('content') === '#deal-bills') {

+ 95 - 0
app/public/js/datacollect_scroll.js

@@ -1,4 +1,5 @@
 window.onload = roll(50);
+window.onload = roll2(50);
 function roll(t) {
     var ul1 = document.getElementById("comment1");
     var ul2 = document.getElementById("comment2");
@@ -23,6 +24,7 @@ function rollStart() {
     var ul1 = document.getElementById("comment1");
     var ul2 = document.getElementById("comment2");
     var ulbox = document.getElementById("review_box");
+    // console.log(ulbox.scrollTop);
     // 正常滚动不断给scrollTop的值+1,当滚动高度大于列表内容高度时恢复为0
     if (ulbox.scrollTop >= ul1.scrollHeight) {
         ulbox.scrollTop = 0;
@@ -30,3 +32,96 @@ function rollStart() {
         ulbox.scrollTop++;
     }
 }
+function roll2(t) {
+    var ul3 = document.getElementById("comment3");
+    var ul4 = document.getElementById("comment4");
+    var ulbox2 = document.getElementById("review_box2");
+    ul4.innerHTML = ul3.innerHTML;
+    ulbox2.scrollTop = 0; // 开始无滚动时设为0
+    // var timer = setInterval(rollStart, t); // 设置定时器,参数t用在这为间隔时间(单位毫秒),参数t越小,滚动速度越快
+    var timer2 = setInterval(rollStart2, '40');
+    ulbox2.onmouseover = function () {
+        clearInterval(timer2);
+    }
+    // 鼠标移出div后继续滚动
+    ulbox2.onmouseout = function () {
+        // timer = setInterval(rollStart, t);
+        timer2 = setInterval(rollStart2, '40');
+    }
+}
+function rollStart2() {
+    // 上面声明的DOM对象为局部对象需要再次声明
+    var ul3 = document.getElementById("comment3");
+    var ul4 = document.getElementById("comment4");
+    var ulbox2 = document.getElementById("review_box2");
+    // console.log(ulbox2.scrollTop);
+    // 正常滚动不断给scrollTop的值+1,当滚动高度大于列表内容高度时恢复为0
+    if (ulbox2.scrollTop >= ul3.scrollHeight) {
+        ulbox2.scrollTop = 0;
+    } else {
+        ulbox2.scrollTop++;
+    }
+}
+
+// tableScroll('tableId', '100%', 30, 10);
+var MyMarhq;
+function tableScroll(tableid, hei, speed, len) {
+    clearTimeout(MyMarhq);
+    $('#' + tableid).parent().find('.tableid_').remove()
+    $('#' + tableid).parent().prepend(
+        '<table class="tableid_"><thead>' + $('#' + tableid + ' thead').html() + '</thead></table>'
+    ).css({
+        'position': 'relative',
+        'overflow': 'hidden',
+        'height': hei + 'px'
+    })
+    $(".tableid_").find('th').each(function(i) {
+        $(this).css('width', $('#' + tableid).find('th:eq(' + i + ')').width());
+    });
+    $(".tableid_").css({
+        'position': 'absolute',
+        'top': 0,
+        'left': 0,
+        'z-index': 9
+    })
+    $('#' + tableid).css({
+        'position': 'absolute',
+        'top': 0,
+        'left': 0,
+        'z-index': 1
+    })
+
+    if ($('#' + tableid).find('tbody tr').length > len) {
+        if ($('#' + tableid).find('tbody tr').length > 30) {
+            $('#' + tableid).find('tbody').html($('#' + tableid).find('tbody').html() + $('#' + tableid).find('tbody').html());
+        } else {
+            $('#' + tableid).find('tbody').html($('#' + tableid).find('tbody').html() + $('#' + tableid).find('tbody').html() + $('#' + tableid).find('tbody').html() + $('#' + tableid).find('tbody').html());
+        }
+        $(".tableid_").css('top', 0);
+        $('#' + tableid).css('top', 0);
+        var tblTop = 0;
+        var outerHeight = $('#' + tableid).find('tbody').find("tr").outerHeight();
+        function Marqueehq() {
+            if (tblTop <= -outerHeight * $('#' + tableid).find('tbody').find("tr").length) {
+                tblTop = 0;
+            } else {
+                tblTop -= 1;
+            }
+            $('#' + tableid).css('margin-top', tblTop + 'px');
+            clearTimeout(MyMarhq);
+            MyMarhq = setTimeout(function() {
+                Marqueehq()
+            }, speed);
+        }
+
+        MyMarhq = setTimeout(Marqueehq, speed);
+        $('#' + tableid).find('tbody').hover(function() {
+            clearTimeout(MyMarhq);
+        }, function() {
+            clearTimeout(MyMarhq);
+            if ($('#' + tableid).find('tbody tr').length > len) {
+                MyMarhq = setTimeout(Marqueehq, speed);
+            }
+        })
+    }
+};

+ 42 - 30
app/public/js/ledger.js

@@ -414,6 +414,7 @@ $(document).ready(function() {
                         self.refreshTree(sheet, refreshNode);
                         self.refreshOperationValid(sheet);
                         posOperationObj.loadCurPosData();
+                        billsTag.afterDeleteBills(refreshNode.delete);
                     });
                 });
             }
@@ -2293,7 +2294,10 @@ $(document).ready(function() {
             treeOperationObj.refreshTree(mainSheet, refreshNode);
             if (refreshNode.create && refreshNode.create.length > 0) {
                 mainSheet.setSelection(refreshNode.create[refreshNode.create.length - 1].index, sel.col, sel.rowCount, sel.colCount);
-                SpreadJsObj.reloadRowsBackColor(mainSheet, [sel.row, refreshNode.create[refreshNode.create.length - 1].index]);
+                const refreshRow = [sel.row, refreshNode.create[refreshNode.create.length - 1].index];
+                const curIndex = mainTree.nodes.indexOf(mainNode);
+                if (sel.row !== curIndex && curIndex >= 0) refreshRow.push(curIndex);
+                SpreadJsObj.reloadRowsBackColor(mainSheet, refreshRow);
             } else {
                 const node = _.find(ledgerTree.nodes, {code: stdNode.code, name: stdNode.name});
                 if (node) {
@@ -2309,6 +2313,7 @@ $(document).ready(function() {
     const stdXmjSetting = {
         selector: '#std-xmj',
         stdType: 'xmj',
+        libs: stdChapters,
         treeSetting: {
             id: 'chapter_id',
             pid: 'pid',
@@ -2340,6 +2345,7 @@ $(document).ready(function() {
     const stdGclSetting = {
         selector: '#std-gcl',
         stdType: 'gcl',
+        libs: stdBills,
         treeSetting: {
             id: 'bill_id',
             pid: 'pid',
@@ -2383,14 +2389,12 @@ $(document).ready(function() {
             showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#std-xmj') {
                 if (!stdXmj) {
-                    stdXmj = new stdLib(stdXmjSetting);
-                    //stdXmj.loadLib($('select', '#std-xmj').val());
+                    stdXmj = $.stdLib(stdXmjSetting);
                 }
                 stdXmj.spread.refresh();
             } else if (tab.attr('content') === '#std-gcl') {
                 if (!stdGcl) {
-                    stdGcl = new stdLib(stdGclSetting);
-                    //stdGcl.loadLib($('select', '#std-gcl').val());
+                    stdGcl = $.stdLib(stdGclSetting);
                 }
                 stdGcl.spread.refresh();
             } else if (tab.attr('content') === '#deal-bills') {
@@ -2453,7 +2457,7 @@ $(document).ready(function() {
             } else if (tab.attr('content') === '#check-list') {
                 checkList.spread.refresh();
             } else if (tab.attr('content') === '#fujian') {
-              $('#showAttachment').hide()
+              $('#showAttachment').hide();
               const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
               getNodeList(node.id);
               getAllList();
@@ -2926,7 +2930,7 @@ $(document).ready(function() {
                             }
                             qdSheet.setSelection(sel.row, sel.col, 1, 1);
                         },
-                    },
+                    }
                 }
             });
             // 拉取签约清单数据
@@ -2938,7 +2942,7 @@ $(document).ready(function() {
                 });
             }
             // 双击签约清单,自动添加到清单编号窗口
-            this.dealSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, function (e, info) {
+            this.dealSpread.bind(spreadNS.Events.CellDoubleClick, function (e, info) {
                 const deal = info.sheet.zh_data[info.row];
                 const qdSheet = self.qdSpread.getActiveSheet(), posSheet = self.posSpread.getActiveSheet();
                 const sel = qdSheet.getSelections()[0];
@@ -2957,30 +2961,38 @@ $(document).ready(function() {
                 }
                 qdSheet.setSelection(sel.row + 1, sel.col, 1, 1);
             });
-            this.qdSpread.bind(spreadNS.Events.ClipboardPasted, function (e, info) {
-                const billsCount = info.sheet.getRowCount(), posSheet = self.posSpread.getActiveSheet();
-                const count = posSheet.getColumnCount() - 2;
-                if (billsCount > count) {
-                    posSheet.setColumnCount(billsCount + 2);
-                    for (let i = count + 1; i <= billsCount; i++) {
-                        info.sheet.getCell(i - 1, 0, spreadNS.SheetArea.rowHeader).text('清单' + i);
+            this.qdSpread.bind(spreadNS.Events.ClipboardPasting, function (e, info) {
+                info.cancel = true;
+                const transpose = $('[name=batch-transpose]')[0].checked;
+                const pasteData = SpreadJsObj.analysisPasteText(info.pasteData.text, transpose);
+
+                const billsSheet = info.sheet, posSheet = self.posSpread.getActiveSheet();
+                const billsCount = info.sheet.getRowCount(), finalCount = info.cellRange.row + pasteData.length + 1;
+                SpreadJsObj.beginMassOperation(billsSheet);
+                if (finalCount > billsCount) {
+                    billsSheet.setRowCount(finalCount);
+                    posSheet.setColumnCount(finalCount + 2);
+                    for (let i = billsCount - 1; i <= finalCount; i++) {
+                        billsSheet.getCell(i - 1, 0, spreadNS.SheetArea.rowHeader).text('清单' + i);
                         posSheet.getCell(0, i + 2 - 1, spreadNS.SheetArea.colHeader).text('清单' + i);
                     }
                 }
-                if (info.cellRange.col === 0 && info.cellRange.colCount === 1) {
-                    const dealBills = self.dealSpread.getActiveSheet().zh_data;
-                    if (dealBills && dealBills.length > 0) {
-                        for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
-                            const curRow = iRow + info.cellRange.row;
-                            const bills = _.find(dealBills, {code: info.sheet.getText(curRow, 0)});
-                            if (bills) {
-                                info.sheet.getCell(curRow, 1).value(bills.name);
-                                info.sheet.getCell(curRow, 2).value(bills.unit);
-                                info.sheet.getCell(curRow, 3).value(bills.unit_price);
-                            }
+                for (let iRow = 0; iRow < pasteData.length; iRow++) {
+                    const curRow = iRow + info.cellRange.row;
+                    pasteData[iRow].forEach((value, iCol) => {
+                        billsSheet.getCell(curRow, iCol + info.cellRange.col).value(value);
+                    });
+                    if ([0, 1].indexOf(info.cellRange.col) >= 0) {
+                        const dealBills = self.dealSpread.getActiveSheet().zh_data;
+                        const bills = _.find(dealBills, {code: billsSheet.getText(curRow, 0)});
+                        if (bills) {
+                            billsSheet.getCell(curRow, 1).value(bills.name);
+                            billsSheet.getCell(curRow, 2).value(bills.unit);
+                            billsSheet.getCell(curRow, 3).value(bills.unit_price);
                         }
                     }
                 }
+                SpreadJsObj.endMassOperation(billsSheet);
             });
             this.posSpread.bind(spreadNS.Events.ClipboardPasted, function (e, info) {
                 const billsCount = info.sheet.getColumnCount() - 2, qdSheet = self.qdSpread.getActiveSheet();
@@ -3622,7 +3634,7 @@ $(document).ready(function() {
       const filename = name.substring(0, name.lastIndexOf("."));
       const fileext = name.substr(name.indexOf("."));
       const filesize = file.size;
-      if (filesize > 10 * 1024 * 1024) {
+      if (filesize > 30 * 1024 * 1024) {
           toastr.error('文件大小过大!');
           $('#change-att-btn').val('');
           return false;
@@ -3668,8 +3680,8 @@ $(document).ready(function() {
       });
 
       if (fileIds.length) {
-        if (fileIds.length > 10) {
-          return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`)
+        if (fileIds.length > 20) {
+          return toastr.warning(`最大允许20个文件(当前${fileIds.length}个)`)
         }
         toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0})
         $(this).attr('disabled', "true")
@@ -3754,7 +3766,7 @@ function getNodeList(node) {
 // 生成所有附件列表
 function getAllList(currPageNum = 1) {
   // 每页最多几个附件
-  const pageCount = 15;
+  const pageCount = 20;
   // 附件总数
   const total = attData.length;
   // 总页数

+ 9 - 5
app/public/js/ledger_check.js

@@ -148,12 +148,16 @@ const ledgerCheckUtil = {
 
             addXmjCheck(topLevel);
         }
-        let check = null;
-        while (xmj.length > 0) {
-            [check, xmj] = _.partition(xmj, x => { return x.code === xmj[0].code; });
-            if (check.length > 1) {
-                error.push(...check);
+        const xmjPart = {}, xmjIndex = [];
+        for (const x of xmj) {
+            if (!xmjPart[x.code]) {
+                xmjPart[x.code] = [];
+                xmjIndex.push(x.code);
             }
+            xmjPart[x.code].push(x);
+        }
+        for (const x of xmjIndex) {
+            if (xmjPart[x].length > 1) error.push(...xmjPart[x]);
         }
         return error;
     },

+ 91 - 46
app/public/js/material.js

@@ -72,13 +72,18 @@ DatePickerCellType.prototype.updateEditor = function (editorContext, cellStyle,
 };
 
 function resetTpTable() {
-    const rate = $('#changeRate').val();
-    const bqhs = ZhCalc.round(ZhCalc.mul(m_tp, 1+rate/100), 2);
-    const jzbqhs = ZhCalc.round(ZhCalc.add(pre_tp_hs, bqhs), 2);
     $('#tp_set').find('td').eq(1).text(ZhCalc.round(m_tp, 2));
     $('#tp_set').find('td').eq(2).text(ZhCalc.round(ZhCalc.add(pre_tp, m_tp), 2));
-    $('#rate_set').find('td').eq(1).text(bqhs !== 0 ? bqhs : '');
-    $('#rate_set').find('td').eq(2).text(jzbqhs !== 0 ? jzbqhs : '');
+    if (materialTax) {
+        $('#rate_set').find('td').eq(1).text(ZhCalc.round(m_tax_tp, 2));
+        $('#rate_set').find('td').eq(2).text(ZhCalc.round(ZhCalc.add(m_tax_pre_tp, m_tax_tp), 2));
+    } else {
+        const rate = $('#changeRate').val();
+        const bqhs = ZhCalc.round(ZhCalc.mul(m_tp, 1+rate/100), 2);
+        const jzbqhs = ZhCalc.round(ZhCalc.add(pre_tp_hs, bqhs), 2);
+        $('#rate_set').find('td').eq(1).text(bqhs !== 0 ? bqhs : '');
+        $('#rate_set').find('td').eq(2).text(jzbqhs !== 0 ? jzbqhs : '');
+    }
 }
 function getPasteHint (str, row = '') {
     let returnObj = str;
@@ -99,27 +104,6 @@ $(document).ready(() => {
     autoFlashHeight();
     const materialSpread = SpreadJsObj.createNewSpread($('#material-spread')[0]);
     const materialSpreadSetting = {
-        cols: [
-            {title: '调差类型', colSpan: '1', rowSpan: '2', field: 't_type', hAlign: 1, width: 80, formatter: '@', readOnly: 'readOnly.isUsed', cellType: 'customizeCombo', comboItems: materialType.t_type, cellTypeKey: 1},
-            {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 60, formatter: '@', readOnly: 'readOnly.isUsed'},
-            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@', readOnly: 'readOnly.isEdit'},
-            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: 'readOnly.isEdit'},
-            {title: '规格', colSpan: '1', rowSpan: '2', field: 'spec', hAlign: 0, width: 180, formatter: '@', readOnly: 'readOnly.isEdit'},
-            {title: '工料分类', colSpan: '1', rowSpan: '2', field: 'm_type', hAlign: 1, width: 60, readOnly: 'readOnly.isEdit', cellType: 'customizeCombo', comboItems: materialType.m_type, cellTypeKey: 2},
-            {title: '本期应耗数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 100, type: 'Number', readOnly: true},
-            {title: '基准价', colSpan: '1', rowSpan: '2', field: 'basic_price', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.isEdit'},
-            {title: '基准时间', colSpan: '1', rowSpan: '2', field: 'basic_times', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.isEdit'},
-            {title: '本期信息价|单价', colSpan: '3|1', rowSpan: '1|1', field: 'msg_tp', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.msg_tp'},
-            {title: '|时间', colSpan: '|1', rowSpan: '|1', field: 'msg_times', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.remark'},
-            {title: '|价差', colSpan: '|1', rowSpan: '|1', field: 'msg_spread', hAlign: 2, width: 60, type: 'Number', readOnly: true, getValue: 'getValue.msg_spread'},
-            {title: '本期材料调差|上涨幅度(%)', colSpan: '4|1', rowSpan: '1|1', field: 'm_up_risk', hAlign: 2, width: 100, type: 'Number', readOnly: 'readOnly.isEdit'},
-            {title: '|下跌幅度(%)', colSpan: '|1', rowSpan: '|1', field: 'm_down_risk', hAlign: 2, width: 100, type: 'Number', readOnly: 'readOnly.isEdit'},
-            {title: '|有效价差', colSpan: '|1', rowSpan: '|1', field: 'm_spread', hAlign: 2, width: 80, type: 'Number', readOnly: true, getValue: 'getValue.m_spread'},
-            {title: '|调差金额', colSpan: '|1', rowSpan: '|1', field: 'm_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, getValue: 'getValue.m_tp'},
-            {title: '截止上期调差金额', colSpan: '1', rowSpan: '2', field: 'pre_tp', hAlign: 2, width: 120, type: 'Number', readOnly: true},
-            {title: '备注', colSpan: '1', rowSpan: '2', field: 'remark', hAlign: 0, width: 60, formatter: '@', readOnly: 'readOnly.remark'},
-            {title: '是否汇总', colSpan: '1', rowSpan: '2', field: 'is_summary', hAlign: 1, width: 60, cellType: 'checkbox', readOnly: 'readOnly.isEdit'},
-        ],
         emptyRows: 0,
         headRows: 2,
         headRowHeight: [25, 25],
@@ -128,7 +112,49 @@ $(document).ready(() => {
         font: '12px 微软雅黑',
         readOnly: readOnly,
     };
-
+    let materialSpreadSettingCols = [
+        {title: '调差类型', colSpan: '1', rowSpan: '2', field: 't_type', hAlign: 1, width: 60, formatter: '@', readOnly: 'readOnly.isUsed', cellType: 'customizeCombo', comboItems: materialType.t_type, cellTypeKey: 1},
+        {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 60, formatter: '@', readOnly: 'readOnly.isUsed'},
+        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 150, formatter: '@', readOnly: 'readOnly.isEdit'},
+        {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: 'readOnly.isEdit'},
+        {title: '规格', colSpan: '1', rowSpan: '2', field: 'spec', hAlign: 0, width: 150, formatter: '@', readOnly: 'readOnly.isEdit'},
+        {title: '工料分类', colSpan: '1', rowSpan: '2', field: 'm_type', hAlign: 1, width: 60, readOnly: 'readOnly.isEdit', cellType: 'customizeCombo', comboItems: materialType.m_type, cellTypeKey: 2},
+    ];
+    if (materialTax) {
+        materialSpreadSettingCols.push({title: '税率(%)', colSpan: '1', rowSpan: '2', field: 'm_tax', hAlign: 2, width: 50, type: 'Number', readOnly: 'readOnly.isEdit'});
+    }
+    materialSpreadSettingCols = _.concat(materialSpreadSettingCols, [
+        {title: '本期应耗数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 90, type: 'Number', readOnly: true},
+        {title: '基准价', colSpan: '1', rowSpan: '2', field: 'basic_price', hAlign: 2, width: 50, type: 'Number', readOnly: 'readOnly.isEdit'},
+        {title: '基准时间', colSpan: '1', rowSpan: '2', field: 'basic_times', hAlign: 0, width: 70, formatter: '@', readOnly: 'readOnly.isEdit'},
+        {title: '本期信息价|单价', colSpan: '3|1', rowSpan: '1|1', field: 'msg_tp', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.msg_tp'},
+        {title: '|时间', colSpan: '|1', rowSpan: '|1', field: 'msg_times', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.remark'},
+        {title: '|价差', colSpan: '|1', rowSpan: '|1', field: 'msg_spread', hAlign: 2, width: 60, type: 'Number', readOnly: true, getValue: 'getValue.msg_spread'},]
+    );
+    if (materialTax) {
+        materialSpreadSettingCols = _.concat(materialSpreadSettingCols, [
+            {title: '本期材料调差|上涨幅度(%)', colSpan: '5|1', rowSpan: '1|1', field: 'm_up_risk', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.isEdit'},
+            {title: '|下跌幅度(%)', colSpan: '|1', rowSpan: '|1', field: 'm_down_risk', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.isEdit'},
+            {title: '|有效价差', colSpan: '|1', rowSpan: '|1', field: 'm_spread', hAlign: 2, width: 80, type: 'Number', readOnly: true, getValue: 'getValue.m_spread'},
+            {title: '|调差金额', colSpan: '|1', rowSpan: '|1', field: 'm_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, getValue: 'getValue.m_tp'},
+            {title: '|调差金额(材料税)', colSpan: '|1', rowSpan: '|1', field: 'm_tax_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, getValue: 'getValue.m_tax_tp'},
+            {title: '截止上期|调差金额', colSpan: '2|1', rowSpan: '1|1', field: 'pre_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '|调差金额(材料税)', colSpan: '|1', rowSpan: '|1', field: 'tax_pre_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'remark', hAlign: 0, width: 50, formatter: '@', readOnly: 'readOnly.remark'},
+            {title: '是否汇总', colSpan: '1', rowSpan: '2', field: 'is_summary', hAlign: 1, width: 60, cellType: 'checkbox', readOnly: 'readOnly.isEdit'}
+        ])
+    } else {
+        materialSpreadSettingCols = _.concat(materialSpreadSettingCols, [
+            {title: '本期材料调差|上涨幅度(%)', colSpan: '4|1', rowSpan: '1|1', field: 'm_up_risk', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.isEdit'},
+            {title: '|下跌幅度(%)', colSpan: '|1', rowSpan: '|1', field: 'm_down_risk', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.isEdit'},
+            {title: '|有效价差', colSpan: '|1', rowSpan: '|1', field: 'm_spread', hAlign: 2, width: 80, type: 'Number', readOnly: true, getValue: 'getValue.m_spread'},
+            {title: '|调差金额', colSpan: '|1', rowSpan: '|1', field: 'm_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true, getValue: 'getValue.m_tp'},
+            {title: '截止上期|调差金额', colSpan: '1|1', rowSpan: '1|1', field: 'pre_tp', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'remark', hAlign: 0, width: 50, formatter: '@', readOnly: 'readOnly.remark'},
+            {title: '是否汇总', colSpan: '1', rowSpan: '2', field: 'is_summary', hAlign: 1, width: 60, cellType: 'checkbox', readOnly: 'readOnly.isEdit'}
+        ])
+    }
+    materialSpreadSetting.cols = materialSpreadSettingCols;
     const spCol = _.find(materialSpreadSetting.cols, {field: 'quantity'});
     spCol.readOnly = true;
     spCol.cellType = 'activeImageBtn';
@@ -192,6 +218,10 @@ $(document).ready(() => {
             },
             m_tp: function (data) {
                 return ZhCalc.round(ZhCalc.mul(materialCol.getValue.m_spread(data), data.quantity), 2);
+            },
+            m_tax_tp: function (data) {
+                const m_tp = ZhCalc.round(ZhCalc.mul(materialCol.getValue.m_spread(data), data.quantity), 2);
+                return data.m_tax ? ZhCalc.round(ZhCalc.mul(m_tp, (1+ZhCalc.div(data.m_tax, 100))), 2) : m_tp;
             }
         },
         readOnly: {
@@ -257,6 +287,9 @@ $(document).ready(() => {
             const select = SpreadJsObj.getSelectObject(sheet);
             postData(window.location.pathname + '/save', {type: 'del', id: select.id}, function (result) {
                 m_tp = result.m_tp;
+                if (materialTax) {
+                    m_tax_tp = result.m_tax_tp;
+                }
                 resetTpTable();
                 const index = materialBillsData.indexOf(select);
                 materialBillsData.splice(index, 1);
@@ -391,21 +424,7 @@ $(document).ready(() => {
                         // return;
                     }
                 }
-                if (col.field === 'm_up_risk') {
-                    // 只能输入正整数
-                    if (isNaN(validText)) {
-                        toastr.error('不能输入其它非数字类型字符');
-                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                        return;
-                    }
-                    const num = parseFloat(validText);
-                    if (validText !== null && (num < 0 || num > 100 || !/^\d+$/.test(num))) {
-                        toastr.error('只能输入0-100的正整数');
-                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                        return;
-                    }
-                }
-                if (col.field === 'm_down_risk') {
+                if (col.field === 'm_up_risk' || col.field === 'm_down_risk' || col.field === 'm_tax') {
                     // 只能输入正整数
                     if (isNaN(validText)) {
                         toastr.error('不能输入其它非数字类型字符');
@@ -430,6 +449,7 @@ $(document).ready(() => {
                 select.msg_spread = materialCol.getValue.msg_spread(select);
                 select.m_spread = materialCol.getValue.m_spread(select);
                 select.m_tp = materialCol.getValue.m_tp(select);
+                select.m_tax_tp = materialCol.getValue.m_tax_tp(select);
                 delete select.waitingLoading;
 
                 // console.log(select);
@@ -437,6 +457,9 @@ $(document).ready(() => {
                 // 更新至服务器
                 postData(window.location.pathname + '/save', { type:'update', updateData: select }, function (result) {
                     m_tp = result.m_tp;
+                    if (materialTax) {
+                        m_tax_tp = result.m_tax_tp;
+                    }
                     resetTpTable();
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     // 判断如果是更改了编号,名称,单位,月信息价需要跟着改变值
@@ -466,6 +489,9 @@ $(document).ready(() => {
                     // 更新至服务器
                     postData(window.location.pathname + '/save', { type:'update', updateData: select }, function (result) {
                         m_tp = result.m_tp;
+                        if (materialTax) {
+                            m_tax_tp = result.m_tax_tp;
+                        }
                         resetTpTable();
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     }, function () {
@@ -561,7 +587,7 @@ $(document).ready(() => {
                                 // bPaste = false;
                                 // continue;
                             }
-                        } else if (colSetting.field === 'm_up_risk' || colSetting.field === 'm_down_risk') {
+                        } else if (colSetting.field === 'm_up_risk' || colSetting.field === 'm_down_risk' || colSetting.field === 'm_tax') {
                             if (validText !== null && (num < 0 || num > 100 || !/^\d+$/.test(num))) {
                                 toastMessageUniq(getPasteHint(hint.riskCan, hintRow));
                                 bPaste = false;
@@ -580,6 +606,7 @@ $(document).ready(() => {
                     materialData.msg_spread = materialCol.getValue.msg_spread(sortData[curRow]);
                     materialData.m_spread = materialCol.getValue.m_spread(sortData[curRow]);
                     materialData.m_tp = materialCol.getValue.m_tp(sortData[curRow]);
+                    materialData.m_tax_tp = materialCol.getValue.m_tax_tp(sortData[curRow]);
                     data.push(materialData);
                     // rowData.push(curRow);
                 } else {
@@ -611,6 +638,9 @@ $(document).ready(() => {
                     // SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
                 }
                 m_tp = result.m_tp;
+                if (materialTax) {
+                    m_tax_tp = result.m_tax_tp;
+                }
                 resetTpTable();
                 // materialSpreadObj.refreshActn();
             }, function () {
@@ -638,9 +668,9 @@ $(document).ready(() => {
     sheet.resumePaint();
     const static_cols = [
         {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 60, formatter: '@', readOnly: true},
-        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 140, formatter: '@', readOnly: true},
-        {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
-        {title: '来源地', colSpan: '1', rowSpan: '2', field: 'origin', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.isEdit'},
+        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 100, formatter: '@', readOnly: true},
+        {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
+        {title: '来源地', colSpan: '1', rowSpan: '2', field: 'origin', hAlign: 0, width: 70, formatter: '@', readOnly: 'readOnly.isEdit'},
         {title: '平均单价', colSpan: '1', rowSpan: '2', field: 'average_msg_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true, getValue:'getValue.average_msg_tp'},
     ];
     // 月信息价方法集合
@@ -797,6 +827,9 @@ $(document).ready(() => {
                         materialBillsData = result.materialBillsData;
                         SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
                         m_tp = result.m_tp;
+                        if (materialTax) {
+                            m_tax_tp = result.m_tax_tp;
+                        }
                         resetTpTable();
                     }, function () {
                         select[col.field] = orgValue;
@@ -926,6 +959,9 @@ $(document).ready(() => {
                     materialBillsData = result.materialBillsData;
                     SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
                     m_tp = result.m_tp;
+                    if (materialTax) {
+                        m_tax_tp = result.m_tax_tp;
+                    }
                     resetTpTable();
                 }, function () {
                     SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
@@ -1142,6 +1178,9 @@ $(document).ready(() => {
             }
             postData(window.location.pathname + '/save', { type:'expr', id: $('#materialbillsId').val(), expr: expr }, function (result) {
                 m_tp = result.m_tp;
+                if (materialTax) {
+                    m_tax_tp = result.m_tax_tp;
+                }
                 resetTpTable();
                 const sheet = materialSpread.getActiveSheet();
                 const select = SpreadJsObj.getSelectObject(sheet);
@@ -1174,6 +1213,9 @@ $(document).ready(() => {
                 materialBillsData = data.materialBillsData;
                 SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
                 m_tp = data.m_tp;
+                if (materialTax) {
+                    m_tax_tp = data.m_tax_tp;
+                }
                 resetTpTable();
                 $('#add-month').modal('hide');
             });
@@ -1204,6 +1246,9 @@ $(document).ready(() => {
                 materialBillsData = data.materialBillsData;
                 SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
                 m_tp = data.m_tp;
+                if (materialTax) {
+                    m_tax_tp = data.m_tax_tp;
+                }
                 resetTpTable();
                 $('#remove-month').modal('hide');
             });

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

@@ -9,7 +9,7 @@
 
 $(document).ready(function () {
     // 每页最多几个附件
-    const pageCount = 15;
+    const pageCount = 20;
     // 全局fileData初始化
     let fileData = fileList || []
     // let currPageFileData = [];
@@ -257,8 +257,8 @@ $(document).ready(function () {
         // console.log('fileIds', fileIds)
 
         if (fileIds.length) {
-            if (fileIds.length > 10) {
-              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`)
+            if (fileIds.length > 20) {
+              return toastr.warning(`最大允许20个文件(当前${fileIds.length}个)`)
             }
             toastr.success('正在进行下载并压缩文件...', '', { timeOut: 0, extendedTimeOut: 0})
             $(this).attr('disabled', "true");

+ 2 - 0
app/public/js/material_list.js

@@ -622,6 +622,7 @@ $(document).ready(() => {
                         const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
                         loadMaterialData(index, xmjIndex);
                         SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
+                        materialSpread.getActiveSheet().setSelection(info.row + 1, info.col, 1, 1);
                     }, function () {
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     });
@@ -747,6 +748,7 @@ $(document).ready(() => {
                     const xmjIndex = gclGatherData[index].leafXmjs.indexOf(xmjSelect);
                     loadMaterialData(index, xmjIndex);
                     SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), index);
+                    materialSpread.getActiveSheet().setSelection(info.cellRange.row, info.cellRange.col, info.cellRange.rowCount, info.cellRange.colCount);
                 }, function () {
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 });

+ 1 - 0
app/public/js/path_tree.js

@@ -1822,6 +1822,7 @@ const createNewPathTree = function (type, setting) {
                 delete x.grow_dgn_qty;
                 delete x.grow_tp;
             });
+            this.loadDatas(this.datas);
         }
         resortChildrenByCustom(fun) {
             for (const n of this.nodes) {

+ 100 - 21
app/public/js/revise.js

@@ -57,6 +57,37 @@ $(document).ready(() => {
     const billsSheet = billsSpread.getActiveSheet();
     sjsSettingObj.setFxTreeStyle(billsSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(billsSpreadSetting);
+
+    billsSpreadSetting.headColWidth = [50];
+    billsSpreadSetting.rowHeader = [
+        {
+            rowHeaderType: 'tag',
+            setting: {
+                indent: 14,
+                tagSize: 0.8,
+                tagFont: '8px 微软雅黑',
+                getColor: function (index, data) {
+                    if (!data) return;
+                    return billsTag.getBillsTagsColor(data.id);
+                },
+                getTagHtml: function (index, data) {
+                    if (!data) return;
+                    const getHtml = function (list) {
+                        if (!list || list.length === 0) return '';
+                        const html = [];
+                        for (const l of list) {
+                            html.push('<div class="row mr-1">');
+                            html.push(`<div class="col-auto pr-1 ${l.tagClass}">`, '<i class="fa fa-tag"></i>', '</div>');
+                            html.push('<div class="col p-0">', '<p>', l.comment, '</p>', '</div>');
+                            html.push('</div>');
+                        }
+                        return html.join('');
+                    };
+                    return getHtml(billsTag.getBillsTagsInfo(data.id));
+                }
+            },
+        },
+    ];
     SpreadJsObj.initSheet(billsSheet, billsSpreadSetting);
     const posSpread = SpreadJsObj.createNewSpread($('#pos-spread')[0]);
     const posSheet = posSpread.getActiveSheet();
@@ -66,6 +97,21 @@ $(document).ready(() => {
 
     const posSearch = $.posSearch({selector: '#pos-search', searchSpread: posSpread});
 
+    const billsTag = $.billsTag({
+        selector: '#bills-tag',
+        relaSpread: billsSpread,
+        updateUrl: window.location.pathname + '/tag',
+        afterModify: function (nodes) {
+            SpreadJsObj.repaintNodesRowHeader(billsSpread.getActiveSheet(), nodes);
+        },
+        afterLocated:  function () {
+            posSpreadObj.loadCurPosData();
+        },
+        afterShow: function () {
+            billsSpread.refresh();
+            if (posSpread) posSpread.refresh();
+        },
+    });
     const errorList = $.cs_errorList({
         tabSelector: '#error-list-tab',
         selector: '#error-list',
@@ -293,6 +339,7 @@ $(document).ready(() => {
                     const rows = [];
                     for (const u of data.update) {
                         rows.push(tree.nodes.indexOf(u));
+                        billsTag.refreshBillsTagView(u);
                     }
                     SpreadJsObj.reLoadRowsData(sheet, rows);
                 }
@@ -362,7 +409,11 @@ $(document).ready(() => {
                 const parent = tree.getParent(node);
                 const children = parent ? parent.children : tree.children;
                 const index = children.indexOf(node);
-                for (let i = 0; i < count; i++) {
+                if (index > 0 && children[index-1].used) {
+                    toastr.warning('其前节点已计量,选中的节点不可降级');
+                    return;
+                }
+                for (let i = index; i < count; i++) {
                     const child = children[i+index];
                     if (tree.checkNodeUsed(child, pos)) {
                         toastr.warning('选中的节点已计量,不可降级');
@@ -387,6 +438,7 @@ $(document).ready(() => {
                             sheet.setSelection(sel.row, sel.col, 1, sel.colCount);
                         }
                         self.refreshOperationValid(sheet);
+                        billsTag.afterDeleteBills(refreshData.delete);
                     });
                 });
             } else {
@@ -1005,6 +1057,7 @@ $(document).ready(() => {
             .keyup((e) => {if (e.keyCode === 13) item.batchInsert($input[0], root);})
             .on('input', function () {this.value = this.value.replace(/[^\d]/g, '');});
     };
+    const addTag = newTag({ledgerSheet: billsSpread.getActiveSheet(), billsTag});
     const billsContextMenuOptions = {
         selector: '#bills-spread',
         build: function ($trigger, e) {
@@ -1300,7 +1353,19 @@ $(document).ready(() => {
                 tenderSelect.showSelect(SpreadJsObj.getSelectObject(billsSheet));
             }
         };
+        billsContextMenuOptions.items.sprImport = '----';
     }
+    billsContextMenuOptions.items.tag = {
+        name: '书签',
+        callback: function (key, opt, menu, e) {
+            const node = SpreadJsObj.getSelectObject(billsSpread.getActiveSheet());
+            addTag.do(node);
+        },
+        disabled: function (key, opt) {
+            const node = SpreadJsObj.getSelectObject(billsSpread.getActiveSheet());
+            return !node;
+        }
+    };
     billsContextMenuOptions.items.sprTag = '----';
     billsContextMenuOptions.items.showLast = {
         name: '显示至最底层',
@@ -1861,6 +1926,10 @@ $(document).ready(() => {
     postData(window.location.pathname + '/load', {}, function (result) {
         billsTree.loadDatas(result.bills);
         treeCalc.calculateAll(billsTree);
+        for (const t of result.tags) {
+            t.node = billsTree.datas.find(x => {return x.id === t.lid});
+        }
+        billsTag.loadDatas(result.tags);
         SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, billsTree);
         SpreadJsObj.loadTopAndSelect(billsSheet, ckBillsSpread);
 
@@ -2103,30 +2172,38 @@ $(document).ready(() => {
                 qdSheet.setSelection(sel.row + 1, sel.col, 1, 1);
                 qdSheet.getParent().focus();
             });
-            this.qdSpread.bind(spreadNS.Events.ClipboardPasted, function (e, info) {
-                const billsCount = info.sheet.getRowCount(), posSheet = self.posSpread.getActiveSheet();
-                const count = posSheet.getColumnCount() - 2;
-                if (billsCount > count) {
-                    posSheet.setColumnCount(billsCount + 2);
-                    for (let i = count + 1; i <= billsCount; i++) {
-                        info.sheet.getCell(i - 1, 0, spreadNS.SheetArea.rowHeader).text('清单' + i);
+            this.qdSpread.bind(spreadNS.Events.ClipboardPasting, function (e, info) {
+                info.cancel = true;
+                const transpose = $('[name=batch-transpose]')[0].checked;
+                const pasteData = SpreadJsObj.analysisPasteText(info.pasteData.text, transpose);
+
+                const billsSheet = info.sheet, posSheet = self.posSpread.getActiveSheet();
+                const billsCount = info.sheet.getRowCount(), finalCount = info.cellRange.row + pasteData.length + 1;
+                SpreadJsObj.beginMassOperation(billsSheet);
+                if (finalCount > billsCount) {
+                    billsSheet.setRowCount(finalCount);
+                    posSheet.setColumnCount(finalCount + 2);
+                    for (let i = billsCount - 1; i <= finalCount; i++) {
+                        billsSheet.getCell(i - 1, 0, spreadNS.SheetArea.rowHeader).text('清单' + i);
                         posSheet.getCell(0, i + 2 - 1, spreadNS.SheetArea.colHeader).text('清单' + i);
                     }
                 }
-                if (info.cellRange.col === 0 && info.cellRange.colCount === 1) {
-                    const dealBills = self.dealSpread.getActiveSheet().zh_data;
-                    if (dealBills && dealBills.length > 0) {
-                        for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
-                            const curRow = iRow + info.cellRange.row;
-                            const bills = _.find(dealBills, {code: info.sheet.getText(curRow, 0)});
-                            if (bills) {
-                                info.sheet.getCell(curRow, 1).value(bills.name);
-                                info.sheet.getCell(curRow, 2).value(bills.unit);
-                                info.sheet.getCell(curRow, 3).value(bills.unit_price);
-                            }
+                for (let iRow = 0; iRow < pasteData.length; iRow++) {
+                    const curRow = iRow + info.cellRange.row;
+                    pasteData[iRow].forEach((value, iCol) => {
+                        billsSheet.getCell(curRow, iCol + info.cellRange.col).value(value);
+                    });
+                    if ([0, 1].indexOf(info.cellRange.col) >= 0) {
+                        const dealBills = self.dealSpread.getActiveSheet().zh_data;
+                        const bills = _.find(dealBills, {code: billsSheet.getText(curRow, 0)});
+                        if (bills) {
+                            billsSheet.getCell(curRow, 1).value(bills.name);
+                            billsSheet.getCell(curRow, 2).value(bills.unit);
+                            billsSheet.getCell(curRow, 3).value(bills.unit_price);
                         }
                     }
                 }
+                SpreadJsObj.endMassOperation(billsSheet);
             });
             this.posSpread.bind(spreadNS.Events.ClipboardPasted, function (e, info) {
                 const billsCount = info.sheet.getColumnCount() - 2, qdSheet = self.qdSpread.getActiveSheet();
@@ -2428,6 +2505,7 @@ $(document).ready(() => {
     const stdXmjSetting = {
         selector: '#std-xmj',
         stdType: 'xmj',
+        libs: stdChapters,
         treeSetting: {
             id: 'chapter_id',
             pid: 'pid',
@@ -2459,6 +2537,7 @@ $(document).ready(() => {
     const stdGclSetting = {
         selector: '#std-gcl',
         stdType: 'gcl',
+        libs: stdBills,
         treeSetting: {
             id: 'bill_id',
             pid: 'pid',
@@ -2501,12 +2580,12 @@ $(document).ready(() => {
             showSideTools(tab.hasClass('active'));
             if (tab.attr('content') === '#std-xmj') {
                 if (!stdXmj) {
-                    stdXmj = new stdLib(stdXmjSetting);
+                    stdXmj = $.stdLib(stdXmjSetting);
                 }
                 stdXmj.spread.refresh();
             } else if (tab.attr('content') === '#std-gcl') {
                 if (!stdGcl) {
-                    stdGcl = new stdLib(stdGclSetting);
+                    stdGcl = $.stdLib(stdGclSetting);
                 }
                 stdGcl.spread.refresh();
             } else if (tab.attr('content') === '#deal-bills') {

+ 190 - 0
app/public/js/setting_datacollect_tender.js

@@ -0,0 +1,190 @@
+'use strict';
+
+/**
+ *
+ * @author LanJianRong
+ * @date 2020/11/13
+ * @version
+ */
+const tenderTree = [];
+let parentId = 0;
+// 查询方法
+function findNode (key, value, arr) {
+    for (const a of arr) {
+        if (a[key] && a[key] === value) {
+            return a;
+        }
+    }
+}
+// 初始化TenderTree数据
+function initTenderTree () {
+    const levelCategory = category.filter(function (c) {
+        return c.level && c.level > 0;
+    });
+    function findCategoryNode(cid, value, array) {
+        for (const a of array) {
+            if (a.cid === cid && a.vid === value) {
+                return a;
+            }
+        }
+    }
+    function getCategoryNode(category, value, parent, i = null) {
+        const array = parent ?  parent.children : tenderTree;
+        let cate = findCategoryNode(category.id, value, array);
+        if (!cate) {
+            const cateValue = findNode('id', value, category.value);
+            if (!cateValue) return null;
+            cate = {
+                cid: category.id,
+                vid: value,
+                name: cateValue.value,
+                children: [],
+                level: i ? i : category.level,
+                sort_id: ++parentId,
+                sort: cateValue.sort,
+            };
+            array.push(cate);
+        }
+        return cate;
+    }
+    function loadTenderCategory (tender) {
+        let tenderCategory = null;
+        for (const [index,lc] of levelCategory.entries()) {
+            const tenderCate = findNode('cid', lc.id, tender.category);
+            if (tenderCate) {
+                tenderCategory = getCategoryNode(lc, tenderCate.value, tenderCategory);
+            } else {
+                if (index === 0 && tender.category) {
+                    for (const [i,c] of tender.category.entries()) {
+                        const cate = findNode('id', c.cid, category);
+                        tenderCategory = getCategoryNode(cate, c.value, tenderCategory, i+1);
+                    }
+                }
+                return tenderCategory;
+            }
+        }
+        return tenderCategory;
+    }
+    tenderTree.splice(0, tenderTree.length);
+    for (const t of tenders) {
+        t.valid = true;
+        delete t.level;
+        if (t.category && levelCategory.length > 0) {
+            const parent = loadTenderCategory(t);
+            if (parent) {
+                t.level = parent.level + 1;
+                parent.children.push(t);
+            } else {
+                tenderTree.push(t);
+            }
+        } else {
+            tenderTree.push(t);
+        }
+    }
+}
+function recursiveGetTenderNodeHtml (node, arr, pid) {
+    // console.log(node, tender)
+    const html = [];
+    html.push('<tr pid="' + pid + '">');
+    // 名称
+    html.push('<td class="in-' + node.level + '">');
+    if (node.cid) {
+        html.push('<i class="fa fa-folder-o"></i> ', node.name);
+    } else {
+        html.push('<span class="text-muted mr-2">');
+        html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+        html.push('</span>');
+        //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
+        html.push('<a href="javascript: void(0)" id="' + node.id + '">', node.name, '</a>');
+    }
+    html.push('</td>');
+    // 创建人
+    html.push('<td>');
+    if (!node.cid) {
+        // html.push('<input data-tid="'+ node.id +'" type="radio"> '+ (node.copy_id === tender.copy_id ? 'checked' : '') + '/>');
+        html.push(`<input data-tid=${node.id} type="checkbox" ${_.findIndex(dcTenders, { tid: node.id }) === -1 ? 'checked' : ''}>`);
+    }
+    html.push('</td>');
+    html.push('</tr>');
+    if (node.children) {
+        for (const c of node.children) {
+            html.push(recursiveGetTenderNodeHtml(c, node.children, node.sort_id));
+        }
+    }
+    return html.join('');
+}
+// 根据TenderTree数据获取Html代码
+function getTenderTreeHtml () {
+    if (tenderTree.length > 0) {
+        const html = [];
+        // html.push('<table class="table table-hover table-bordered">');
+        // html.push('<thead>', '<tr>');
+        // html.push('<th>名称</th>');
+        // html.push('<th width="60">选择 <input type="checkbox" id="select-tender-all"></th>');
+        // html.push('</tr>', '</thead>');
+        parentId = 0;
+        for (const t of tenderTree) {
+            html.push(recursiveGetTenderNodeHtml(t, tenderTree, ''));
+        }
+        // html.push('</table>');
+        return html.join('');
+    } else {
+        return EmptyTenderHtml.join('');
+    }
+}
+$(document).ready(function () {
+    initTenderTree();
+    $('#tenderBtn').click(() => {
+        const html = getTenderTreeHtml();
+        $('#copyModalContent').html(html);
+        $('#sort input[value="'+ addDataCollect +'"]').prop('checked', true);
+        if($('#copyModalContent input[type="checkbox"]:not(:checked)').length === 0) {
+            $('#select-tender-all').prop('checked', true);
+        } else {
+            $('#select-tender-all').prop('checked', false);
+        }
+        $('#sort').modal('show');
+    });
+
+    $('#tender_dataCollect_btn').click(function () {
+        // 获取是否新增展示到决策大屏
+        const add_datacollect = $('input[name="add_datacollect"]:checked').val();
+        const noTidList = [];
+        $("#copyModalContent input[type='checkbox']:not(:checked)").each(function () {
+           noTidList.push($(this).data('tid'));
+        });
+        const dcTidList = _.map(dcTenders, 'tid');
+        let is_list_update = true;
+        let is_collect_update = true;
+        if (_.isEqual(_.sortBy(dcTidList), _.sortBy(noTidList))) {
+            is_list_update = false;
+        }
+        if (parseInt(add_datacollect) === addDataCollect) {
+            is_collect_update = false;
+        }
+        if (is_list_update || is_collect_update) {
+            postData('/setting/datacollect/save', { type: 'tender', add_datacollect: parseInt(add_datacollect), tids: noTidList }, function (result) {
+                addDataCollect = result.addDataCollect;
+                dcTenders = result.dcTenders;
+                toastr.success('修改成功');
+            })
+        }
+        $('#sort').modal('hide');
+    });
+
+    $('#select-tender-all').click(function () {
+        const is_checked = $(this).is(':checked');
+        if(is_checked) {
+            $("#copyModalContent input[type='checkbox']").prop('checked', true);
+        } else {
+            $("#copyModalContent input[type='checkbox']").prop('checked', false);
+        }
+    });
+    $('body').on('click', "#copyModalContent input[type='checkbox']", function () {
+        if($('#copyModalContent input[type="checkbox"]:not(:checked)').length === 0) {
+            $('#select-tender-all').prop('checked', true);
+        } else {
+            $('#select-tender-all').prop('checked', false);
+        }
+    })
+});

+ 234 - 1
app/public/js/shares/cs_tools.js

@@ -783,6 +783,7 @@ const showSelectTab = function(select, spread, afterShow) {
             billsTags = [];
             billsIndexes = {};
             for (const d of datas) {
+                if (!d.node) continue;
                 billsTags.push(d);
                 _addToBillsIndex(d);
             }
@@ -851,6 +852,19 @@ const showSelectTab = function(select, spread, afterShow) {
             }) : undefined;
         };
 
+        const afterDeleteBills = function (nodes) {
+            for (const node of nodes) {
+                const bi = billsIndexes[node.id];
+                if (!bi) continue;
+                delete billsIndexes[node.id];
+                for (const biTag of bi) {
+                    const delTag = billsTags.find(x => {return x.id === biTag.id});
+                    billsTags.splice(billsTags.indexOf(delTag), 1);
+                    $('#bills-tag-' + delTag.id).remove();
+                }
+            }
+        };
+
         $('body').on('click', '[name=bills-tag-locate]', function () {
             const lid = parseInt(this.getAttribute('lid'));
             SpreadJsObj.locateTreeNode(setting.relaSpread.getActiveSheet(), lid);
@@ -935,7 +949,7 @@ const showSelectTab = function(select, spread, afterShow) {
         $('#bills-tag-search').bind('click', () => {searchTagsAndShow();});
         $('#bills-tag-keyword').bind('keydown', e => {if (e.keyCode === 13) searchTagsAndShow();});
 
-        return { loadDatas, updateDatasAndShow, show, getBillsTagsColor, getBillsTagsInfo, refreshBillsTagView, }
+        return { loadDatas, updateDatasAndShow, show, getBillsTagsColor, getBillsTagsInfo, refreshBillsTagView, afterDeleteBills }
     };
 
     $.sumLoadMiss = function (setting) {
@@ -1074,4 +1088,223 @@ const showSelectTab = function(select, spread, afterShow) {
             };
         }
     };
+
+    $.stdLib = function (setting) {
+        if (!setting.selector) return;
+        const obj = $(setting.selector);
+        const stdLibHtml = setting.libs.map(l => {
+            return `<option value="${l.id}" >${l.name}</option>`;
+        });
+        const relaSelect = {
+            showLevel: `std-${setting.stdType}-sl`,
+            searchText: `std-${setting.stdType}-st`,
+            searchResult: `std-${setting.stdType}-sr`,
+            searchPre: `std-${setting.stdType}-sp`,
+            searchNext: `std-${setting.stdType}-sn`,
+            searchClose: `std-${setting.stdType}-sc`,
+        };
+        obj.html(
+            '<div class="sjs-bar d-flex">\n' +
+            '    <div class="dropdown mr-1">\n' +
+            '        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">\n' +
+            '             <i class="fa fa-list-ol"></i> 显示层级\n' +
+            '        </button>\n' +
+            '        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">\n' +
+            `            <a class="dropdown-item" href="javascript: void(0);" tag="1" name="${relaSelect.showLevel}">第一层</a>\n` +
+            `            <a class="dropdown-item" href="javascript: void(0);" tag="2" name="${relaSelect.showLevel}">第二层</a>\n` +
+            `            <a class="dropdown-item" href="javascript: void(0);" tag="3" name="${relaSelect.showLevel}">第三层</a>\n` +
+            `            <a class="dropdown-item" href="javascript: void(0);" tag="4" name="${relaSelect.showLevel}">第四层</a>\n` +
+            `            <a class="dropdown-item" href="javascript: void(0);" tag="5" name="${relaSelect.showLevel}">第五层</a>\n` +
+            `            <a class="dropdown-item" href="javascript: void(0);" tag="last" name="${relaSelect.showLevel}">最底层</a>\n` +
+            '        </div>\n' +
+            '    </div>' +
+            `    <div class=input-group input-group-sm pr-1"><select class="form-control form-control-sm">${stdLibHtml.join('')}</select></div>\n` +
+            '    <div class="ml-1">\n' +
+            '        <div class="dropdown">\n' +
+            '            <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">\n' +
+            '                <i class="fa fa-search"></i>\n' +
+            '            </button>\n' +
+            '            <div class="dropdown-menu dropdown-menu-right">\n' +
+            '                <div class="px-2 border-primary border-1 d-flex" style="width: 300px">\n' +
+            '                    <div class="d-inline-block">\n' +
+            '                        <div class="input-group input-group-sm mr-1">' +
+            `                            <input type="text" class="form-control" placeholder="输入编号/名称查找" id="${relaSelect.searchText}">\n` +
+            `                            <div class="input-group-append" ><span class="input-group-text" id="${relaSelect.searchResult}">结果:0</span></div>\n` +
+            '                            <div class="input-group-append" >\n' +
+            `                                <button class="btn btn-outline-secondary" type="button" title="上一个" id="${relaSelect.searchPre}"><i class="fa fa-angle-double-left"></i></button>\n` +
+            `                                <button class="btn btn-outline-secondary" type="button" title="下一个" id="${relaSelect.searchNext}"><i class="fa fa-angle-double-right"></i></button>\n` +
+            '                            </div>\n' +
+            '                        </div>\n' +
+            '                    </div>\n' +
+            `                    <div class="d-inline-block"><button class="btn btn-light text-danger btn-sm ml-1" type="button" id="${relaSelect.searchClose}"><i class="fa fa-remove"></i></button></div>\n` +
+            '                </div>\n' +
+            '            </div>\n' +
+            '        </div>\n' +
+            '    </div>' +
+            '</div>\n' +
+            `<div id="std-${setting.stdType}-spread" class="sjs-sh"></div>\n`
+        );
+        autoFlashHeight();
+        const pathTree = createNewPathTree('base', setting.treeSetting);
+
+        const spreadSetting = {
+            cols: [
+                {title: '名称', field: 'name', hAlign: 0, width: 180, formatter: '@'},
+                {title: '单位', field: 'unit', hAlign: 1, width: 60, formatter: '@'},
+            ],
+            treeCol: 0,
+            emptyRows: 0,
+            headRows: 1,
+            headRowHeight: [32],
+            defaultRowHeight: 21,
+            headerFont: '12px 微软雅黑',
+            font: '12px 微软雅黑',
+            headColWidth: [30],
+            selectedBackColor: '#fffacd',
+            readOnly: true,
+            stdType: setting.stdType,
+        };
+        spreadSetting.cols.unshift(setting.stdType === 'xmj'
+            ? {title: '项目节编号', field: 'code', hAlign: 0, width: 150, formatter: '@', cellType: 'tree'}
+            : {title: '清单编号', field: 'b_code', hAlign: 0, width: 150, formatter: '@', cellType: 'tree'});
+
+        const spread = SpreadJsObj.createNewSpread($(`#std-${setting.stdType}-spread`)[0]);
+        const sheet = spread.getActiveSheet();
+        SpreadJsObj.initSheet(sheet, spreadSetting);
+
+
+        if (setting.cellDoubleClick) sheet.bind(spreadNS.Events.CellDoubleClick, setting.cellDoubleClick);
+        sheet.bind(spreadNS.Events.SelectionChanged, function (e, info) {
+            if (!info.oldSelections || !info.oldSelections[0] || info.newSelections[0].row !== info.oldSelections[0].row) {
+                SpreadJsObj.saveTopAndSelect(info.sheet, cacheKey.node);
+            }
+        });
+        sheet.bind(spreadNS.Events.TopRowChanged, function (e, info) {
+            SpreadJsObj.saveTopAndSelect(info.sheet, cacheKey.node);
+        });
+
+        const cacheLib = [];
+        const cacheKey = {
+            lib: setting.page + '-' + setting.tid + '-' + setting.stdType,
+        };
+
+        $('select', setting.selector).change(function () {
+            loadLib(parseInt(this.value), true);
+        });
+        (function (select, sheet) {
+            $(select).click(function () {
+                if (!sheet.zh_tree) return;
+                const tag = $(this).attr('tag');
+                const tree = sheet.zh_tree;
+                setTimeout(() => {
+                    switch (tag) {
+                        case "1":
+                        case "2":
+                        case "3":
+                        case "4":
+                        case "5":
+                            tree.expandByLevel(parseInt(tag));
+                            SpreadJsObj.refreshTreeRowVisible(sheet);
+                            break;
+                        case "last":
+                            tree.expandByCustom(() => { return true; });
+                            SpreadJsObj.refreshTreeRowVisible(sheet);
+                            break;
+                    }
+                }, 100);
+            });
+        })(`a[name=${relaSelect.showLevel}]`, sheet);
+
+        const loadLib = function(listId, reload = false) {
+            cacheKey.node = cacheLib.lib + '-' + listId;
+            const locateMemory = function () {
+                if (!reload) {
+                    SpreadJsObj.loadTopAndSelect(sheet, cacheKey.node);
+                } else {
+                    removeLocalCache(cacheKey.node);
+                }
+            };
+            const cacheData = cacheLib.find(function (lib) {
+                return lib.id === listId;
+            });
+            if (cacheData) {
+                pathTree.loadDatas(cacheData.data);
+                SpreadJsObj.loadSheetData(sheet, 'tree', pathTree);
+                locateMemory();
+                setLocalCache(cacheKey.lib, listId);
+            } else {
+                postData(`/std-lib/get-data`, {stdType: setting.stdType, list_id: listId}, function (data) {
+                    cacheLib.push({id: listId, data: data});
+                    pathTree.loadDatas(data);
+                    SpreadJsObj.loadSheetData(sheet, 'tree', pathTree);
+                    locateMemory();
+                    setLocalCache(cacheKey.lib, listId);
+                });
+            }
+        };
+
+        const _loadCacheLib = function() {
+            let libId = getLocalCache(cacheKey.lib);
+            if (libId) {
+                $('select', setting.selector).val(libId);
+                loadLib(parseInt(libId));
+            } else {
+                loadLib(parseInt($('select', setting.selector).val()));
+            }
+        };
+        _loadCacheLib();
+
+        const searchObj = {
+            result: [],
+            cur: 0,
+            searchStdNode: function() {
+                const keyword = $(`#${relaSelect.searchText}`).val();
+                searchObj.result = keyword ? pathTree.nodes.filter(x => {
+                    return x.code.indexOf(keyword) >= 0 || x.b_code.indexOf(keyword) >= 0 || x.name.indexOf(keyword) >= 0;
+                }) : [];
+                // searchObj.result = [];
+                // for (const x of pathTree.nodes) {
+                //     if (x.code.indexOf(keyword) >= 0 || x.b_code.indexOf(keyword) >= 0 || x.name.indexOf(keyword) >= 0) {
+                //         searchObj.result.push(x);
+                //     }
+                // }
+                $(`#${relaSelect.searchResult}`)[0].innerText = `结果:${searchObj.result.length}`;
+                searchObj.cur = 0;
+                if (searchObj.result.length > 0) {
+                    SpreadJsObj.locateTreeNode(sheet, pathTree.getNodeKey(searchObj.result[searchObj.cur]));
+                }
+            },
+            searchPre: function () {
+                if (searchObj.result.length === 0) return;
+                searchObj.cur = searchObj.cur === 0 ? searchObj.result.length - 1 : this.cur - 1;
+                SpreadJsObj.locateTreeNode(sheet, pathTree.getNodeKey(searchObj.result[searchObj.cur]), true);
+            },
+            searchNext: function () {
+                if (searchObj.result.length === 0) return;
+                searchObj.cur = searchObj.cur === searchObj.result.length - 1 ? 0 : searchObj.cur + 1;
+                SpreadJsObj.locateTreeNode(sheet, pathTree.getNodeKey(searchObj.result[searchObj.cur]), true);
+            },
+            clear: function () {
+                $(`#${relaSelect.searchText}`).val('');
+                $(`#${relaSelect.searchResult}`)[0].innerText = `结果:${0}`;
+                searchObj.result = [];
+                searchObj.cur = 0;
+            }
+        };
+        $(`#${relaSelect.searchText}`).change(searchObj.searchStdNode);
+        $(`#${relaSelect.searchPre}`).click(function (e) {
+            searchObj.searchPre();
+            e.stopPropagation();
+        });
+        $(`#${relaSelect.searchNext}`).click(function (e) {
+            searchObj.searchNext();
+            e.stopPropagation();
+        });
+        $(`#${relaSelect.searchClose}`).click(function (e) {
+            searchObj.clear();
+            e.stopPropagation();
+        });
+
+        return { spread }
+    };
 })(jQuery);

+ 4 - 3
app/public/js/shares/tenders2tree.js

@@ -53,7 +53,7 @@ const Tender2Tree = (function () {
         return cate;
     }
 
-    function loadCategoryTreeNode ( tender, levelCate) {
+    function loadCategoryTreeNode (category, tender, levelCate) {
         let tenderCategory = null;
         for (const [i, lc] of levelCate.entries()) {
             const tenderCate = findNode('cid', lc.id, tender.category);
@@ -73,7 +73,7 @@ const Tender2Tree = (function () {
         return tenderCategory;
     }
 
-    function convert (category, tenders, ledgerAuditConst, stageAuditConst) {
+    function convert (category, tenders, ledgerAuditConst, stageAuditConst, loadFun) {
         tenderTree.clearDatas();
 
         const levelCategory = category.filter(function (c) {
@@ -81,7 +81,7 @@ const Tender2Tree = (function () {
         });
 
         for (const t of tenders) {
-            const parent = (t.category && levelCategory.length > 0) ? loadCategoryTreeNode(t, levelCategory) : null;
+            const parent = (t.category && levelCategory.length > 0) ? loadCategoryTreeNode(category, t, levelCategory) : null;
             const node = {
                 tid: t.id,
                 name: t.name,
@@ -91,6 +91,7 @@ const Tender2Tree = (function () {
             if (ledgerAuditConst && stageAuditConst) {
                 node.status = t.lastStage ? stageAuditConst.statusString[t.lastStage.status] : ledgerAuditConst.statusString[t.ledger_status];
             }
+            if (loadFun) loadFun(node, t);
             tenderTree.addNode(node, parent);
         }
         tenderTree.sortTreeNode(true);

+ 18 - 4
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -952,23 +952,37 @@ const SpreadJsObj = {
             }
             copyData.push(rowText.join('\t'));
         }
-        return copyData.join('\n');
+        return copyData.join('\r\n');
     },
-    analysisPasteText: function (text) {
+    analysisPasteText: function (text, transpose = false) {
+        console.log(text);
         const result = [];
         if (text === '') return result;
 
-        const rows = text.split('\n');
+        const rows = text.split('\r\n');
+        if (rows[rows.length - 1] === '') rows.splice(rows.length - 1, 1);
         for (const r of rows) {
             const cols = r.split('\t');
             result.push(cols);
         }
-        return result;
+        return transpose ? SpreadJsObj.transposePasteData(result) : result;
     },
     analysisPasteHtml: function (html) {
         const result = [];
         if (!html || html === '') return result;
     },
+    transposePasteData: function (data) {
+        const result = [];
+        const rowCount = data.length, colCount = data.reduce((r, x) => { return r ? Math.max(r, x.length) : x.length; });
+        for (let c = 0; c < colCount; c++) {
+            const newRow = [];
+            for (let r = 0; r < rowCount; r++) {
+                newRow.push(data[r][c]);
+            }
+            result.push(newRow)
+        }
+        return result;
+    },
     /**
      * 树表结构,定位至指定的节点
      * @param {GC.Spread.Sheets.Worksheet} sheet - 需要定位的sheet

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

@@ -74,7 +74,7 @@ function customizeStageTreeSetting(setting, customDisplay) {
 // 生成所有附件列表
 function getAllList(currPageNum = 1) {
     // 每页最多几个附件
-    const pageCount = 15;
+    const pageCount = 20;
     // 附件总数
     const total = attData.length;
     // 总页数
@@ -1217,8 +1217,8 @@ $(document).ready(() => {
         });
 
         if (fileIds.length) {
-            if (fileIds.length > 10) {
-              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`)
+            if (fileIds.length > 20) {
+              return toastr.warning(`最大允许20个文件(当前${fileIds.length}个)`)
             }
             toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0})
             $(this).attr('disabled', "true")

+ 27 - 6
app/public/js/stage.js

@@ -109,7 +109,7 @@ function initTreeColSettingEvents(setting) {
 // 生成所有附件列表
 function getAllList(currPageNum = 1) {
     // 每页最多几个附件
-    const pageCount = 15;
+    const pageCount = 20;
     // 附件总数
     const total = attData.length;
     // 总页数
@@ -2021,13 +2021,23 @@ $(document).ready(() => {
 
     // 加载计量单元数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
     postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;change;tag;cooperation' }, function (result) {
+        result.ledgerData && console.log('ledger: ' + result.ledgerData.length);
+        result.posData && console.log('pos: ' + result.posData.length);
+        result.detailData && console.log('detail: ' + result.detailData.length);
+        result.detailAtt && console.log('detailAtt: ' + result.detailAtt.length);
+        result.changeData && console.log('change: ' + result.changeData.length);
+        result.tags && console.log('tag: ' + result.tags.length);
+        result.cooperation && console.log('cooperation: ' + result.cooperation.length);
         // 加载树结构
+        console.time('loadLedger');
         stageTree.loadDatas(result.ledgerData);
-        // stageTree.loadCurStageData(curStageData);
-        // stageTree.loadPreStageData(preStageData);
+        console.timeEnd('loadLedger');
         checkShowLast(result.ledgerData.length);
+        console.time('calcLedger');
         treeCalc.calculateAll(stageTree);
+        console.timeEnd('calcLedger');
         // 加载解锁相关
+        console.time('loadCooperation');
         if (result.cooperation) {
             stageTree.loadPwd(result.cooperation, 'bills-p-' + userID + '-' + window.location.pathname.split('/')[2], result.cooperationConfirm);
             $('#cooperationCount').html(stageTree.pwd.length || '');
@@ -2035,20 +2045,31 @@ $(document).ready(() => {
             setCooperationSelectHtml();
             reloadCooperationHtml();
         }
+        console.timeEnd('loadCooperation');
+        console.time('loadTag');
         for (const t of result.tags) {
             t.node = stageTree.datas.find(x => {return x.id === t.lid});
         }
         billsTag.loadDatas(result.tags);
+        console.timeEnd('loadTag');
         // 加载部位明细
+        console.time('loadPos');
         stagePos.loadDatas(result.posData);
+        console.timeEnd('loadPos');
         stagePos.calculateAll();
+        console.time('showLedger');
         SpreadJsObj.loadSheetData(slSpread.getActiveSheet(), 'tree', stageTree);
         SpreadJsObj.loadTopAndSelect(slSpread.getActiveSheet(), ckBillsSpread);
+        console.timeEnd('showLedger');
+        console.time('showPos');
         stagePosSpreadObj.loadCurPosData();
         SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
+        console.timeEnd('showPos');
         // 加载中间计量
+        console.time('loadIm');
         stageIm.init(stage, imType, tenderInfo.decimal);
         stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.changeData, result.detailAtt);
+        console.timeEnd('loadIm');
 
         errorList.loadHisErrorData();
         checkList.loadHisCheckData();
@@ -4154,7 +4175,7 @@ $(document).ready(() => {
         const filename = name.substring(0, name.lastIndexOf("."));
         const fileext = name.substr(name.indexOf("."));
         const filesize = file.size;
-        if (filesize > 10 * 1024 * 1024) {
+        if (filesize > 30 * 1024 * 1024) {
             toastr.error('文件大小过大!');
             $('#change-att-btn').val('');
             return false;
@@ -4200,8 +4221,8 @@ $(document).ready(() => {
         });
 
         if (fileIds.length) {
-            if (fileIds.length > 10) {
-              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`)
+            if (fileIds.length > 20) {
+              return toastr.warning(`最大允许20个文件(当前${fileIds.length}个)`)
             }
             toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0})
             $(this).attr('disabled', "true")

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

@@ -299,9 +299,9 @@ function getProgressHtml(total, pre, cur) {
         let other = Math.max(ZhCalc.sub(ZhCalc.sub(total, pre), cur), 0);
         let otherP = Math.max(100 - preP - curP, 0);
         const html = '<div class="progress">' +
-            '<div class="progress-bar bg-success" style="width: ' + preP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期完成:¥' + pre + '">' + preP + '%</div>' +
-            '<div class="progress-bar bg-info" style="width: ' + curP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥' + cur + '">' + curP + '%</div>' +
-            '<div class="progress-bar bg-gray" style="width: ' + otherP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥' + other + '">' + otherP + '%</div>' +
+            '<div class="progress-bar bg-success" style="width: ' + preP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="截止上期完成:¥' + (pre || 0) + '">' + preP + '%</div>' +
+            '<div class="progress-bar bg-info" style="width: ' + curP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="本期完成:¥' + (cur || 0) + '">' + curP + '%</div>' +
+            '<div class="progress-bar bg-gray" style="width: ' + otherP + '%;" data-placement="bottom" data-toggle="tooltip" data-original-title="未完成:¥' + (other || 0) + '">' + otherP + '%</div>' +
             '</div>';
         return html;
     } else {

+ 3 - 2
app/public/report/js/rpt_jspdf.js

@@ -42,7 +42,8 @@ let JpcJsPDFHelper = {
         let strReplaceReg1 = new RegExp('\n\r', 'gm'),
             strReplaceReg2 = new RegExp('\r\n', 'gm'),
             strReplaceReg3 = new RegExp('\n', 'gm'),
-            strReplaceReg4 = new RegExp('\r', 'gm')
+            strReplaceReg4 = new RegExp('\r', 'gm'),
+            strReplaceReg5 = new RegExp('〜', 'gm')
         ;
         // let newName = pdfName;
         let pageObj = pageData;
@@ -282,7 +283,7 @@ let JpcJsPDFHelper = {
         function _preHandleSpliter(orgVal) {
             let rst = orgVal;
             if (rst !== null && rst !== '') {
-                rst = rst.replace(strReplaceReg1, '|').replace(strReplaceReg2, '|').replace(strReplaceReg3, '|').replace(strReplaceReg4, '|');
+                rst = rst.replace(strReplaceReg1, '|').replace(strReplaceReg2, '|').replace(strReplaceReg3, '|').replace(strReplaceReg4, '|').replace(strReplaceReg5, '~');
             }
             return rst;
         }

+ 2 - 0
app/router.js

@@ -553,6 +553,7 @@ module.exports = app => {
 
     // 书签
     app.post('/tender/:id/ledger/tag', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.billsTag');
+    app.post('/tender/:id/revise/info/tag', sessionAuth, tenderCheck, uncheckTenderCheck, reviseCheck, 'tenderController.billsTag');
     app.post('/tender/:id/measure/stage/:order/tag', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'tenderController.billsTag');
 
     // 总分包
@@ -574,6 +575,7 @@ module.exports = app => {
 
     // 决策大屏
     app.get('/datacollect', sessionAuth, 'datacollectController.index');
+    app.post('/datacollect/load', sessionAuth, 'datacollectController.loadData');
 
     // 概算投资
     app.get('/budget', sessionAuth, 'budgetController.list');

+ 25 - 0
app/service/category.js

@@ -173,6 +173,31 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 获取项目下全部分类数据
+         *
+         * @param {Number} pid - 标段id
+         * @returns {Promise<*>}
+         */
+        async getListByCategoryLevel(pid) {
+            let data = await this.getAllDataByCondition({ where: { pid }, orders: [['level', 'asc']] });
+            data = this._.filter(data, function(item) {
+                return item.level !== 0;
+            });
+            const values = await this.ctx.service.categoryValue.getAllDataByCondition({
+                where: { pid },
+                orders: [['sort', 'asc'], ['id', 'asc']],
+            });
+            // values 按名称排序
+            // values.sort((a, b) => a.value.localeCompare(b.value, 'zh-Hans-CN', { sensitivity: 'accent' }));
+            for (const d of data) {
+                d.value = values.filter(function (v) {
+                    return v.cid === d.id;
+                });
+            }
+            return data;
+        }
+
     }
 
     return Category;

+ 15 - 0
app/service/change.js

@@ -105,6 +105,7 @@ module.exports = app => {
                     in_time: new Date(),
                     code,
                     name,
+                    tp_decimal: this.ctx.tender.info.decimal.tp,
                 };
                 const operate = await this.transaction.insert(this.tableName, change);
 
@@ -1623,6 +1624,20 @@ module.exports = app => {
                 cid,
             });
         }
+
+        async updateDecimalAndTp() {
+            // 判断是否可修改
+            // 判断t_type是否为费用
+            const transaction = await this.db.beginTransaction();
+            try {
+                await this.ctx.service.changeAuditList.calcCamountSum(transaction, true);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return Change;

+ 16 - 0
app/service/change_audit.js

@@ -234,6 +234,15 @@ module.exports = app => {
             const list = await this.db.query(sql, sqlParam);
             return list;
         }
+        async getListGroupByTimesWithDetail(cid, times) {
+            const sql = 'SELECT *, pa.name, pa.company, pa.role, pa.mobile, pa.telephone FROM ' + this.tableName + ' ca ' +
+                '  Left Join ' + this.ctx.service.projectAccount.tableName + ' pa On ca.uid = pa.id' +
+                '  where id in (SELECT MAX(id) FROM ' + this.tableName +' WHERE cid = ? AND times = ? GROUP BY usite)' +
+                '  ORDER BY usite asc';
+            const sqlParam = [cid, times];
+            const list = await this.db.query(sql, sqlParam);
+            return list;
+        }
 
         /**
          * 获取比sort大的审批人列表
@@ -634,6 +643,13 @@ module.exports = app => {
             }
             return true;
         }
+
+        async getNumByMonth(tid, startMonth, endMonth) {
+            const sql = 'SELECT COUNT(*) as num FROM ?? WHERE id in (SELECT b.id FROM (SELECT * FROM ?? WHERE tid = ? AND usite != 0 GROUP BY id ORDER BY usort DESC) as b GROUP BY b.cid) AND status = ? AND sin_time between ? and ?';
+            const sqlParam = [this.tableName, this.tableName, tid, auditConst.auditStatus.checked, startMonth, endMonth];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result ? result.num : 0;
+        }
     }
 
     return ChangeAudit;

+ 4 - 1
app/service/change_audit_list.js

@@ -297,7 +297,7 @@ module.exports = app => {
             }
         }
 
-        async calcCamountSum(transaction) {
+        async calcCamountSum(transaction, updateTpDecimal = false) {
             // const sql = 'SELECT SUM(ROUND(`camount`*`unit_price`, )) as total_price FROM ?? WHERE cid = ?';
             // const sqlParam = [this.tableName, this.change.cid];
             // const tp = await transaction.queryOne(sql, sqlParam);
@@ -313,6 +313,9 @@ module.exports = app => {
             const updateData = {
                 total_price,
             };
+            if (updateTpDecimal) {
+                updateData.tp_decimal = tp_decimal;
+            }
             const options = {
                 where: {
                     cid: this.ctx.change.cid,

+ 100 - 0
app/service/datacollect_tender.js

@@ -0,0 +1,100 @@
+'use strict';
+
+/**
+ * 决策大屏标段管理-数据模型
+ *
+ * @author ellisran
+ * @date 2021/09/23
+ * @version
+ */
+// const accountGroup = require('../const/account_group').group;
+module.exports = app => {
+    class datacollectTender extends app.BaseService {
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'datacollect_tender';
+        }
+
+        // async getGroupInfo(pid, groupid) {
+        //     const sql = 'SELECT * FROM ?? WHERE pid = ? AND groupid = ? AND uid is NULL';
+        //     const sqlParam = [this.tableName, pid, groupid];
+        //     return await this.db.queryOne(sql, sqlParam);
+        // }
+        //
+        // async saveAudit(pid, groupid, uid) {
+        //     const data = {
+        //         pid,
+        //         groupid,
+        //         uid,
+        //         create_time: new Date(),
+        //     };
+        //     return await this.db.insert(this.tableName, data);
+        // }
+        //
+        // async saveGroup(pid, groupid) {
+        //     const transaction = await this.db.beginTransaction();
+        //     try {
+        //         // 删除所在组的用户
+        //         await transaction.delete(this.tableName, { pid, groupid });
+        //         const data = {
+        //             pid,
+        //             groupid,
+        //             create_time: new Date(),
+        //         };
+        //         await transaction.insert(this.tableName, data);
+        //         await transaction.commit();
+        //         return true;
+        //     } catch (err) {
+        //         await transaction.rollback();
+        //         throw err;
+        //     }
+        // }
+        //
+        // async delAudit(id) {
+        //     return await this.db.delete(this.tableName, { id });
+        // }
+
+        async getList(pid) {
+            return await this.db.select(this.tableName, { pid });
+        }
+
+        async updateList(pid, tids) {
+            // 初始化事务
+            const transaction = await this.db.beginTransaction();
+            try {
+                const oldList = await this.getList(pid);
+                const oldIds = this._.map(oldList, 'tid');
+                const insertTids = this._.difference(tids, oldIds);
+                const delTids = this._.difference(oldIds, tids);
+                if (insertTids.length > 0) {
+                    const insertDatas = [];
+                    for (const i of insertTids) {
+                        insertDatas.push({
+                            pid,
+                            tid: i,
+                        });
+                    }
+                    await transaction.insert(this.tableName, insertDatas);
+                }
+                if (delTids.length > 0) {
+                    for (const d of delTids) {
+                        await transaction.delete(this.tableName, { pid, tid: d });
+                    }
+                }
+                transaction.commit();
+            } catch (e) {
+                console.log(e);
+                transaction.rollback();
+            }
+        }
+
+        async add(pid, tid) {
+            const data = {
+                pid,
+                tid,
+            };
+            return await this.db.insert(this.tableName, data);
+        }
+    }
+    return datacollectTender;
+};

+ 2 - 2
app/service/ledger_tag.js

@@ -12,7 +12,7 @@ const validField = ['lid', 'share', 'color', 'comment'];
 
 module.exports = app => {
 
-    class StageBillsDgn extends app.BaseService {
+    class LedgerTag extends app.BaseService {
         /**
          * 构造函数
          *
@@ -98,5 +98,5 @@ module.exports = app => {
         }
     }
 
-    return StageBillsDgn;
+    return LedgerTag;
 };

+ 71 - 6
app/service/material.js

@@ -68,11 +68,33 @@ module.exports = app => {
             return material;
         }
 
+        async checkMaterial(tid, order) {
+            if (this.ctx.material) return;
+            const materials = await this.getSelectMaterial(tid, order);
+            this.ctx.material = materials[0]
+        }
+
         /**
          * 获取标段下的全部计量期,按倒序
          * @param tenderId
          * @return {Promise<void>}
          */
+        async getSelectMaterial(tenderId, order) {
+            const materials = await this.db.select(this.tableName, {
+                where: { tid: tenderId, order },
+            });
+            if (materials.length > 0 && materials[0].status !== auditConst.status.checked) {
+                const material = materials[0];
+                const curAuditor = await this.ctx.service.materialAudit.getCurAuditor(material.id, material.times);
+                const isActive = curAuditor ? curAuditor.id === this.ctx.session.sessionUser.accountId : material.user_id === this.ctx.session.sessionUser.accountId;
+                if (isActive) {
+                    material.curTimes = material.times;
+                    material.curOrder = curAuditor ? curAuditor.order : 0;
+                }
+            }
+            return materials;
+        }
+
         async getValidMaterials(tenderId) {
             const materials = await this.db.select(this.tableName, {
                 where: { tid: tenderId },
@@ -122,6 +144,7 @@ module.exports = app => {
                 user_id: this.ctx.session.sessionUser.accountId,
                 stage_id: data.stage_id.join(','),
                 s_order: data.s_order,
+                material_tax: this.ctx.session.sessionProject.page_show.openMaterialTax,
             };
             const transaction = await this.db.beginTransaction();
             try {
@@ -129,6 +152,7 @@ module.exports = app => {
                     newMaterial.rate = preMaterial.rate;
                     newMaterial.pre_tp = this.ctx.helper.add(preMaterial.m_tp, preMaterial.pre_tp);
                     newMaterial.ex_pre_tp = this.ctx.helper.add(preMaterial.ex_tp, preMaterial.ex_pre_tp);
+                    newMaterial.m_tax_pre_tp = preMaterial.material_tax ? this.ctx.helper.add(preMaterial.m_tax_tp, preMaterial.m_tax_pre_tp) : preMaterial.m_tax_pre_tp;
                 }
                 // 新增期记录
                 const result = await transaction.insert(this.tableName, newMaterial);
@@ -149,13 +173,14 @@ module.exports = app => {
                     // 复制调差清单工料关联表
                     await this.ctx.service.materialList.copyPreMaterialList(transaction, preMaterial, newMaterial);
                     // 修改本期应耗数量值和有效价差,需要剔除不参与调差的清单数据,并返回总金额
-                    const m_tp = await this.ctx.service.materialBills.updateNewMaterial(transaction, this.ctx.tender.id, newMaterial.id, this.ctx, newMaterial.stage_id);
+                    const [m_tp, m_tax_tp] = await this.ctx.service.materialBills.updateNewMaterial(transaction, this.ctx.tender.id, newMaterial.id, this.ctx, newMaterial.stage_id);
                     // 修改现行价格指数,并返回调差基数json
                     const ex_calc = await this.ctx.service.materialExponent.updateNewMaterial(transaction, newMaterial.id, this.ctx, newMaterial.stage_id, preMaterial.ex_calc);
                     // 计算得出本期总金额
                     const updateMaterialData = {
                         id: newMaterial.id,
                         m_tp,
+                        m_tax_tp,
                         ex_calc: JSON.stringify(ex_calc),
                     };
                     await transaction.update(this.tableName, updateMaterialData);
@@ -199,7 +224,8 @@ module.exports = app => {
                         'mb.`msg_spread` = mbh.`msg_spread`, mb.`m_up_risk` = mbh.`m_up_risk`, ' +
                         'mb.`m_down_risk` = mbh.`m_down_risk`, mb.`m_spread` = mbh.`m_spread`, ' +
                         'mb.`m_tp` = mbh.`m_tp`, mb.`pre_tp` = mbh.`pre_tp`, ' +
-                        'mb.`origin` = mbh.`origin`, mb.`is_summary` = mbh.`is_summary` ' +
+                        'mb.`m_tax_tp` = mbh.`m_tax_tp`, mb.`tax_pre_tp` = mbh.`tax_pre_tp`, ' +
+                        'mb.`origin` = mbh.`origin`, mb.`is_summary` = mbh.`is_summary`, mb.`m_tax` = mbh.`m_tax` ' +
                         'WHERE mbh.`tid` = ? AND mbh.`order` = ? AND mbh.`mb_id` = mb.`id`';
                     const sqlParam = [this.ctx.tender.id, materialInfo.order - 1];
                     await transaction.query(sql, sqlParam);
@@ -281,20 +307,33 @@ module.exports = app => {
         }
 
         /**
-         * 取当前期截止上期含税金额
+         * 取当前期截止上期含建筑税金额
          * @param {int} tid 标段id
          * @param {int} order 调差期数
          * @return {Promise<*>}
          */
         async getPreTpHs(tid, order) {
-            const sql = 'SELECT SUM(ROUND(`m_tp`*(1+ `rate`/100),2)) AS `pre_tp_hs` FROM ?? WHERE `tid` = ? AND `order` < ?';
-            const sqlParam = [this.tableName, tid, order];
+            const sql = 'SELECT SUM(ROUND(`m_tp`*(1+ `rate`/100),2)) AS `pre_tp_hs` FROM ?? WHERE `tid` = ? AND `material_tax` = ? AND `order` < ?';
+            const sqlParam = [this.tableName, tid, 0, order];
             const result = await this.db.queryOne(sql, sqlParam);
             return result.pre_tp_hs;
         }
 
         /**
-         * 取当前期截止上期含税指数金额
+         * 取当前期截止上期含材料税金额
+         * @param {int} tid 标段id
+         * @param {int} order 调差期数
+         * @return {Promise<*>}
+         */
+        async getTaxPreTpHs(tid, order) {
+            const sql = 'SELECT SUM(`m_tax_tp`) AS `tax_pre_tp_hs` FROM ?? WHERE `tid` = ? AND `material_tax` = ? AND `order` < ?';
+            const sqlParam = [this.tableName, tid, 1, order];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result.tax_pre_tp_hs;
+        }
+
+        /**
+         * 取当前期截止上期含建筑税指数金额
          * @param {int} tid 标段id
          * @param {int} order 调差期数
          * @return {Promise<*>}
@@ -305,6 +344,32 @@ module.exports = app => {
             const result = await this.db.queryOne(sql, sqlParam);
             return result.ex_pre_tp_hs;
         }
+
+        async updateMaterialTax(id, mtax) {
+            const updateData = {
+                id,
+                material_tax: mtax,
+            };
+            return await this.db.update(this.tableName, updateData);
+        }
+
+        async getMaterialTaxTp(id) {
+            const info = await this.getDataById(id);
+            return info.m_tax_tp;
+        }
+
+        async getSumMaterial(tid) {
+            const sql = 'Select sum(IFNULL(m_tp, 0) + IFNULL(ex_tp, 0)) as tp From ' + this.tableName + ' where tid = ?';
+            const result = await this.db.queryOne(sql, [tid]);
+            return result ? result.tp : 0;
+        }
+
+        async getOldMaterialTax(tid, order) {
+            const sql = 'SELECT COUNT(id) as count FROM ?? WHERE `tid` = ? AND `order` <= ? AND `material_tax` = 1';
+            const sqlParam = [this.tableName, tid, order];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result && result.count !== 0;
+        }
     }
 
     return Material;

+ 10 - 0
app/service/material_audit.js

@@ -251,8 +251,11 @@ module.exports = app => {
                         m_spread: mb.m_spread,
                         m_tp: mb.m_tp,
                         pre_tp: mb.pre_tp,
+                        m_tax_tp: mb.m_tax_tp,
+                        tax_pre_tp: mb.tax_pre_tp,
                         origin: mb.origin,
                         is_summary: mb.is_summary,
+                        m_tax: mb.m_tax,
                     };
                     mbhList.push(newMbh);
                 }
@@ -930,6 +933,13 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        async getNumByMonth(tid, startMonth, endMonth) {
+            const sql = 'SELECT COUNT(*) as num FROM ?? WHERE id in (SELECT MAX(id) FROM ?? WHERE tid = ? GROUP BY mid) AND status = ? AND end_time between ? and ?';
+            const sqlParam = [this.tableName, this.tableName, tid, auditConst.status.checked, startMonth, endMonth];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result ? result.num : 0;
+        }
     }
 
     return MaterialAudit;

+ 26 - 9
app/service/material_bills.js

@@ -225,12 +225,14 @@ module.exports = app => {
         async updateNewMaterial(transaction, tid, mid, ctx, stage_id) {
             const materialBillsData = await this.getAllDataByCondition({ where: { tid } });
             let m_tp = 0;
+            let m_tax_tp = 0;
             const materialCalculator = new MaterialCalculator(ctx, stage_id, ctx.tender.info);
             for (const mb of materialBillsData) {
-                const one_tp = await this.calcQuantityByMB(transaction, mid, mb, materialCalculator);
+                const [one_tp, one_tax_tp] = await this.calcQuantityByMB(transaction, mid, mb, materialCalculator);
                 m_tp = this.ctx.helper.add(m_tp, one_tp);
+                m_tax_tp = this.ctx.helper.add(m_tax_tp, one_tax_tp);
             }
-            return m_tp;
+            return [m_tp, m_tax_tp];
         }
 
         /**
@@ -248,21 +250,28 @@ module.exports = app => {
                 const mb_quantity = await transaction.queryOne(sql, sqlParam);
                 console.log(mb_quantity);
                 // 取历史期记录获取截止上期调差金额,并清空本期单价和时间,来源地,重新计算价差和有效价差
+                const newQuantity = this.ctx.helper.round(mb_quantity.quantity, 3);
+                const newTp = this.ctx.helper.round(this.ctx.helper.mul(newQuantity, newm_spread), 2);
                 const updateData = {
                     id: mb.id,
-                    quantity: this.ctx.helper.round(mb_quantity.quantity, 3),
+                    quantity: newQuantity,
                     msg_tp: null,
                     msg_times: null,
                     msg_spread: newmsg_spread,
                     m_spread: newm_spread,
                     origin: null,
-                    m_tp: this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(mb_quantity.quantity, 3), newm_spread), 2),
+                    m_tp: newTp,
                     pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp,
+                    m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2),
+                    tax_pre_tp: mb.m_tax_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.tax_pre_tp, mb.m_tax_tp), 2) : mb.tax_pre_tp,
                 };
                 await transaction.update(this.tableName, updateData);
-                return mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(mb_quantity.quantity, newm_spread), 2) : 0;
+                const m_tp = mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(mb_quantity.quantity, newm_spread), 2) : 0;
+                const m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(m_tp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2);
+                return [m_tp, m_tax_tp];
             } else if (mb.t_type === materialConst.t_type[1].value) {
                 const quantity = await materialCalculator.calculateExpr(mb.expr);
+                const newTp = quantity !== 0 && quantity !== null ? this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(quantity, 3), newm_spread), 2) : null;
                 const updateData = {
                     id: mb.id,
                     quantity: quantity !== 0 && quantity !== null ? this.ctx.helper.round(quantity, 3) : null,
@@ -271,11 +280,15 @@ module.exports = app => {
                     msg_spread: newmsg_spread,
                     m_spread: newm_spread,
                     origin: null,
-                    m_tp: quantity !== 0 && quantity !== null ? this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(quantity, 3), newm_spread), 2) : null,
+                    m_tp: newTp,
                     pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp,
+                    m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2),
+                    tax_pre_tp: mb.m_tax_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.tax_pre_tp, mb.m_tax_tp), 2) : mb.tax_pre_tp,
                 };
                 await transaction.update(this.tableName, updateData);
-                return mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(quantity, newm_spread), 2) : 0;
+                const m_tp = mb.is_summary === 1 ? await this.ctx.helper.round(this.ctx.helper.mul(quantity, newm_spread), 2) : 0;
+                const m_tax_tp = this.ctx.helper.round(this.ctx.helper.mul(m_tp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2);
+                return [m_tp, m_tax_tp];
             }
         }
 
@@ -325,14 +338,18 @@ module.exports = app => {
         // 更改计算总金额并返回值
         async calcMaterialMTp(transaction) {
             // 金额发生变化,则重新计算本期金额
-            const sql = 'SELECT SUM(`m_tp`) as total_price FROM ' + this.tableName + ' WHERE `tid` = ? AND `is_summary` = 1';
+            const sql = 'SELECT SUM(`m_tp`) as total_price, SUM(IF(`m_tax_tp` is null, `m_tp`, `m_tax_tp`)) as tax_total_price FROM ' + this.tableName + ' WHERE `tid` = ? AND `is_summary` = 1';
             const sqlParam = [this.ctx.tender.id];
             const tp = await transaction.queryOne(sql, sqlParam);
-            console.log(tp);
             const updateData2 = {
                 id: this.ctx.material.id,
                 m_tp: tp.total_price,
+                m_tax_tp: tp.tax_total_price,
             };
+            console.log(tp);
+            // if (this.ctx.material.material_tax) {
+            //     updateData2.m_tax_tp = tp.tax_total_price;
+            // }
             await transaction.update(this.ctx.service.material.tableName, updateData2);
             return tp.total_price;
         }

+ 6 - 2
app/service/material_list.js

@@ -216,20 +216,24 @@ module.exports = app => {
             const sqlParam = [this.ctx.material.id, mb_id];
             const mb_quantity = await transaction.queryOne(sql, sqlParam);
             console.log(mb_quantity);
+            const newQuantity = this.ctx.helper.round(mb_quantity.quantity, 3);
+            const newTp = this.ctx.helper.round(this.ctx.helper.mul(newQuantity, mbInfo.m_spread), 2);
             const updateData = {
                 id: mb_id,
                 quantity: this.ctx.helper.round(mb_quantity.quantity, 3),
-                m_tp: this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(mb_quantity.quantity, 3), mbInfo.m_spread), 2),
+                m_tp: newTp,
+                m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mbInfo.m_tax, 100))), 2),
             };
             await transaction.update(this.ctx.service.materialBills.tableName, updateData);
             // 计算本期总金额
-            const sql2 = 'SELECT SUM(`m_tp`) as total_price FROM ' + this.ctx.service.materialBills.tableName + ' WHERE `tid` = ? AND `is_summary` = 1';
+            const sql2 = 'SELECT SUM(`m_tp`) as total_price, SUM(IF(`m_tax_tp` is null, `m_tp`, `m_tax_tp`)) as tax_total_price FROM ' + this.ctx.service.materialBills.tableName + ' WHERE `tid` = ? AND `is_summary` = 1';
             const sqlParam2 = [this.ctx.tender.id];
             const tp = await transaction.queryOne(sql2, sqlParam2);
             console.log(tp);
             const updateData2 = {
                 id: this.ctx.material.id,
                 m_tp: tp.total_price,
+                m_tax_tp: tp.tax_total_price,
             };
             return await transaction.update(this.ctx.service.material.tableName, updateData2);
         }

+ 12 - 4
app/service/material_month.js

@@ -63,12 +63,14 @@ module.exports = app => {
                             const month_num = material_month.length - this.ctx.helper.arrayCount(this._.concat(this._.map(this._.filter(monthList, { mb_id: mb.id }), 'msg_tp'), one_month.msg_tp), [null, '', 0]);
                             const new_msg_tp = this.ctx.helper.round(this.ctx.helper.div(this.ctx.helper.add(mb_msg_tp_sum, one_month.msg_tp), month_num), 3);
                             const [newmsg_spread, newm_spread] = await this.ctx.service.materialBills.getSpread(mb, new_msg_tp);
+                            const newTp = this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, newm_spread), 2);
                             updateArray.push({
                                 id: mb.id,
                                 msg_tp: new_msg_tp,
                                 msg_spread: newmsg_spread,
                                 m_spread: newm_spread,
-                                m_tp: this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, newm_spread), 2),
+                                m_tp: newTp,
+                                m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2),
                             });
                         }
                     }
@@ -111,12 +113,14 @@ module.exports = app => {
                         const month_num = material_month.length - this.ctx.helper.arrayCount(this._.map(this._.filter(monthList, { mb_id: mb.id }), 'msg_tp'), [null, '', 0]);
                         const new_msg_tp = month_num !== 0 ? this.ctx.helper.round(this.ctx.helper.div(mb_msg_tp_sum, month_num), 3) : null;
                         const [newmsg_spread, newm_spread] = await this.ctx.service.materialBills.getSpread(mb, new_msg_tp);
+                        const newTp = this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, newm_spread), 2);
                         updateArray.push({
                             id: mb.id,
                             msg_tp: new_msg_tp,
                             msg_spread: newmsg_spread,
                             m_spread: newm_spread,
-                            m_tp: this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, newm_spread), 2),
+                            m_tp: newTp,
+                            m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2),
                         });
                     }
                     if (updateArray.length !== 0) await transaction.updateRows(this.ctx.service.materialBills.tableName, updateArray);
@@ -151,12 +155,14 @@ module.exports = app => {
                     const month_num = material_month.length - this.ctx.helper.arrayCount(this._.map(monthList, 'msg_tp'), [null, '', 0]);
                     const new_msg_tp = month_num !== 0 ? this.ctx.helper.round(this.ctx.helper.div(mb_msg_tp_sum, month_num), 3) : null;
                     const [newmsg_spread, newm_spread] = await this.ctx.service.materialBills.getSpread(mbInfo, new_msg_tp);
+                    const newTp = this.ctx.helper.round(this.ctx.helper.mul(mbInfo.quantity, newm_spread), 2);
                     await transaction.update(this.ctx.service.materialBills.tableName, {
                         id: mbInfo.id,
                         msg_tp: new_msg_tp,
                         msg_spread: newmsg_spread,
                         m_spread: newm_spread,
-                        m_tp: this.ctx.helper.round(this.ctx.helper.mul(mbInfo.quantity, newm_spread), 2),
+                        m_tp: newTp,
+                        m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mbInfo.m_tax, 100))), 2),
                     });
                 }
                 const m_tp = await this.ctx.service.materialBills.calcMaterialMTp(transaction);
@@ -203,12 +209,14 @@ module.exports = app => {
                         const month_num = material_month.length - this.ctx.helper.arrayCount(this._.map(this._.filter(monthList, { mb_id: mb.id }), 'msg_tp'), [null, '', 0]);
                         const new_msg_tp = month_num !== 0 ? this.ctx.helper.round(this.ctx.helper.div(mb_msg_tp_sum, month_num), 3) : null;
                         const [newmsg_spread, newm_spread] = await this.ctx.service.materialBills.getSpread(mb, new_msg_tp);
+                        const newTp = this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, newm_spread), 2);
                         mbUpdateArray.push({
                             id: mb.id,
                             msg_tp: new_msg_tp,
                             msg_spread: newmsg_spread,
                             m_spread: newm_spread,
-                            m_tp: this.ctx.helper.round(this.ctx.helper.mul(mb.quantity, newm_spread), 2),
+                            m_tp: newTp,
+                            m_tax_tp: this.ctx.helper.round(this.ctx.helper.mul(newTp, (1 + this.ctx.helper.div(mb.m_tax, 100))), 2),
                         });
                     }
                     if (mbUpdateArray.length !== 0) await transaction.updateRows(this.ctx.service.materialBills.tableName, mbUpdateArray);

+ 22 - 0
app/service/notice_push.js

@@ -52,6 +52,28 @@ module.exports = app => {
             })
             return notice
         }
+
+        /**
+         * 查询所有推送记录,不重复数据
+         * @param {Integer} pid - 项目id
+         * @param {Integer} uid - 查询人id
+         */
+        async getNoticeByDataCollect(pid, tenderIds = []) {
+            const wheres = { pid };
+            let notice = await this.db.select(this.tableName, {
+                where: wheres,
+                orders: [['create_time', 'desc']],
+                limit: 40,
+                offset: 0
+            });
+            notice = this._.uniqBy(notice, 'content');
+            notice = notice.map(v => {
+                const extra = JSON.parse(v.content);
+                delete v.content;
+                return { ...v, ...extra }
+            });
+            return notice
+        }
     }
     return NoticePush
 }

+ 7 - 0
app/service/project.js

@@ -184,6 +184,13 @@ module.exports = app => {
             await this.db.update(this.tableName, { id: id, sjs_rela: JSON.stringify(sjsRela) });
             return sjsField;
         }
+
+        async updatePageshow(id) {
+            const result = await this.db.update(this.tableName, {
+                id, page_show: JSON.stringify(this.ctx.session.sessionProject.page_show),
+            });
+            return result.affectedRows === 1;
+        }
     }
 
     return Project;

+ 11 - 0
app/service/report.js

@@ -160,6 +160,14 @@ module.exports = app => {
                                 customDefine.gather_select, customSelect ? customSelect.gather_select : null));
                             runnableKey.push(filter);
                             break;
+                        case 'mem_select_material':
+                            runnableRst.push(service.material.getSelectMaterial(params.tender_id, params.material_order));
+                            runnableKey.push(filter);
+                            break;
+                        case 'mem_select_material_audit':
+                            runnableRst.push(service.reportMemory.getSelectMaterialAuditors(params.tender_id, params.material_order));
+                            runnableKey.push(filter);
+                            break;
                         case 'mem_material':
                             runnableRst.push(service.reportMemory.getMaterial(params.tender_id, params.material_order, memFieldKeys[filter]));
                             runnableKey.push(filter);
@@ -263,6 +271,9 @@ module.exports = app => {
                     case 'mem_change_bills':
                         rst[filter] = await service.reportMemory.getChangeBillsData(params.tender_id, params.stage_id, memFieldKeys[filter]);
                         break;
+                    case 'mem_change_audit':
+                        rst[filter] = await service.reportMemory.getChangeAuditData(params.tender_id, params.stage_id, memFieldKeys[filter]);
+                        break;
                     case 'mem_jh_im_change':
                         const jhHelper1 = new rptCustomData.jhHelper(this.ctx);
                         rst[filter] = await jhHelper1.convert(params.tender_id, params.stage_id, memFieldKeys[filter], customDefine.option);

+ 51 - 2
app/service/report_memory.js

@@ -791,6 +791,16 @@ module.exports = app => {
 
         }
 
+        async _generateChangeAudit() {
+            if (!!this.changeData.audit) return;
+
+            this.changeData.audit = [];
+            for (const c of this.changeData.change) {
+                const changeAudit = await this.ctx.service.changeAudit.getListGroupByTimes(c.cid, c.times);
+                this.changeData.audit.push(...changeAudit);
+            }
+        }
+
         async getChangeData(tid, sid, fields) {
             try {
                 await this.ctx.service.tender.checkTender(tid);
@@ -813,6 +823,18 @@ module.exports = app => {
             }
         }
 
+        async getChangeAuditData(tid, sid, fields) {
+            try {
+                await this.ctx.service.tender.checkTender(tid);
+
+                await this._generateChange(tid);
+                await this._generateChangeAudit();
+                return this.changeData.audit;
+            } catch (err) {
+                return [];
+            }
+        }
+
         async getStageJgcl(tid, sid, fields) {
             try {
                 await this.ctx.service.tender.checkTender(tid);
@@ -921,8 +943,34 @@ module.exports = app => {
             }
         }
 
+        async getSelectMaterialAuditors(tid, material_order, fields) {
+            await this.ctx.service.material.checkMaterial(tid, material_order);
+            const auditors = await this.ctx.service.materialAudit.getFinalAuditGroup(this.ctx.material.id, this.ctx.material.curTimes);
+            const user = await this.ctx.service.projectAccount.getDataById(this.ctx.material.user_id);
+            const result = [{
+                aid: user.id,
+                name: user.name,
+                company: user.company,
+                role: user.role,
+                mobile: user.mobile,
+                telephone: user.telephone,
+                sign_path: user.sign_path,
+                opinion: user.opinion,
+                end_time: auditors && auditors.length > 0 ? auditors[0].begin_time : null,
+                sort: 0,
+            }, ...auditors];
+            return result;
+        }
+
         async getMaterial(tender_id, material_order, fields) {
-            return await this.ctx.service.material.getValidMaterials(tender_id);
+            const result = await this.ctx.service.material.getValidMaterials(tender_id);
+            if (this._checkFieldsExist(fields, ['checked_time'])) {
+                for (const r of result) {
+                    const auditors = await this.ctx.service.materialAudit.getFinalAuditGroup(r.id, r.curTimes || r.times);
+                    r.checked_time = !r.curTimes ? auditors[auditors.length - 1].end_time : null;
+                }
+            }
+            return result;
         }
 
         _completeMaterialGl(materialGl) {
@@ -956,7 +1004,7 @@ module.exports = app => {
                     const material = this.ctx.helper._.find(materials, {order: material_order});
                     if (!material) return [];
                     const sql = 'SELECT m.id, m.tid, m.mid, m.t_type, m.code, m.name, m.unit, m.spec, m.m_type,' +
-                        '    m.basic_price, m.basic_times, m.remark, m.in_time,' +
+                        '    m.basic_price, m.basic_times, m.remark, m.in_time, m.m_tax, m.m_tax_tp, m.tax_pre_tp,' +
                         '    mh.quantity, mh.expr, mh.msg_tp, mh.msg_times, mh.msg_spread, mh.m_up_risk, mh.m_down_risk, mh.m_spread' +
                         '  FROM ' + this.ctx.service.materialBills.tableName + ' m' +
                         '  LEFT JOIN ' + this.ctx.service.materialBillsHistory.tableName + ' mh' +
@@ -964,6 +1012,7 @@ module.exports = app => {
                         '  WHERE mh.mid = ?';
                     const sqlParam = [material.id];
                     result = await this.ctx.app.mysql.query(sql, sqlParam);
+                    console.log(result);
                 }
                 this._completeMaterialGl(result);
                 return result;

+ 7 - 0
app/service/revise_audit.js

@@ -803,6 +803,13 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        async getNumByMonth(tid, startMonth, endMonth) {
+            const sql = 'SELECT COUNT(*) as num FROM ?? WHERE id in (SELECT MAX(id) FROM ?? WHERE tender_id = ? GROUP BY rid) AND status = ? AND end_time between ? and ?';
+            const sqlParam = [this.tableName, this.tableName, tid, auditConst.status.checked, startMonth, endMonth];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result ? result.num : 0;
+        }
     }
 
     return ReviseAudit;

+ 14 - 0
app/service/stage.js

@@ -693,6 +693,20 @@ module.exports = app => {
             }
             return list;
         }
+
+        async getStageByDataCollect(tenderId) {
+            const stages = await this.db.select(this.tableName, {
+                columns: ['s_time', 'contract_tp', 'qc_tp', 'pre_contract_tp', 'pre_qc_tp'],
+                where: { tid: tenderId },
+                orders: [['order', 'desc']],
+            });
+            for (const s of stages) {
+                s.tp = this.ctx.helper.add(s.contract_tp, s.qc_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);
+            }
+            return stages;
+        }
     }
 
     return Stage;

+ 23 - 1
app/service/stage_audit.js

@@ -17,6 +17,7 @@ const shenpiConst = require('../const/shenpi');
 const payConst = require('../const/deal_pay');
 const pushType = require('../const/audit').pushType;
 const syncApiConst = require('../const/sync_api');
+const measureType = require('../const/tender').measureType;
 
 module.exports = app => {
     class StageAudit extends app.BaseService {
@@ -244,6 +245,16 @@ module.exports = app => {
             return true;
         }
 
+        async _updateTender(transaction) {
+            if (!this.ctx.tender) return;
+            if (this.ctx.tender.data.measure_type !== measureType.gcl.value) return;
+
+            const sum = await this.ctx.service.ledger.addUp({ tender_id: this.ctx.tender.id/* , is_leaf: true*/ });
+            await transaction.update(this.ctx.service.tender.tableName, {
+                id: this.ctx.tender.id, total_price: sum.total_price, deal_tp: sum.deal_tp
+            });
+        }
+
         /**
          * 开始审批
          *
@@ -263,6 +274,7 @@ module.exports = app => {
 
             const transaction = await this.db.beginTransaction();
             try {
+                await this._updateTender(transaction);
                 await transaction.update(this.tableName, {
                     id: audit.id,
                     status: auditConst.status.checking,
@@ -365,6 +377,7 @@ module.exports = app => {
             const transaction = await this.db.beginTransaction();
 
             try {
+                await this._updateTender(transaction);
                 // 添加推送
                 const noticeContent = await this.getNoticeContent(pid, audit.tid, stageId, audit.aid);
                 const auditors = await this.getAuditGroupByListWithOwner(stageId, times);
@@ -548,6 +561,7 @@ module.exports = app => {
 
             const transaction = await this.db.beginTransaction();
             try {
+                await this._updateTender(transaction);
                 // 添加推送
                 const noticeContent = await this.getNoticeContent(pid, audit.tid, stageId, audit.aid);
                 const records = [
@@ -680,6 +694,7 @@ module.exports = app => {
             const tpData = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage);
             const transaction = await this.db.beginTransaction();
             try {
+                await this._updateTender(transaction);
                 // 添加推送
                 const noticeContent = await this.getNoticeContent(pid, audit.tid, stageId, audit.aid);
                 const records = [
@@ -1246,6 +1261,7 @@ module.exports = app => {
                     order++;
                 }
 
+                await this._updateTender(transaction);
                 // 拷贝新一次审核流程列表
                 await transaction.insert(this.tableName, auditors);
 
@@ -1264,7 +1280,6 @@ module.exports = app => {
                 const yfPay = stagePay.find(function(x) {
                     return x.ptype === payConst.payType.yf;
                 });
-                console.log(stagePay);
                 const sfPay = stagePay.find(function(x) {
                     return x.ptype === payConst.payType.sf;
                 });
@@ -1368,6 +1383,13 @@ module.exports = app => {
             }
             return result;
         }
+
+        async getNumByMonth(tid, startMonth, endMonth) {
+            const sql = 'SELECT COUNT(*) as num FROM ?? WHERE id in (SELECT MAX(id) FROM ?? WHERE tid = ? GROUP BY sid) AND status = ? AND end_time between ? and ?';
+            const sqlParam = [this.tableName, this.tableName, tid, auditConst.status.checked, startMonth, endMonth];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result ? result.num : 0;
+        }
     }
 
     return StageAudit;

+ 1 - 1
app/service/stage_bills.js

@@ -110,7 +110,7 @@ module.exports = app => {
                 '  Where tid = ? and sid = ? ' + filterSql;
 
             const result = await this.db.query(sql, [tid, sid]);
-            const stageBills = this.ctx.helper.filterLastestData(result, ['lid']);
+            const stageBills = this.ctx.helper.filterLastestData2(result, ['lid']);
             if (!lid || lid instanceof Array) return stageBills;
             return stageBills[0];
         }

+ 2 - 6
app/service/stage_detail_att.js

@@ -123,18 +123,14 @@ module.exports = app => {
             await this._analysisDetailAtt(detailAtt);
 
             const index = detailAtt.attachment.findIndex(x => { return x.file_id === fileId });
-            if (index < 0) throw '不存在文件';
+            if (index < 0) throw '不存在文件';
             const att = detailAtt.attachment[index];
             if (att.uid !== this.ctx.session.sessionUser.accountId) throw '您无权删除该文件';
 
             detailAtt.attachment.splice(index, 1);
             await this.db.update(this.tableName, { id: detailAtt.id, attachment: JSON.stringify(detailAtt.attachment) });
 
-            // if (fs.existsSync(path.join(this.ctx.app.baseDir, att.filepath))) {
-            //     await fs.unlinkSync(path.join(this.ctx.app.baseDir, att.filepath));
-            // }
-            await this.ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + att.filepath);
-
+            await this.ctx.app.fujianOss.delete(this.ctx.app.config.fujianOssFolder + att.filepath);
 
             await this._complete4Output(detailAtt);
             return detailAtt;

+ 2 - 2
app/service/stage_shoufang.js

@@ -42,7 +42,7 @@ module.exports = app => {
                 const qr_png = await qr.image(text || '', { type: 'png', size: size || 5, margin: margin || 1 });
                 const qrcodePath = 'app/public/upload/' + this.ctx.tender.id + '/stage/shoufang/qrcode/' + result.insertId + '.png';
                 // await this.ctx.helper.saveStreamFile(qr_png, path.resolve(this.app.baseDir, 'app/' + qrcodePath));
-                await this.ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + qrcodePath, qr_png);
+                await this.ctx.app.fujianOss.put(this.ctx.app.config.fujianOssFolder + qrcodePath, qr_png);
                 await transaction.update(this.tableName, { id: result.insertId, qrcode: qrcodePath });
                 await transaction.commit();
                 return result;
@@ -72,7 +72,7 @@ module.exports = app => {
                 // if (fs.existsSync(path.join(this.app.baseDir, 'app/' + sfInfo.qrcode))) {
                 //     await fs.unlinkSync(path.join(this.app.baseDir, 'app/' + sfInfo.qrcode));
                 // }
-                await this.ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + sfInfo.qrcode);
+                await this.ctx.app.fujianOss.delete(this.ctx.app.config.fujianOssFolder + sfInfo.qrcode);
                 await transaction.delete(this.ctx.service.stageShoufangAtt.tableName, { sfid });
                 await transaction.delete(this.tableName, { id: sfid });
                 await transaction.commit();

+ 7 - 0
app/service/tender.js

@@ -253,6 +253,11 @@ module.exports = app => {
                 if (tender) {
                     tender.category = tender.category && tender.category !== '' ? JSON.parse(tender.category) : null;
                 }
+
+                // 是否加入到决策大屏中
+                if (sessionProject.page_show.addDataCollect === 0) {
+                    await this.ctx.service.datacollectTender.add(sessionProject.id, operate.insertId);
+                }
                 return tender;
             } catch (error) {
                 await this.transaction.rollback();
@@ -365,6 +370,8 @@ module.exports = app => {
 
                 await transaction.delete(this.ctx.service.advanceFile.tableName, { tid: id });
 
+                await transaction.delete(this.ctx.service.datacollectTender.tableName, { pid: this.ctx.session.sessionProject.id, tid: id });
+
                 // 记录删除日志
                 await this.ctx.service.projectLog.addProjectLog(transaction, projectLogConst.type.tender, projectLogConst.status.delete, tenderMsg.name, id);
                 await transaction.commit();

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

@@ -94,16 +94,19 @@
                                             <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
                                                 <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- item.name %>
                                                 <small class="text-muted"><%- item.role %></small>
+                                                <span class="pull-right">原报</span>
                                             </li>
                                             <% } else if(idx === auditors.length -1 && idx !== 0) { %>
                                             <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
                                                 <i class="fa fa fa-stop-circle"></i> <%- item.name %>
                                                 <small class="text-muted"><%- item.role %></small>
+                                                <span class="pull-right">终审</span>
                                             </li>
                                             <% } else {%>
                                             <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
                                                 <i class="fa fa-chevron-circle-down"></i> <%- item.name %>
                                                 <small class="text-muted"><%- item.role %></small>
+                                                <span class="pull-right"><%- ctx.helper.transFormToChinese(idx) -%>审</span>
                                             </li>
                                             <% } %>
                                             <% }) %>

+ 5 - 1
app/view/budget/compare.ejs

@@ -33,4 +33,8 @@
             </div>
         </div>
     </div>
-</div>
+</div>
+<script>
+    const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const tenderList = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
+</script>

+ 2 - 18
app/view/budget/compare_modal.ejs

@@ -4,25 +4,9 @@
             <div class="modal-header">
                 <h5 class="modal-title">选择决算标段</h5>
             </div>
-            <div class="modal-body" style="display: block; overflow: auto; height: 500px">
+            <div class="modal-body">
                 <h5>可选标段</h5>
-                <table class="table table-sm table-bordered">
-                    <thead>
-                    <tr class="text-center">
-                        <th>选择</th>
-                        <th>标段名称</th>
-                        <th>期数</th>
-                        <th>状态</th>
-                    </tr>
-                    </thead>
-                    <tbody>
-                    <% for (const t of tenderList) { %>
-                    <tr>
-                        <td class="text-center"><input type="checkbox" name="sf-tender" tid="<%- t.id %>"><td><%- t.name %></td><td>第<%- t.lastStage.order %>期</td><td><%- auditConst.stage.statusString[t.lastStage.status] %></td>
-                    </tr>
-                    <% } %>
-                    </tbody>
-                </table>
+                <div id="sf-spread" style="height: 300px"></div>
             </div>
             <div class="modal-footer">
                 <div class="form-check form-check-inline">

+ 2 - 22
app/view/budget/detail.ejs

@@ -67,31 +67,9 @@
                         </div>
                     </div>
                     <div id="std-xmj" class="tab-pane tab-select-show">
-                        <div class="sjs-bar-2">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const [i, c] of stdChapters.entries()) { %>
-                                    <option value="<%- c.id %>" <%- (i===0 ? ' selected' : '') %>><%- c.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-xmj-spread" class="sjs-sh-2">
-                        </div>
                     </div>
                     <% if (needGcl) { %>
                     <div id="std-gcl" class="tab-pane tab-select-show">
-                        <div class="sjs-bar-3">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const [i, b] of stdBills.entries()) { %>
-                                    <option value="<%- b.id %>" <%- (i===0 ? ' selected' : '') %>><%- b.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-gcl-spread" class="sjs-sh-3">
-                        </div>
                     </div>
                     <% } %>
                 </div>
@@ -115,6 +93,8 @@
     </div>
 </div>
 <script>
+    const stdChapters = JSON.parse(unescape('<%- escape(JSON.stringify(stdChapters)) %>'));
+    const stdBills = JSON.parse(unescape('<%- escape(JSON.stringify(stdBills)) %>'));
     const readOnly = <%- ctx.budget.readOnly %>;
     const needGcl = <%- needGcl %>;
     const spreadSetting = JSON.parse('<%- JSON.stringify(spreadSetting) %>');

+ 4 - 1
app/view/budget/list.ejs

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

+ 3 - 10
app/view/budget/list_modal.ejs

@@ -77,16 +77,9 @@
             <div class="modal-header">
                 <h5 class="modal-title">选择决算标段</h5>
             </div>
-            <div class="modal-body" style="display: block; overflow: auto; height: 500px">
+            <div class="modal-body">
                 <h5>可选标段</h5>
-                <table class="table table-sm table-bordered">
-                    <tr class="text-center"><th>选择</th><th>标段名称</th><th>期数</th><th>状态</th></tr>
-                    <tbody id="valid-rela-tender">
-                    <% for (const t of tenderList) { %>
-                    <tr><td class="text-center"><input type="checkbox" name="select-rela-check" tid="<%- t.id %>"></td><td><%- t.name %></td><td>第<%- t.lastStage.order %>期</td><td><%- auditConst.stage.statusString[t.lastStage.status] %></td></tr>
-                    <% } %>
-                    </tbody>
-                </table>
+                <div id="sr-spread" style="height: 300px"></div>
             </div>
             <div class="modal-footer">
                 <div class="form-check form-check-inline">
@@ -94,7 +87,7 @@
                     <label class="form-check-label" for="sr-select-all">全选</label>
                 </div>
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-primary" onclick="relaTender();">确定</button>
+                <button type="button" class="btn btn-sm btn-primary" id="select-rela-ok">确定</button>
             </div>
         </div>
     </div>

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

@@ -326,7 +326,7 @@
                         </div>
                     </div>
                     <div class="tab-pane" id="bgfujian">
-                        <div class="sjs-sh-1">
+                        <div class="sjs-sh-1" style="overflow: auto">
                             <div class="p-2">
                                 <table class="table table-bordered" style="word-break:break-all; table-layout: fixed">
                                     <thead>
@@ -383,7 +383,7 @@
     </div>
 </div>
 <script>
-    const tenderName = '<%- tender.name %>';
+    const tenderName = JSON.parse(unescape('<%- escape(JSON.stringify(tender.name)) %>'));
     const tenderId = '<%- tender.id %>';
     const totalPriceUnit = '<%- tpUnit %>';
     const unitPriceUnit = '<%- upUnit %>';

+ 2 - 22
app/view/change/revise.ejs

@@ -95,30 +95,8 @@
                     <div id="search" class="tab-pane">
                     </div>
                     <div id="std-xmj" class="tab-pane">
-                        <div class="sjs-bar">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const c of stdChapters) { %>
-                                    <option value="<%- c.id %>" <% if (stdChapters.indexOf(c) === 0) { %>selected<% } %>><%- c.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-xmj-spread" class="sjs-sh">
-                        </div>
                     </div>
                     <div id="std-gcl" class="tab-pane">
-                        <div class="sjs-bar">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const b of stdBills) { %>
-                                    <option value="<%- b.id %>" <% if (stdBills.indexOf(b) === 0) { %>selected<% } %>><%- b.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-gcl-spread" class="sjs-sh">
-                        </div>
                     </div>
                     <div id="deal-bills" class="tab-pane">
                         <div class="sjs-bar">
@@ -164,6 +142,8 @@
     </div>
 </div>
 <script>
+    const stdChapters = JSON.parse(unescape('<%- escape(JSON.stringify(stdChapters)) %>'));
+    const stdBills = JSON.parse(unescape('<%- escape(JSON.stringify(stdBills)) %>'));
     const readOnly = <%- readOnly %>;
     const isTz = <%- ctx.tender.data.measure_type === measureType.tz.value %>;
     const billsSpreadSetting = JSON.parse('<%- JSON.stringify(ledgerSpread) %>');

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1501 - 391
app/view/datacollect/index.ejs


+ 2 - 22
app/view/ledger/explode.ejs

@@ -109,30 +109,8 @@
                     <div id="search" class="tab-pane tab-select-show">
                     </div>
                     <div id="std-xmj" class="tab-pane tab-select-show">
-                        <div class="sjs-bar-2">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const c of stdChapters) { %>
-                                    <option value="<%- c.id %>" <% if (stdChapters.indexOf(c) === 0) { %>selected<% } %>><%- c.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-xmj-spread" class="sjs-sh-2">
-                        </div>
                     </div>
                     <div id="std-gcl" class="tab-pane tab-select-show">
-                        <div class="sjs-bar-3">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const b of stdBills) { %>
-                                    <option value="<%- b.id %>" <% if (stdBills.indexOf(b) === 0) { %>selected<% } %>><%- b.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-gcl-spread" class="sjs-sh-3">
-                        </div>
                     </div>
                     <div id="deal-bills" class="tab-pane tab-select-show">
                         <div class="sjs-bar-4">
@@ -327,6 +305,8 @@
         key: 'ledger-pos',
         colWidth: true,
     };
+    const stdChapters = JSON.parse(unescape('<%- escape(JSON.stringify(stdChapters)) %>'));
+    const stdBills = JSON.parse(unescape('<%- escape(JSON.stringify(stdBills)) %>'));
     $('.sp-list-btn').click(function () {
         const type = $(this).data('type')
         if (type === 'hide') {

+ 7 - 1
app/view/ledger/explode_modal.ejs

@@ -63,12 +63,18 @@
                 <h5 class="modal-title">批量插入清单-计量单元</h5>
             </div>
             <div class="modal-body">
-                <div class="custom-control custom-checkbox mb-2">
+                <div class="custom-control custom-checkbox mb-2 d-inline-block">
                     <label class="form-check-label">
                         <input class="form-check-input" type="checkbox" name="batch-filter">
                         过滤无计量单元的清单
                     </label>
                 </div>
+                <div class="custom-control custom-checkbox mb-2 d-inline-block">
+                    <label class="form-check-label">
+                        <input class="form-check-input" type="checkbox" name="batch-transpose">
+                        竖向粘贴
+                    </label>
+                </div>
                 <div class="row">
                     <div class="col-6">
                         <h6>清单信息</h6>

+ 54 - 22
app/view/material/exponent.ejs

@@ -49,29 +49,61 @@
                             </select>
                         </div>
                     </div>
-                    <div class="sp-wrap" style="max-width: 800px;min-width: 500px;">
-                        <div class="col-12 p-0">
-                            <table class="table table-sm table-bordered">
-                                <tr><th rowspan="2"></th><th colspan="2" class="text-center">信息价</th><th colspan="2" class="text-center">价格指数</th></tr>
-                                <tr class="text-center"><th>本期金额</th><th>截止本期金额</th>
-                                    <th>本期金额
-                                        <a href="javascript:void(0);" id="ex_expr" data-toggle="tooltip" data-placement="bottom" title="本期价差:<%- material.ex_expr ? material.ex_expr : '' %>"><i class="fa fa-question-circle-o"></i></a></th>
-                                    <th>截止本期金额</th></tr>
-                                <tr id="tp_set"><td>材料价差费用</td>
-                                    <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(material.m_tp, 2) : null %></td>
-                                    <td class="text-center"><%= material.m_tp !== null || material.pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.pre_tp, material.m_tp), 2) : null %></td>
-                                    <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(material.ex_tp, 2) : null %></td>
-                                    <td class="text-center"><%= material.ex_tp !== null || material.ex_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.ex_pre_tp, material.ex_tp), 2) : null %></td>
-                                </tr>
-                                <tr id="rate_set"><td>材料价差费用(含税)</td>
-                                    <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2) : null %></td>
-                                    <td class="text-center"><%= material.m_tp !== null || pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2)), 2) : null %></td>
-                                    <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2) : null %></td>
-                                    <td class="text-center"><%= material.ex_tp !== null || ex_pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(ex_pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2)), 2) : null %></td>
-                                </tr>
-                            </table>
+                    <% if (!material.material_tax && !old_had_tax) { %>
+                        <div class="sp-wrap" style="max-width: 800px;min-width: 500px;">
+                            <div class="col-12 p-0">
+                                <table class="table table-sm table-bordered">
+                                    <tr><th rowspan="2"></th><th colspan="2" class="text-center">信息价</th><th colspan="2" class="text-center">价格指数</th></tr>
+                                    <tr class="text-center"><th>本期金额</th><th>截止本期金额</th>
+                                        <th>本期金额
+                                            <a href="javascript:void(0);" id="ex_expr" data-toggle="tooltip" data-placement="bottom" title="本期价差:<%- material.ex_expr ? material.ex_expr : '' %>"><i class="fa fa-question-circle-o"></i></a></th>
+                                        <th>截止本期金额</th></tr>
+                                    <tr id="tp_set"><td>材料价差费用</td>
+                                        <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(material.m_tp, 2) : null %></td>
+                                        <td class="text-center"><%= material.m_tp !== null || material.pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.pre_tp, material.m_tp), 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(material.ex_tp, 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null || material.ex_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.ex_pre_tp, material.ex_tp), 2) : null %></td>
+                                    </tr>
+                                    <tr id="rate_set"><td>材料价差费用(含建筑税)</td>
+                                        <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2) : null %></td>
+                                        <td class="text-center"><%= material.m_tp !== null || pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2)), 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null || ex_pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(ex_pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2)), 2) : null %></td>
+                                    </tr>
+                                </table>
+                            </div>
                         </div>
-                    </div>
+                    <% } else { %>
+                        <div class="sp-wrap" style="max-width: 800px;min-width: 500px;">
+                            <div class="col-12 p-0">
+                                <table class="table table-sm table-bordered">
+                                    <tr><th rowspan="2"></th><th colspan="2" class="text-center">信息价</th><th colspan="2" class="text-center">价格指数</th></tr>
+                                    <tr class="text-center"><th>本期金额</th><th>截止本期金额</th>
+                                        <th>本期金额
+                                            <a href="javascript:void(0);" id="ex_expr" data-toggle="tooltip" data-placement="bottom" title="本期价差:<%- material.ex_expr ? material.ex_expr : '' %>"><i class="fa fa-question-circle-o"></i></a></th>
+                                        <th>截止本期金额</th></tr>
+                                    <tr id="tp_set"><td>材料价差费用</td>
+                                        <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(material.m_tp, 2) : null %></td>
+                                        <td class="text-center"><%= material.m_tp !== null || material.pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.pre_tp, material.m_tp), 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(material.ex_tp, 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null || material.ex_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.ex_pre_tp, material.ex_tp), 2) : null %></td>
+                                    </tr>
+                                    <tr id="rate_set"><td>材料价差费用(含材料税)</td>
+                                        <td class="text-center"><%= material.m_tax_tp !== null ? material.m_tax_tp : null %></td>
+                                        <td class="text-center"><%= material.m_tax_tp !== null || material.tax_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.tax_pre_tp, material.m_tax_tp), 2) : null %></td>
+                                        <td class="text-center">-</td>
+                                        <td class="text-center">-</td>
+                                    </tr>
+                                    <tr id="rate_set"><td>材料价差费用(含建筑税)</td>
+                                        <td class="text-center">-</td>
+                                        <td class="text-center"><%= pre_tp_hs !== null ? pre_tp_hs : '-' %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2) : null %></td>
+                                        <td class="text-center"><%= material.ex_tp !== null || ex_pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(ex_pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2)), 2) : null %></td>
+                                    </tr>
+                                </table>
+                            </div>
+                        </div>
+                    <% } %>
                 </div>
             </div>
             <div id="right-view" class="c-body" style="display:none;width: 33%">

+ 11 - 7
app/view/material/index.ejs

@@ -23,19 +23,21 @@
                         <th rowspan="2">期数</th>
                         <th class="text-center" rowspan="2">添加时间</th>
                         <th class="text-center" rowspan="2">计量期</th>
-                        <th class="text-center" colspan="2">信息价调差</th>
+                        <th class="text-center" colspan="<% if (openMaterialTax && !allMaterialTax) { %>3<% } else { %>2<% } %>">信息价调差</th>
                         <th class="text-center" colspan="2">指数法调差</th>
-                        <th class="text-center" colspan="2">合计</th>
+                        <th class="text-center" colspan="<% if (openMaterialTax) { %>3<% } else { %>2<% } %>">合计</th>
                         <th class="text-center" rowspan="2">审批进度</th>
                         <th class="text-center" rowspan="2" width="140">操作</th>
                     </tr>
                     <tr>
                         <th class="text-center">价差费用</th>
-                        <th class="text-center">价差费用(含税)</th>
+                        <% if (openMaterialTax) { %><th class="text-center">价差费用(含材料税)</th><% } %>
+                        <% if ((openMaterialTax && !allMaterialTax) || !openMaterialTax) { %><th class="text-center">价差费用(含建筑税)</th><% } %>
                         <th class="text-center">价差费用</th>
-                        <th class="text-center">价差费用(含税)</th>
+                        <th class="text-center">价差费用(含建筑税)</th>
                         <th class="text-center">价差费用</th>
-                        <th class="text-center">价差费用(含税)</th>
+                        <% if (openMaterialTax) { %><th class="text-center">价差费用(含材料税)</th><% } %>
+                        <th class="text-center">价差费用(含建筑税)</th>
                     </tr>
                     </thead>
                     <tbody>
@@ -47,11 +49,13 @@
                             <td class="text-center"><%= moment(m.in_time).format('YYYY-MM-DD') %></td>
                             <td class="text-center">第 <%= m.s_order %> 期</td>
                             <td class="text-right"><%= m.m_tp !== null ? ctx.helper.round(m.m_tp, 2) : null %></td>
-                            <td class="text-right"><%= m.m_tp !== null ? ctx.helper.round(ctx.helper.mul(m.m_tp, 1+m.rate/100), 2) : null %></td>
+                            <% if (openMaterialTax) { %><td class="text-right"><% if (m.material_tax) { %><% if (m.m_tax_tp) { %><%- m.m_tax_tp %><% } else { %><%- m.m_tp %><% } %><% } %></td><% } %>
+                            <% if ((openMaterialTax && !allMaterialTax) || !openMaterialTax) { %><td class="text-right"><% if (!m.material_tax) { %><%= m.m_tp !== null ? ctx.helper.round(ctx.helper.mul(m.m_tp, 1+m.rate/100), 2) : null %><% } %></td><% } %>
                             <td class="text-right"><%= m.ex_tp !== null ? ctx.helper.round(m.ex_tp, 2) : null %></td>
                             <td class="text-right"><%= m.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(m.ex_tp, 1+m.rate/100), 2) : null %></td>
                             <td class="text-right"><%= ctx.helper.add(ctx.helper.round(m.ex_tp, 2), ctx.helper.round(m.m_tp, 2)) %></td>
-                            <td class="text-right"><%= ctx.helper.add(ctx.helper.round(ctx.helper.mul(m.ex_tp, 1+m.rate/100), 2), ctx.helper.round(ctx.helper.mul(m.m_tp, 1+m.rate/100), 2)) %></td>
+                            <% if (openMaterialTax) { %><td class="text-right"><% if (m.material_tax) { %><% if (m.m_tax_tp) { %><%- m.m_tax_tp %><% } else { %><%- m.m_tp %><% } %><% } %></td><% } %>
+                            <td class="text-right"><% if (m.material_tax) { %><%= m.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(m.ex_tp, 1+m.rate/100), 2) : null %><% } else { %><%= ctx.helper.add(ctx.helper.round(ctx.helper.mul(m.ex_tp, 1+m.rate/100), 2), ctx.helper.round(ctx.helper.mul(m.m_tp, 1+m.rate/100), 2)) %><% } %></td>
                             <td class="<%- auditConst.auditProgressClass[m.status] %>">
                                 <% if (m.curAuditor) { %>
                                     <a href="#sp-list" data-toggle="modal" data-target="#sp-list" m-order="<%- m.order %>"><%- m.curAuditor.name %><%if (m.curAuditor.role !== '' && m.curAuditor.role !== null) { %>-<%- m.curAuditor.role %><% } %></a>

+ 39 - 3
app/view/material/info.ejs

@@ -37,12 +37,13 @@
                 <!--下部分-->
                 <div class="bcontent-wrap" id="main-bottom">
                     <div id="main-resize" class="resize-y" r-Type="height" div1=".sjs-height-1" div2=".bcontent-wrap" title="调整大小"><!--调整上下高度条--></div>
+
                     <div class="bc-bar mb-1">
                         <div class="input-group input-group-sm ">
                             <div class="input-group-prepend">
-                                <span class="input-group-text" id="basic-addon1">增值税税率</span>
+                                <span class="input-group-text" id="basic-addon1">建筑增值税</span>
                             </div>
-                            <select class="form-control form-control-sm col-1" id="changeRate">
+                            <select class="form-control form-control-sm col-1" id="changeRate" <% if (material.material_tax) { %>disabled<% } %>>
                                 <% if (!material.readOnly) { %>
                                     <option value="9" <% if(material.rate === 9) { %>selected<% } %>>9%</option>
                                     <option value="10" <% if(material.rate === 10) { %>selected<% } %>>10%</option>
@@ -53,6 +54,7 @@
                             </select>
                         </div>
                     </div>
+                    <% if (!material.material_tax && !old_had_tax) { %>
                     <div class="sp-wrap" style="max-width: 800px;min-width: 500px;">
                         <div class="col-12 p-0">
                             <table class="table table-sm table-bordered">
@@ -67,7 +69,7 @@
                                     <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(material.ex_tp, 2) : null %></td>
                                     <td class="text-center"><%= material.ex_tp !== null || material.ex_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.ex_pre_tp, material.ex_tp), 2) : null %></td>
                                 </tr>
-                                <tr id="rate_set"><td>材料价差费用(含税)</td>
+                                <tr id="rate_set"><td>材料价差费用(含建筑税)</td>
                                     <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2) : null %></td>
                                     <td class="text-center"><%= material.m_tp !== null || pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2)), 2) : null %></td>
                                     <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2) : null %></td>
@@ -76,6 +78,37 @@
                             </table>
                         </div>
                     </div>
+                    <% } else { %>
+                    <div class="sp-wrap" style="max-width: 800px;min-width: 500px;">
+                        <div class="col-12 p-0">
+                            <table class="table table-sm table-bordered">
+                                <tr><th rowspan="2"></th><th colspan="2" class="text-center">信息价</th><th colspan="2" class="text-center">价格指数</th></tr>
+                                <tr class="text-center"><th>本期金额</th><th>截止本期金额</th>
+                                    <th>本期金额
+                                        <a href="javascript:void(0);" id="ex_expr" data-toggle="tooltip" data-placement="bottom" title="本期价差:<%- material.ex_expr ? material.ex_expr : '' %>"><i class="fa fa-question-circle-o"></i></a></th>
+                                    <th>截止本期金额</th></tr>
+                                <tr id="tp_set"><td>材料价差费用</td>
+                                    <td class="text-center"><%= material.m_tp !== null ? ctx.helper.round(material.m_tp, 2) : null %></td>
+                                    <td class="text-center"><%= material.m_tp !== null || material.pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.pre_tp, material.m_tp), 2) : null %></td>
+                                    <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(material.ex_tp, 2) : null %></td>
+                                    <td class="text-center"><%= material.ex_tp !== null || material.ex_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.ex_pre_tp, material.ex_tp), 2) : null %></td>
+                                </tr>
+                                <tr id="rate_set"><td>材料价差费用(含材料税)</td>
+                                    <td class="text-center"><%= material.material_tax ? (material.m_tax_tp !== null ? material.m_tax_tp : null) : '-' %></td>
+                                    <td class="text-center"><%= material.material_tax ? (material.m_tax_tp !== null || material.m_tax_pre_tp !== null ? ctx.helper.round(ctx.helper.add(material.m_tax_pre_tp, material.m_tax_tp), 2) : null) : material.m_tax_pre_tp %></td>
+                                    <td class="text-center">-</td>
+                                    <td class="text-center">-</td>
+                                </tr>
+                                <tr><td>材料价差费用(含建筑税)</td>
+                                    <td class="text-center"><%= !material.material_tax ? (material.m_tp !== null ? ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2) : null) : '-' %></td>
+                                    <td class="text-center"><%= !material.material_tax ? (material.m_tp !== null || pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.m_tp, 1+material.rate/100), 2)), 2) : null) : pre_tp_hs !== null ? pre_tp_hs : '-' %></td>
+                                    <td class="text-center"><%= material.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2) : null %></td>
+                                    <td class="text-center"><%= material.ex_tp !== null || ex_pre_tp_hs !== null ? ctx.helper.round(ctx.helper.add(ex_pre_tp_hs, ctx.helper.round(ctx.helper.mul(material.ex_tp, 1+material.rate/100), 2)), 2) : null %></td>
+                                </tr>
+                            </table>
+                        </div>
+                    </div>
+                    <% } %>
                 </div>
             </div>
             <div id="right-view" class="c-body" style="display:none;width: 33%">
@@ -119,12 +152,15 @@
     const materialListData = JSON.parse('<%- JSON.stringify(materialListData) %>');
     const readOnly = <%- material.readOnly %>;
     const materialID = <%- material.id %>;
+    const materialTax = <%- material.material_tax %>;
     let m_tp = <%= material.m_tp !== null ? material.m_tp : 0 %>;
     let ex_tp = <%= material.ex_tp !== null ? material.ex_tp : 0 %>;
     const pre_tp = <%= material.pre_tp !== null ? material.pre_tp : 0 %>;
     const ex_pre_tp = <%= material.ex_pre_tp !== null ? material.ex_pre_tp : 0 %>;
     const pre_tp_hs = <%= pre_tp_hs !== null ? pre_tp_hs : 0 %>;
     const ex_pre_tp_hs = <%= ex_pre_tp_hs !== null ? ex_pre_tp_hs : 0 %>;
+    let m_tax_tp = <%= material.m_tax_tp !== null ? material.m_tax_tp : 0 %>;
+    const m_tax_pre_tp = <%= material.m_tax_pre_tp !== null ? material.m_tax_pre_tp : 0 %>;
     const calcBase = JSON.parse('<%- JSON.stringify(calcBase) %>');
     const months = JSON.parse('<%- JSON.stringify(months) %>');
     let monthsList = JSON.parse('<%- JSON.stringify(monthsList) %>');

+ 1 - 1
app/view/measure/stage.ejs

@@ -50,7 +50,7 @@
                         <td class="text-center"><%- s.s_time %></td>
                         <td class="text-center">
                             <span data-toggle="tooltip" data-placement="bottom" data-original-title="<%- (s.period ? s.period : '') %>">
-                                <%- (s.period ? s.period.split('~')[1] : '') %>
+                                <%- (s.period ? (s.period.split('~')[1] ? s.period.split('~')[1] : s.period)  : '') %>
                             </span>
                         </td>
                         <% if (ctx.tender.info.display.thousandth) { %>

+ 3 - 0
app/view/report/index.ejs

@@ -578,6 +578,9 @@
                 zTreeOprObj.onClick(null, null, zTreeOprObj.currentNode);
                 zTreeOprObj.countChkedRptTpl();
                 //console.log(ARCHIVE_LIST);
+                if (zTreeOprObj.currentNode) {
+                    zTreeOprObj.treeObj.selectNode(zTreeOprObj.currentNode, false);
+                }
             }, function(err){
                 $.bootstrapLoading.end();
             }, function(ex){

+ 7 - 22
app/view/revise/info.ejs

@@ -139,30 +139,8 @@
                     <div id="search" class="tab-pane">
                     </div>
                     <div id="std-xmj" class="tab-pane">
-                        <div class="sjs-bar">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const c of stdChapters) { %>
-                                    <option value="<%- c.id %>" <% if (stdChapters.indexOf(c) === 0) { %>selected<% } %>><%- c.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-xmj-spread" class="sjs-sh">
-                        </div>
                     </div>
                     <div id="std-gcl" class="tab-pane">
-                        <div class="sjs-bar">
-                            <div class="pb-1">
-                                <select class="form-control form-control-sm">
-                                    <% for (const b of stdBills) { %>
-                                    <option value="<%- b.id %>" <% if (stdBills.indexOf(b) === 0) { %>selected<% } %>><%- b.name %></option>
-                                    <% } %>
-                                </select>
-                            </div>
-                        </div>
-                        <div id="std-gcl-spread" class="sjs-sh">
-                        </div>
                     </div>
                     <div id="deal-bills" class="tab-pane">
                         <div class="sjs-bar">
@@ -179,6 +157,8 @@
                         <div id="bg-bills-spread" class="sjs-sh">
                         </div>
                     </div>
+                    <div id="bills-tag" class="tab-pane tab-select-show">
+                    </div>
                     <div id="error-list" class="tab-pane">
                     </div>
                     <div id="check-list" class="tab-pane">
@@ -211,6 +191,9 @@
                     <a class="nav-link" content="#bg-bills" href="javascript: void(0);">变更清单</a>
                 </li>
                 <li class="nav-item">
+                    <a class="nav-link" content="#bills-tag" href="javascript: void(0);">书签</a>
+                </li>
+                <li class="nav-item">
                     <a class="nav-link" content="#error-list" id="error-list-tab" href="javascript: void(0);" style="display: none;">错误列表</a>
                 </li>
                 <li class="nav-item">
@@ -225,6 +208,8 @@
 </div>
 <script src="/public/js/moment/moment.min.js"></script>
 <script>
+    const stdChapters = JSON.parse(unescape('<%- escape(JSON.stringify(stdChapters)) %>'));
+    const stdBills = JSON.parse(unescape('<%- escape(JSON.stringify(stdBills)) %>'));
     const readOnly = <%- readOnly %>;
     const isTz = <%- ctx.tender.data.measure_type === measureType.tz.value %>;
     const billsSpreadSetting = JSON.parse('<%- JSON.stringify(ledgerSpread) %>');

+ 8 - 1
app/view/revise/info_modal.ejs

@@ -6,12 +6,18 @@
                 <h5 class="modal-title">批量插入清单-计量单元</h5>
             </div>
             <div class="modal-body">
-                <div class="custom-control custom-checkbox mb-2">
+                <div class="custom-control custom-checkbox mb-2 d-inline-block">
                     <label class="form-check-label">
                         <input class="form-check-input" type="checkbox" name="batch-filter">
                         过滤无计量单元的清单
                     </label>
                 </div>
+                <div class="custom-control custom-checkbox mb-2 d-inline-block">
+                    <label class="form-check-label">
+                        <input class="form-check-input" type="checkbox" name="batch-transpose">
+                        竖向粘贴
+                    </label>
+                </div>
                 <div class="row">
                     <div class="col-6">
                         <h6>清单信息</h6>
@@ -721,6 +727,7 @@
     <% include ../shares/delete_hint_modal.ejs %>
     <% include ../shares/check_data_modal.ejs %>
     <% include ../shares/check_modal2.ejs %>
+<% include ../shares/new_tag_modal.ejs %>
     <% include ../shares/tender_select_modal.ejs %>
     <% if(ctx.session.sessionUser.accountId === revise.uid && (revise.status === auditConst.status.uncheck || revise.status === auditConst.status.checkNo)) { %>
     <script>

+ 92 - 69
app/view/setting/datacollect.ejs

@@ -4,7 +4,7 @@
         <div class="title-main">
             <h2>决策大屏
                 <a href="#power" data-toggle="modal" data-target="#power" class="btn btn-primary btn-sm pull-right">权限管理</a>
-                <a href="#sort" data-toggle="modal" data-target="#sort" class="btn btn-primary btn-sm pull-right mr-1">分类管理</a>
+                <a href="javascript:void(0);" id="tenderBtn" class="btn btn-primary btn-sm pull-right mr-1">标段管理</a>
             </h2>
         </div>
     </div>
@@ -12,98 +12,121 @@
         <div class="c-body">
             <div class="sjs-height-0">
                 <nav class="nav nav-tabs m-3" id="tablist" role="tablist">
-                    <a class="nav-item nav-link<% if (ctx.session.sessionProject.dataCollect === 0 || ctx.session.sessionProject.dataCollect === 1) { %> active<% } %>" data-datacollect="1" data-toggle="tab" href="#shujudaping-one" role="tab">决策大屏一</a>
-                    <a class="nav-item nav-link<% if (ctx.session.sessionProject.dataCollect === 2) { %> active<% } %>" data-datacollect="2" data-toggle="tab" href="#shujudaping-two" role="tab">决策大屏二</a>
-                    <a class="nav-item nav-link<% if (ctx.session.sessionProject.dataCollect === 3) { %> active<% } %>" data-datacollect="3" data-toggle="tab" href="#shujudaping-three" role="tab">决策大屏三</a>
-                    <a class="nav-item nav-link<% if (ctx.session.sessionProject.dataCollect === 4) { %> active<% } %>" data-datacollect="4" data-toggle="tab" href="#shujudaping-four" role="tab">决策大屏四</a>
+                    <% for (let i = 1; i <= 2; i++) { %>
+                        <a class="nav-item nav-link<% if ((ctx.session.sessionProject.dataCollect === 0 && i === 1) || ctx.session.sessionProject.dataCollect === i) { %> active<% } %>" data-datacollect="<%- i %>" data-toggle="tab" href="#shujudaping-<%- i %>" role="tab">
+                            决策大屏<%- ctx.helper.transFormToChinese(i) %><% if (ctx.helper._.indexOf(projectData.data_collect_pages, i.toString()) !== -1) { %>(已开启<% if (i === ctx.session.sessionProject.dataCollect) { %>、默认<% } %>)<% } %></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<% } %>>
-                            <label class="form-check-label" for="show-datacollect">数据大屏显示</label>
+                        <!--<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<% } %>>-->
+                            <!--<label class="form-check-label" for="show-datacollect">数据大屏显示</label>-->
+                        <!--</div>-->
+                        <div class="d-inline-block form-group form-check mt-2">
+                            <div class="custom-control custom-switch">
+                                <input type="checkbox" class="custom-control-input" id="show_datacollect" <% if (ctx.session.sessionProject.dataCollect !== 0) { %>checked<% } %>>
+                                <label class="custom-control-label" for="show_datacollect">开启<i class="fa fa-question-circle text-primary" data-placement="bottom" data-toggle="tooltip" data-original-title="开启后,在决策大屏模块显示"></i></label>
+                            </div>
+                        </div>
+                        <div class="d-inline-block form-group form-check mt-2">
+                            <div class="custom-control custom-switch">
+                                <input type="checkbox" class="custom-control-input" id="default_datacollect" <% if (ctx.session.sessionProject.dataCollect !== 0) { %>checked<% } %>>
+                                <label class="custom-control-label" for="default_datacollect">默认<i class="fa fa-question-circle text-primary" data-placement="bottom" data-toggle="tooltip" data-original-title="决策大屏第一个显示"></i></label>
+                            </div>
                         </div>
                     </div>
                 </nav>
                 <div class="tab-content m-3">
-                    <div id="shujudaping-one" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === 0 || ctx.session.sessionProject.dataCollect === 1) { %> active<% } %>"><img src="/public/images/juecedaping01.png" width="100%"></div>
-                    <div id="shujudaping-two" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === 2) { %> active<% } %>"><img src="/public/images/juecedaping02.png" width="100%"></div>
-                    <div id="shujudaping-three" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === 3) { %> active<% } %>"><img src="/public/images/juecedaping03.png" width="100%"></div>
-                    <div id="shujudaping-four" class="tab-pane<% if (ctx.session.sessionProject.dataCollect === 4) { %> active<% } %>"><img src="/public/images/juecedaping04.png" width="100%"></div>
+                    <% for (let i = 1; i <= 2; i++) { %>
+                        <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>
+                    <% } %>
                 </div>
             </div>
         </div>
     </div>
 </div>
-<script src="/public/js/ztree/jquery.ztree.core.js"></script>
-<script src="/public/js/ztree/jquery.ztree.excheck.js"></script>
+<script src="/public/js/setting_datacollect_tender.js"></script>
 <script>
+    let dataCollectPages = JSON.parse(unescape('<%- escape(JSON.stringify(projectData.data_collect_pages)) %>'));
+    let dataCollect = parseInt('<%- ctx.session.sessionProject.dataCollect %>');
+    const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenders)) %>'));
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
-    console.log(category);
+    let dcTenders = JSON.parse(unescape('<%- escape(JSON.stringify(dcTenders)) %>'));
+    let addDataCollect = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.session.sessionProject.page_show.addDataCollect)) %>'));
     $(function () {
         autoFlashHeight();
-        $('#show-datacollect').click(function () {
-            let data_collect = 0;
+        // 开启及关闭展示
+        $('#show_datacollect').change(function () {
+            const activePage = $('#tablist').find('.active').data('datacollect').toString();
             if ($(this).is(':checked')) {
-                data_collect = $('#tablist').find('.active').data('datacollect');
+                dataCollectPages.push(activePage);
+                dataCollectPages.sort();
+                if (dataCollect === 0) {
+                    dataCollect = parseInt(activePage);
+                    $('#default_datacollect').prop('checked', true);
+                }
+            } else {
+                dataCollectPages.map((val, i) => {
+                    if (val === activePage) {
+                        dataCollectPages.splice(i, 1);
+                    }
+                });
+                if (dataCollectPages.length === 0) {
+                    dataCollect = 0;
+                } else if (dataCollectPages.length !== 0 && dataCollect === parseInt(activePage)){
+                    dataCollect = parseInt(dataCollectPages[0]);
+                }
+                $('#default_datacollect').prop('checked', false);
             }
-            postData('/setting/datacollect/save', { type: 'show', data_collect }, function (result) {
-
+            postData('/setting/datacollect/save', { type: 'show', data_collect_pages: dataCollectPages, data_collect: dataCollect }, function (result) {
+                updateTab();
             })
         });
-        $('#tablist a').click(function () {
-            if ($('#show-datacollect').is(':checked')) {
-                const data_collect = $(this).data('datacollect');
-                postData('/setting/datacollect/save', { type: 'show', data_collect }, function (result) {
 
-                })
-            }
-        });
-
-        const setting = {
-            check: {
-                enable: true
-            },
-            data: {
-                simpleData: {
-                    enable: true
-                }
-            }
-        };
-        const zNodes = [];
-        const newCategory = _.filter(_.orderBy(category, ['level'], ['asc']), function (item) {
-            return item.level !== 0;
-        });
-        let insertid = 1;
-        const level1Array = [];
-        const level2Array = [];
-        for (const c of newCategory) {
-            if (c.level === 1) {
-                for (const v of c.value) {
-                    level1Array.push({id: insertid});
-                    zNodes.push({id: insertid, pId: 0, name: v.value, open: true, checked:true});
-                    insertid++;
+        $('#default_datacollect').change(function () {
+            const activePage = $('#tablist').find('.active').data('datacollect').toString();
+            if ($(this).is(':checked')) {
+                dataCollect = parseInt(activePage);
+                $('#show_datacollect').prop('checked', true);
+                if (_.indexOf(dataCollectPages, activePage) === -1) {
+                    dataCollectPages.push(activePage);
+                    dataCollectPages.sort();
                 }
-            } else if (c.level === 2) {
-                for (const l1 of level1Array) {
-                    zNodes.push({id: insertid, pId: l1.id, name: '', checked:true});
-                    insertid++;
-                    for (const v of c.value) {
-                        level2Array.push({id: insertid});
-                        zNodes.push({id: insertid, pId: l1.id, name: v.value, open: true, checked:true});
-                        insertid++;
-                    }
+            } else {
+                if (dataCollectPages.length === 1) {
+                    dataCollect = 0;
+                    dataCollectPages = [];
+                    $('#show_datacollect').prop('checked', false);
+                } else {
+                    dataCollect = parseInt(dataCollectPages[0]) === dataCollect ? parseInt(dataCollectPages[1]) : parseInt(dataCollectPages[0]);
                 }
             }
-            else if (c.level === 3) {
-                for (const l2 of level2Array) {
-                    zNodes.push({id: insertid, pId: l2.id, name: '', checked:true});
-                    insertid++;
-                    for (const v of c.value) {
-                        zNodes.push({id: insertid, pId: l2.id, name: v.value, checked:true});
-                        insertid++;
-                    }
+            updateTab();
+            postData('/setting/datacollect/save', { type: 'show', data_collect_pages: dataCollectPages, data_collect: dataCollect }, function (result) {
+                updateTab();
+            })
+        })
+
+        function updateTab() {
+            for (let i = 1; i <= 2; i++) {
+                let msg = '';
+                if (_.indexOf(dataCollectPages, i.toString()) !== -1) {
+                    msg = '(已开启' + (i=== dataCollect ? '、默认' : '') + ')' ;
                 }
+                $('#tablist a').eq(i-1).text('决策大屏' + transFormToChinese(i) + msg);
             }
         }
-        $.fn.zTree.init($("#treeDemo"), setting, zNodes);
+        $('#tablist a').click(function () {
+            const page = parseInt($(this).data('datacollect'));
+            if (_.indexOf(dataCollectPages, page.toString()) !== -1) {
+                $('#show_datacollect').prop('checked', true);
+            } else {
+                $('#show_datacollect').prop('checked', false);
+            }
+            if (page === dataCollect) {
+                $('#default_datacollect').prop('checked', true);
+            } else {
+                $('#default_datacollect').prop('checked', false);
+            }
+        });
     })
 </script>

+ 32 - 6
app/view/setting/datacollect_modal.ejs

@@ -3,16 +3,41 @@
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">
-                <h5 class="modal-title">决策大屏分类管理</h5>
+                <h5 class="modal-title">决策大屏标段管理</h5>
             </div>
             <div class="modal-body">
+                <div class="mb-2">
+                    <span>新增的标段是否默认展示到决策大屏:</span>
+                    <a class="btn btn-sm btn-light">
+                        <div class="custom-control custom-checkbox">
+                            <input type="radio" name="add_datacollect" class="custom-control-input" value="1" <% if (ctx.session.sessionProject.page_show.addDataCollect === 1) { %>checked<% } %> id="yes_datacollect">
+                            <label class="custom-control-label text-primary" for="yes_datacollect">是</label>
+                        </div>
+                    </a>
+                    <a class="btn btn-sm btn-light">
+                        <div class="custom-control custom-checkbox">
+                            <input type="radio" name="add_datacollect" class="custom-control-input" value="0" <% if (ctx.session.sessionProject.page_show.addDataCollect === 0) { %>checked<% } %> id="no_datacollect">
+                            <label class="custom-control-label text-primary" for="no_datacollect">否</label>
+                        </div>
+                    </a>
+                </div>
+                <div class="alert alert-warning mb-1">已勾选的标段将展示到决策大屏中</div>
                 <div class="zTreeDemoBackground left modal-height-500" style="overflow: auto">
-                    <ul id="treeDemo" class="ztree"></ul>
+                    <table class="table table-hover table-bordered">
+                        <thead>
+                        <tr>
+                            <th>名称</th>
+                            <th width="40"><input style="vertical-align: middle" type="checkbox" id="select-tender-all"></th>
+                        </tr>
+                        </thead>
+                        <tbody id="copyModalContent">
+                        </tbody>
+                    </table>
                 </div>
             </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">确定</button>
+                <button type="button" class="btn btn-sm btn-primary" id="tender_dataCollect_btn">确定</button>
             </div>
         </div>
     </div>
@@ -57,7 +82,7 @@
                                     <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
                                            data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
                                     <div class="dd-content" data-toggleid="<%- idx %>">
-                                        <dd class="border-bottom p-2 mb-0" data-groupid="<%- idx %>><p class="mb-0 d-flex"><span class="text-primary">该单位下所有组员</span></p></dd>
+                                        <dd class="border-bottom p-2 mb-0" data-groupid="<%- idx %>"><p class="mb-0 d-flex"><span class="text-primary">该单位下所有组员</span></p></dd>
                                         <% group.groupList.forEach(item => { %>
                                             <% if (item.id !== ctx.session.sessionUser.accountId) { %>
                                                 <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
@@ -72,7 +97,7 @@
                             </dl>
                         </div>
                         <div class="card mt-1">
-                            <ul class="list-unstyled book-list modal-height-500" id="audit-list" style="overflow: auto">
+                            <ul class="list-unstyled modal-height-500" id="audit-list" style="overflow: auto">
                                 <% for (const audit of dataCollectAudits) { %>
                                 <li class="border-bottom p-2 mb-0"><a href="javascript:void(0)" class="text-danger pull-right" data-id="<%- audit.id %>" data-type="<% if (audit.uid) { %>audit<% } else { %>group<% } %>"><i class="fa fa-remove text-danger remove-audit"></i></a><%- audit.name %><small class="text-muted ml-1">账号<% if (!audit.uid) { %>组<% } %></small></li>
                                 <% } %>
@@ -118,7 +143,8 @@
                             if (!group) return
                             html += `<dt><a href="javascript: void(0);" class="acc-btn" data-groupid="${idx}" data-type="hide"><i class="fa fa-plus-square"></i>
                         </a> ${group.groupName}</dt>
-                        <div class="dd-content" data-toggleid="${idx}">`
+                        <div class="dd-content" data-toggleid="${idx}">
+                        <dd class="border-bottom p-2 mb-0" data-groupid="${idx}"><p class="mb-0 d-flex"><span class="text-primary">该单位下所有组员</span></p></dd>`
                             group.groupList.forEach(item => {
                                 if (item.id !== cur_uid) {
                                     html += `<dd class="border-bottom p-2 mb-0 " data-id="${item.id}" >

+ 30 - 0
app/view/setting/fun.ejs

@@ -45,6 +45,34 @@
                                 </div>
                             </div>
                         </div>
+                        <div class="row">
+                            <div class="col-6">
+                                <div class="card mb-3">
+                                    <div class="card-body">
+                                        <h5 class="card-title">工程变更</h5>
+                                        <div class="form-group">
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="openChangeRevise" <% if(ctx.session.sessionProject.page_show.openChangeRevise) { %>checked<% } %> onchange="updateSetting();">
+                                                <label class="form-check-label" for="openChangeRevise">新增部位</label>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="col-6">
+                                <div class="card mb-3">
+                                    <div class="card-body">
+                                        <h5 class="card-title">材料调差</h5>
+                                        <div class="form-group mb-1">
+                                            <div class="form-check form-check-inline">
+                                                <input class="form-check-input" type="checkbox" id="openMaterialTax" <% if(ctx.session.sessionProject.page_show.openMaterialTax) { %>checked<% } %> onchange="updateSetting();">
+                                                <label class="form-check-label" for="openMaterialTax">使用材料税</label>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
                         <div class="card mb-3">
                             <div class="card-body">
                                 <h5 class="card-title">概算控制</h5>
@@ -78,6 +106,8 @@
             banOver: $('[name=ban_over]')[0].checked,
             hintOver: $('#hint_over')[0].checked,
             needGcl: $('#need_gcl')[0].checked,
+            openChangeRevise: $('#openChangeRevise')[0].checked,
+            openMaterialTax: $('#openMaterialTax')[0].checked,
         });
     }
 </script>

+ 74 - 28
app/view/tender/detail.ejs

@@ -57,7 +57,7 @@
         </div>
     </div>
     <div class="content-wrap" id="big-data">
-        <div style="height: 70px;background-color: #2c3237; display: none" id="exitfull-div">
+        <div style="height: 70px;display: none;<% if (ctx.tender.info.display.dayMode) { %> background-color: #fff;<% } else { %> background-color: #2c3237 !important;<% } %>" id="exitfull-div">
             <div class="title-main d-flex">
                 <div class="ml-auto">
                     <div class="dropdown d-flex float-left mt-1 mr-2">
@@ -66,7 +66,7 @@
                 </div>
             </div>
         </div>
-        <div class="c-body" style="background:#2c3237 !important">
+        <div class="c-body <% if (ctx.tender.info.display.dayMode) { %>c-body-white<% } %>" <% if (!ctx.tender.info.display.dayMode) { %>style="background-color: #2c3237 !important;"<% } %>>
             <div class="sjs-height-0">
             <!--<div class="auto-main-height">-->
                 <div class="main-height-one">
@@ -76,7 +76,7 @@
                             <div class="col-12">
                                 <div class="row">
                                     <div class="col-2 pl-0">
-                                        <div class="card text-center bg-dark text-white">
+                                        <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                             <div class="card-body">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.total_price) %></h5>
                                                 <p class="card-text text-muted">0号台账合同</p>
@@ -84,7 +84,7 @@
                                         </div>
                                     </div>
                                     <div class="col-2 pl-0">
-                                        <div class="card text-center bg-dark text-white">
+                                        <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                             <div class="card-body">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.end_qc_tp) %> <small class="text-danger"  data-toggle="tooltip" data-placement="bottom" title="" data-original-title="占合同比例"><%- tender.qc_ratio %>%</small></h5>
                                                 <p class="card-text text-muted">截止本期变更</p>
@@ -92,7 +92,7 @@
                                         </div>
                                     </div>
                                     <div class="col-2 pl-0">
-                                        <div class="card text-center bg-dark text-white">
+                                        <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                             <div class="card-body">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.gather_tp) %></h5>
                                                 <p class="card-text text-muted">本期完成</p>
@@ -100,7 +100,7 @@
                                         </div>
                                     </div>
                                     <div class="col-2 pl-0">
-                                        <div class="card text-center bg-dark text-white">
+                                        <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                             <div class="card-body">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.end_gather_tp) %></h5>
                                                 <p class="card-text text-muted">截止本期完成</p>
@@ -108,7 +108,7 @@
                                         </div>
                                     </div>
                                     <div class="col-2 pl-0">
-                                        <div class="card text-center bg-dark text-white">
+                                        <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                             <div class="card-body">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.pre_gather_tp) %></h5>
                                                 <p class="card-text text-muted">截止上期完成</p>
@@ -116,7 +116,7 @@
                                         </div>
                                     </div>
                                     <div class="col-2 pl-0">
-                                        <div class="card text-center bg-dark text-white">
+                                        <div class="card text-center <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                             <div class="card-body">
                                                 <h5 class="card-title card-big-title"><%- ctx.helper.formatMoney(tender.yf_tp) %></h5>
                                                 <p class="card-text text-muted">本期应付</p>
@@ -148,7 +148,7 @@
                         <div class="row">
                             <div class="col-3">
                                 <!--计量完成概况-->
-                                <div class="card mb-3 bg-dark text-white">
+                                <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                     <div class="card-header"><h6 class="mb-0">计量完成概况</h6></div>
                                     <div class="card-body">
                                         <div id="jlchart1" style="height: 100%; width: 100%;">
@@ -156,7 +156,7 @@
                                     </div>
                                 </div>
                                 <!--支付情况-->
-                                <div class="card mb-3 bg-dark text-white">
+                                <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                     <div class="card-header"><h6 class="mb-0">支付情况</h6></div>
                                     <div class="card-body">
                                         <div id="jlchart2" style="height: 100%; width: 100%;">
@@ -166,7 +166,7 @@
                             </div>
                             <!--章节计量情况图-->
                             <div class="col-6 pl-0">
-                                <div class="card mb-3 bg-dark text-white">
+                                <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                     <% if (hadMap) { %>
                                         <div class="card-body" id="map" style="height: 388px; width: 100%;">
                                         </div>
@@ -181,7 +181,7 @@
                             </div>
                             <div class="col-3 pl-0">
                                 <!--台账审批进度-->
-                                <div class="card mb-3 bg-dark text-white">
+                                <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                     <div class="card-header"><h6 class="mb-0"><% if (lastStage) { %>计量审批进度<% } else { %>台账审批进度<% } %></h6></div>
                                     <div class="card-body">
                                         <div style="">
@@ -261,9 +261,9 @@
                                         </div>
                                     </div>
                                 </div>
-                                <div class="card mb-3 bg-dark text-white">
+                                <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                     <div class="card-header">
-                                        <ul class="nav nav-tabs card-header-tabs panel-card-tabs">
+                                        <ul class="nav nav-tabs card-header-tabs panel-card-tabs <% if (ctx.tender.info.display.dayMode) { %>nav-white-tabs<% } %>">
                                             <li class="nav-item">
                                                 <a class="nav-link active" data-toggle="tab" href="#taizhangshenpi" role="tab" aria-selected="true">工程变更进度</a>
                                             </li>
@@ -307,7 +307,7 @@
                                                                 <% } %>
                                                             </div>
                                                         </div>
-                                                        <table class="table table-bordered table-2sm mb-0 mt-1 table-dark">
+                                                        <table class="table table-bordered table-2sm mb-0 mt-1 <% if (!ctx.tender.info.display.dayMode) { %>table-dark<% } %>">
                                                             <% if (materialData) { %>
                                                                 <tr><th width="60%">含税(信息价/指数法)</th><td width="20%"><%= materialData.m_tp !== null ? ctx.helper.round(ctx.helper.mul(materialData.m_tp, 1+materialData.rate/100), 2) : '0' %></td><td width="20%"><%= materialData.ex_tp !== null ? ctx.helper.round(ctx.helper.mul(materialData.ex_tp, 1+materialData.rate/100), 2) : '0' %></td></tr>
                                                                 <tr><th>不含税(信息价/指数法)</th><td><%= materialData.m_tp !== null ? ctx.helper.round(materialData.m_tp, 2) : '0' %></td><td><%= materialData.ex_tp !== null ? ctx.helper.round(materialData.ex_tp, 2) : '0' %></td></tr>
@@ -325,7 +325,7 @@
                             </div>
                             <!--期进度表-->
                             <div class="col-6">
-                                <div class="card mb-3 bg-dark text-white bottom-height">
+                                <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %> bottom-height">
                                     <% if (hadMap) { %>
                                         <div class="card-header"><h6 class="mb-0">章节计量情况表</h6></div>
                                         <div class="card-body">
@@ -341,10 +341,10 @@
                             </div>
                             <!--月进度表-->
                             <div class="col-6 pl-0">
-                                <div class="card mb-3 bg-dark text-white bottom-height">
+                                <div class="card mb-3 bottom-height <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                                     <% if (hadMap) { %>
                                         <div class="card-header">
-                                            <ul class="nav nav-tabs card-header-tabs panel-card-tabs" id="change-echarts">
+                                            <ul class="nav nav-tabs card-header-tabs panel-card-tabs <% if (ctx.tender.info.display.dayMode) { %>nav-white-tabs<% } %>" id="change-echarts">
                                                 <li class="nav-item">
                                                     <a class="nav-link active" data-toggle="tab" href="#qijindubiao" role="tab" aria-selected="true">期进度表</a>
                                                 </li>
@@ -384,11 +384,19 @@
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
     const tender = JSON.parse('<%- JSON.stringify(tender) %>');
     const cur_uid = parseInt('<%- ctx.session.sessionUser.accountId %>');
+    const dayMode = <%- ctx.tender.info.display.dayMode %>;
     //计量完成概况//
-    var myChart = echarts.init(document.getElementById('jlchart1'), 'dark');
+    var myChart = echarts.init(document.getElementById('jlchart1')<% if (!ctx.tender.info.display.dayMode) { %>, 'dark'<% } %>);
     var option = {
+        <% if (ctx.tender.info.display.dayMode) { %>
+        color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
+            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
+            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
+            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
+        <% } else { %>
         color: ['rgba(24,144,255,0.7)','rgba(69,183,149,0.7)','rgba(250,204,20,0.7)','rgba(145,82,225,0.7)','rgba(58,207,221,0.7)','rgba(204,73,80,0.7)','rgba(255,255,225,0.7)'],
         backgroundColor: '#343a40 ',
+        <% } %>
         tooltip: {
             trigger: 'item'
         },
@@ -432,9 +440,9 @@
     myChart.setOption(option);
     //计量完成概况 结束//
     //计量支付概况//
-    var myChart1 = echarts.init(document.getElementById('jlchart2'), 'dark');
+    var myChart1 = echarts.init(document.getElementById('jlchart2')<% if (!ctx.tender.info.display.dayMode) { %>, 'dark'<% } %>);
     var option1 = {
-        backgroundColor: '#343a40 ',
+        <% if (!ctx.tender.info.display.dayMode) { %>backgroundColor: '#343a40 ',<% } %>
         tooltip: {
             trigger: 'axis',
             axisPointer: {
@@ -485,7 +493,14 @@
             itemStyle:{
                 normal:{
                     color:function(params){
+                        <% if (ctx.tender.info.display.dayMode) { %>
+                        var colorlist = ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
+                            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
+                            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
+                            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'];
+                        <% } else { %>
                         var colorlist = ['rgba(24,144,255,0.7)','rgba(69,183,149,0.7)','rgba(250,204,20,0.7)','rgba(145,82,225,0.7)','rgba(58,207,221,0.7)','rgba(204,73,80,0.7)','rgba(255,255,225,0.7)'];
+                        <% } %>
                         return colorlist[params.dataIndex];
                     }
                 }
@@ -497,10 +512,17 @@
     myChart1.setOption(option1);
     //计量支付概况 结束//
     //章节计量情况图//
-    var myChart2 = echarts.init(document.getElementById('jlchart3'), 'dark');
+    var myChart2 = echarts.init(document.getElementById('jlchart3')<% if (!ctx.tender.info.display.dayMode) { %>, 'dark'<% } %>);
     var option2 = {
+        <% if (ctx.tender.info.display.dayMode) { %>
+        color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
+            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
+            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
+            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
+        <% } else { %>
         color: ['rgba(24,144,255,0.7)','rgba(69,183,149,0.7)','rgba(250,204,20,0.7)','rgba(145,82,225,0.7)','rgba(58,207,221,0.7)','rgba(204,73,80,0.7)','rgba(255,255,225,0.7)'],
         backgroundColor: '#343a40 ',
+        <% } %>
         tooltip: {
             trigger: 'axis',
             axisPointer: {
@@ -586,10 +608,17 @@
     myChart2.setOption(option2);
 
     //4 标段期数计量进度//
-    var myChart3 = echarts.init(document.getElementById('chartContainer4'), 'dark');
+    var myChart3 = echarts.init(document.getElementById('chartContainer4')<% if (!ctx.tender.info.display.dayMode) { %>, 'dark'<% } %>);
     var option3 = {
+        <% if (ctx.tender.info.display.dayMode) { %>
+        color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
+            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
+            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
+            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
+        <% } else { %>
         color: ['rgba(24,144,255,0.7)','rgba(69,183,149,0.7)','rgba(250,204,20,0.7)','rgba(145,82,225,0.7)','rgba(204,73,80,0.7)','rgba(58,207,221,0.7)','rgba(255,255,225,0.7)'],
         backgroundColor: '#343a40 ',
+        <% } %>
         title : {
             text: ''
         },
@@ -753,10 +782,17 @@
     //4 标段期数计量进度//
     //3 标段月进度//
     // 基于准备好的dom,初始化echarts图表
-    var myChart4 = echarts.init(document.getElementById('chartContainer3'), 'dark');
+    var myChart4 = echarts.init(document.getElementById('chartContainer3')<% if (!ctx.tender.info.display.dayMode) { %>, 'dark'<% } %>);
     var option4 = {
+        <% if (ctx.tender.info.display.dayMode) { %>
+        color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
+            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
+            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
+            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
+        <% } else { %>
         color:["#17a2b8","#28a745"],
         backgroundColor: '#343a40 ',
+        <% } %>
         title : {
             text: ''
         },
@@ -911,10 +947,17 @@
     //3 标段月进度//
 
     //变更审批进度//
-    var myChart5 = echarts.init(document.getElementById('bgchart'), 'dark');
+    var myChart5 = echarts.init(document.getElementById('bgchart')<% if (!ctx.tender.info.display.dayMode) { %>, 'dark'<% } %>);
     var option5 = {
+        <% if (ctx.tender.info.display.dayMode) { %>
+        color: ['#e9af68','#57b7b6','#e4575a','#959eac','#6699FF',
+            '#d38b70','#8fb7cf','#cd5c5c','#ffa500','#40e0d0',
+            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
+            '#5c616b','#ff6666','#3cb371','#b8860b','#30e0e0'],
+        <% } else {%>
         color: ['rgba(145,82,225,0.7)','rgba(58,207,221,0.7)','rgba(204,73,80,0.7)','rgba(24,144,255,0.7)','rgba(69,183,149,0.7)','rgba(250,204,20,0.7)','rgba(255,255,225,0.7)'],
         backgroundColor: '#343a40 ',
+        <% } %>
         tooltip: {
             trigger: 'item'
         },
@@ -1103,6 +1146,7 @@
                 const { auditHistory, auditors, user } = result
                 let historyHTML = ''
                 const leftAuditors = auditors;
+                const darkHTML = !dayMode ? 'bg-dark border-secondary text-white' : '';
                 auditHistory.forEach((auditors, idx) => {
                     if(idx === auditHistory.length - 1 && auditHistory.length !== 1) {
                         historyHTML += `<div class="text-right"><a href="javascript: void(0);" id="fold-btn" data-target="show"
@@ -1122,7 +1166,7 @@
                                 <i class="fa fa-caret-down"></i>
                             </div>
                             <div class="timeline-item-content">
-                                <div class="card bg-dark border-secondary text-white">
+                                <div class="card ${darkHTML}">
                                     <div class="card-body p-3">
                                         <div class="card-text">
                                             <p class="mb-1"><span
@@ -1161,7 +1205,7 @@
 
                             }
                             historyHTML += `<div class="timeline-item-content">
-                                <div class="card bg-dark border-secondary text-white">
+                                <div class="card ${darkHTML}">
                                     <div class="card-body p-3">
                                         <div class="card-text">
                                             <p class="mb-1"><span class="h5">${auditor.name}</span><span
@@ -1202,7 +1246,7 @@
                                 historyHTML += `<div class="timeline-item-icon bg-secondary text-light"></div>`
                             }
                             historyHTML += `<div class="timeline-item-content">
-                        <div class="card bg-dark border-secondary text-white">
+                        <div class="card ${darkHTML}">
                             <div class="card-body p-3">
                                 <div class="card-text">
                                     <p class="mb-1"><span class="h5">${auditor.name}</span>
@@ -1371,7 +1415,9 @@
             // const LocationControl = new BMapGL.LocationControl();  // 添加比例尺控件
             // map.addControl(LocationControl);
             map.enableScrollWheelZoom(true);
+            <% if (!ctx.tender.info.display.dayMode) { %>
             map.setMapStyleV2({styleId: '20d4aea41cf71387395f2dc835f1c4b6'});
+            <% } %>
             if (polyLineList.length > 0) {
                 for (const pl of polyLineList) {
                     const polyline = new BMapGL.Polyline(pl.map, {strokeColor: pl.color, strokeWeight:10, strokeOpacity:1});

+ 15 - 5
app/view/tender/detail_modal.ejs

@@ -710,6 +710,10 @@
                         <input type="checkbox" class="custom-control-input" checked="" id="stage-correct">
                         <label class="custom-control-label" for="stage-correct">使用数量纠正完成率</label>
                     </div>
+                    <div class="custom-control custom-checkbox mb-2">
+                        <input type="checkbox" class="custom-control-input" checked="" id="dayMode">
+                        <label class="custom-control-label" for="dayMode">标段概况-浅色模式</label>
+                    </div>
                 </div>
             </div>
             <div class="modal-footer">
@@ -813,14 +817,14 @@
 <div class="modal fade" id="sp-list" data-backdrop="static">
     <div class="modal-dialog" role="document">
         <div class="modal-content">
-            <div class="modal-header bg-dark text-white border-secondary">
+            <div class="modal-header <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white border-secondary<% } %>">
                 <h5 class="modal-title">审批进度详情</h5>
             </div>
-            <div class="modal-body bg-dark text-white">
+            <div class="modal-body <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
                 <div class="modal-height-500" style="overflow: auto" id="audit-list">
                 </div>
             </div>
-            <div class="modal-footer bg-dark text-white border-secondary">
+            <div class="modal-footer <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white border-secondary<% } %>">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
             </div>
         </div>
@@ -1481,6 +1485,7 @@
         $('#thousandth')[0].checked = property.display.thousandth;
         $('#stage-rc')[0].checked = property.display.stage.realComplete;
         $('#stage-correct')[0].checked = property.display.stage.correct;
+        $('#dayMode')[0].checked = property.display.dayMode;
     }
     $('#bd-set-5').on('show.bs.modal', function () {
         loadDisplayProperty();
@@ -1491,12 +1496,17 @@
                 ledger: { dgnQty: $('#ledger-dgn-qty')[0].checked, clQty: $('#ledger-cl-qty')[0].checked, },
                 thousandth: $('#thousandth')[0].checked,
                 stage: { realComplete: $('#stage-rc')[0].checked, correct: $('#stage-correct')[0].checked },
+                dayMode: $('#dayMode')[0].checked,
             },
         };
         const tenderId = window.location.pathname.split('/')[2];
         postData('/tender/' + tenderId + '/save', prop, function (data) {
-            property.display = data.display;
-            $('#bd-set-5').modal('hide');
+            if (data.display.dayMode !== property.display.dayMode) {
+                window.location.reload();
+            } else {
+                property.display = data.display;
+                $('#bd-set-5').modal('hide');
+            }
         });
     }
 

+ 1 - 0
app/view/tender/info.ejs

@@ -9,6 +9,7 @@
 </div>
 <script>
     const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
+    console.log(tenders);
     const categoryType = JSON.parse('<%- JSON.stringify(settingConst.cType) %>');
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');

+ 3 - 0
app/view/wap/dashboard.ejs

@@ -53,7 +53,10 @@
                                 <tr><th>本期完成计量</th><td class="text-right"><%- audit.gather_tp ? audit.gather_tp : 0 %></td></tr>
                                 <tr><th>截止上期完成计量</th><td class="text-right"><%- audit.pre_gather_tp ? audit.pre_gather_tp : 0 %></td></tr>
                                 <tr><th>截止本期完成计量</th><td class="text-right"><%- audit.end_gather_tp ? audit.end_gather_tp : 0 %></td></tr>
+                                <% if (ctx.session.sessionProject.page_show.closeWapYfSf) { %>
                                 <tr><th>本期应付</th><td class="text-right"><%- audit.yf_tp ? audit.yf_tp : 0 %></td></tr>
+                                <tr><th>本期实付</th><td class="text-right"><%- audit.sf_tp ? audit.sf_tp : 0 %></td></tr>
+                                <% } %>
                             </table>
                         </div>
                         <div class="">

+ 12 - 0
app/view/wap/shenpi_stage.ejs

@@ -79,11 +79,23 @@
                                 <p class="mb-0">截止本期完成计量</p>
                                 <b>¥<%- stage.end_tp ? stage.end_tp : 0 %></b>
                             </td>
+                            <% if (ctx.session.sessionProject.page_show.closeWapYfSf) { %>
                             <td>
                                 <p class="mb-0">本期应付</p>
                                 <b>¥<%- stage.yf_tp ? stage.yf_tp : 0 %></b>
                             </td>
+                            <% } %>
+                        </tr>
+                        <% if (ctx.session.sessionProject.page_show.closeWapYfSf) { %>
+                        <tr>
+                            <td>
+                                <p class="mb-0">本期实付</p>
+                                <b>¥<%- stage.sf_tp ? stage.sf_tp : 0 %></b>
+                            </td>
+                            <td>
+                            </td>
                         </tr>
+                        <% } %>
                         </tbody></table>
                 </dd>
             </dl>

+ 12 - 0
app/view/wap/tender.ejs

@@ -173,11 +173,23 @@
                                     <p class="mb-0">截止本期完成计量</p>
                                     <b>¥<%- s.end_tp ? s.end_tp : 0 %></b>
                                 </td>
+                                <% if (ctx.session.sessionProject.page_show.closeWapYfSf) { %>
                                 <td>
                                     <p class="mb-0">本期应付</p>
                                     <b>¥<%- s.yf_tp ? s.yf_tp : 0 %></b>
                                 </td>
+                                <% } %>
                             </tr>
+                            <% if (ctx.session.sessionProject.page_show.closeWapYfSf) { %>
+                            <tr>
+                                <td>
+                                    <p class="mb-0">本期实付</p>
+                                    <b>¥<%- s.sf_tp ? s.sf_tp : 0 %></b>
+                                </td>
+                                <td>
+                                </td>
+                            </tr>
+                            <% } %>
                             <% if (s.curAuditor && s.status == auditConst.status.checking && s.curAuditor.aid === ctx.session.sessionUser.accountId) { %>
                             <tr>
                                 <td colspan="2">

+ 76 - 2
builder_report_index_define.js

@@ -305,6 +305,23 @@ const change_bills = {
         { name: '(空) 变更清单-本期使用', field: 'is_used', type: dataType.int },
     ],
 };
+const change_audit = {
+    name: '变更审批 列表(mem_change_audit)',
+    remark: '',
+    id: 73,
+    key: 'mem_change_audit',
+    prefix: '变更审批',
+    cols: [
+        { name: '变更令id', field: 'cid', type: dataType.str },
+        { name: '审批人id', field: 'uid', type: dataType.int },
+        { name: '姓名', field: 'name', type: dataType.str },
+        { name: '职称', field: 'jobs', type: dataType.str },
+        { name: '公司', field: 'company', type: dataType.str },
+        { name: '审批意见', field: 'sdesc', type: dataType.str },
+        { name: '审批时间', field: 'sin_time', type: dataType.str },
+        { name: '审批顺序', field: 'usort', type: dataType.str },
+    ],
+};
 // 期 - 清单
 const stage_bills = {
     name: '期-清单 数据表(mem_stage_bills)',
@@ -1250,6 +1267,48 @@ const gather_deal_bills = {
 };
 
 // 材差
+const select_material = {
+    name: '材料调差-选择期-数据(mem_select_material)',
+    remark: '',
+    id: 71,
+    key: 'mem_select_material',
+    prefix: '材料调差-选择期',
+    cols: [
+        { name: 'id', field: 'id', type: dataType.int },
+        { name: '标段id', field: 'tid', type: dataType.int },
+        { name: '创建者id', field: 'user_id', type: dataType.int },
+        { name: '审批次数', field: 'times', type: dataType.int },
+        { name: '审批状态', field: 'status', type: dataType.int },
+        { name: '期id列表', field: 'stage_id', type: dataType.str },
+        { name: '期order列表', field: 's_order', type: dataType.str },
+        { name: '材料调差期数', field: 'order', type: dataType.int },
+        { name: '本期金额', field: 'm_tp', type: dataType.currency },
+        { name: '截止上期金额', field: 'pre_tp', type: dataType.currency },
+        { name: '税率', field: 'rate', type: dataType.int },
+        { name: '创建时间', field: 'in_time', type: dataType.str },
+
+    ],
+};
+
+const select_material_audit = {
+    name: '材料调差-选择期-审批人 列表(mem_select_material_audit)',
+    remark: '',
+    id: 72,
+    key: 'mem_select_material_audit',
+    prefix: '材料调差-选择期',
+    cols: [
+        { name: '审批人id', field: 'aid', type: dataType.int },
+        { name: '姓名', field: 'name', type: dataType.str },
+        { name: '公司', field: 'company', type: dataType.str },
+        { name: '角色', field: 'role', type: dataType.str },
+        { name: '手机', field: 'mobile', type: dataType.str },
+        { name: '电话', field: 'telephone', type: dataType.str },
+        { name: '审批意见', field: 'opinion', type: dataType.str },
+        { name: '审批时间', field: 'end_time', type: dataType.str },
+        { name: '审批顺序', field: 'sort', type: dataType.str },
+    ],
+};
+
 const material = {
     name: '材料调差-期列表-数据(mem_material)',
     remark: '',
@@ -1269,6 +1328,16 @@ const material = {
         { name: '截止上期金额', field: 'pre_tp', type: dataType.currency },
         { name: '税率', field: 'rate', type: dataType.int },
         { name: '创建时间', field: 'in_time', type: dataType.str },
+        { name: '月信息价-年月份列表', field: 'months', type: dataType.str },
+        { name: '指数本期金额', field: 'ex_tp', type: dataType.currency },
+        { name: '指数截止上期金额', field: 'ex_pre_tp', type: dataType.currency },
+        { name: '指数调差结果公式', field: 'ex_expr', type: dataType.str },
+        { name: '调差基数值json', field: 'ex_calc', type: dataType.str },
+        { name: '是否已使用材料税,默认为0', field: 'material_tax', type: dataType.int },
+        { name: '材料含税总金额', field: 'm_tax_tp', type: dataType.currency },
+        { name: '截止上期材料含税金额', field: 'm_tax_pre_tp', type: dataType.currency },
+        { name: '小数位数设置JSON', field: 'decimal', type: dataType.currency },
+        { name: '批复时间', field: 'checked_time', type: dataType.str },
 
     ],
 };
@@ -1312,6 +1381,11 @@ const materialGl = {
 
         { name: '创建时间', field: 'in_time', type: dataType.str },
         { name: '备注', field: 'remark', type: dataType.str },
+
+        { name: '税率', field: 'm_tax', type: dataType.int },
+
+        { name: '调差金额(材料税)', field: 'm_tax_tp', type: dataType.currency },
+        { name: '截止上期调差金额(材料税)', field: 'tax_pre_tp', type: dataType.currency },
     ],
 };
 const material_bills = {
@@ -2135,13 +2209,13 @@ const defines = [
     month_progress,
     stage_bills, stage_bills_compare,
     stage_jgcl, stage_bonus, stage_other, stage_safe_prod, stage_temp_land,
-    change, change_bills,
+    change, change_bills, change_audit,
     stage_pos, stage_pos_compare,
     stage_pay,
     stage_im_zl, stage_im_tz, stage_im_tz_bills,
     stage_rela_im, stage_rela_im_bills,
     gather_stage_bills, gather_tender_info, gather_stage_pay, gather_deal_bills,
-    material, materialGl, material_bills, material_pos, material_gl_detail,
+    select_material, select_material_audit, material, materialGl, material_bills, material_pos, material_gl_detail,
     stage_sum_bills, stage_sum_pay, stage_audit, sign_select,
     stage_change, stage_change_bills, stage_change_ledger,
     gcl_gather_bills, gcl_gather_xmj,

+ 2 - 2
config/config.default.js

@@ -214,7 +214,7 @@ module.exports = appInfo => {
         default: {
             accessKeyId: 'LTAIALMjBHOs9PLA',
             accessKeySecret: 'HSnULQs87wAJhcziAdyRv3GZ4EYctc',
-            endpoint: 'oss-cn-shenzhen.aliyuncs.com',
+            endpoint: 'oss-cn-shenzhen-internal.aliyuncs.com',
             timeout: '60s',
         },
     };
@@ -222,7 +222,7 @@ module.exports = appInfo => {
     config.fujianOssPath = 'https://jiliang-saas-oss.smartcost.com.cn/';
     config.fujianOssFolder = '';
 
-    config.syncUrl = 'https://sync.jl.smartcost.com.cn/';
+    config.syncUrl = 'http://sync.jl.smartcost.com.cn/';
 
     return config;
 };

+ 0 - 0
config/config.local.js


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.