Browse Source

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

TonyKang 5 years ago
parent
commit
0a4981d7bc
77 changed files with 4494 additions and 1839 deletions
  1. 2 0
      app/const/account_group.js
  2. 3 0
      app/const/change.js
  3. 1 1
      app/const/deal_pay.js
  4. 10 10
      app/const/spread.js
  5. 1 0
      app/const/tender.js
  6. 26 8
      app/controller/material_controller.js
  7. 1 1
      app/controller/setting_controller.js
  8. 121 56
      app/controller/stage_controller.js
  9. 17 0
      app/extend/helper.js
  10. 68 0
      app/lib/material_calc.js
  11. 34 1
      app/public/css/main.css
  12. 2 2
      app/public/js/change_company.js
  13. 2 4
      app/public/js/global.js
  14. 59 10
      app/public/js/ledger.js
  15. 2 1
      app/public/js/ledger_audit.js
  16. 214 7
      app/public/js/material.js
  17. 4 1
      app/public/js/material_list.js
  18. 2 1
      app/public/js/measure_compare.js
  19. 31 24
      app/public/js/measure_material.js
  20. 30 24
      app/public/js/measure_stage.js
  21. 19 1
      app/public/js/number-precision.js
  22. 72 23
      app/public/js/revise.js
  23. 2 1
      app/public/js/revise_history.js
  24. 7 0
      app/public/js/spreadjs_rela/spreadjs_zh.js
  25. 799 34
      app/public/js/stage.js
  26. 12 7
      app/public/js/stage_audit.js
  27. 2 1
      app/public/js/stage_change.js
  28. 2 1
      app/public/js/stage_compare.js
  29. 19 36
      app/public/js/stage_detail.js
  30. 2 1
      app/public/js/stage_gather.js
  31. 406 72
      app/public/js/stage_im.js
  32. 2 1
      app/public/js/stage_pay.js
  33. 12 1
      app/public/js/sub_menu.js
  34. 1 1
      app/public/js/tender_list_progress.js
  35. 2 2
      app/router.js
  36. 12 6
      app/service/ledger_audit.js
  37. 19 3
      app/service/material.js
  38. 32 16
      app/service/material_audit.js
  39. 125 3
      app/service/material_bills.js
  40. 41 0
      app/service/material_bills_history.js
  41. 3 3
      app/service/material_list.js
  42. 75 16
      app/service/material_list_notjoin.js
  43. 1 1
      app/service/project_account.js
  44. 59 12
      app/service/stage.js
  45. 12 5
      app/service/stage_audit.js
  46. 43 1
      app/service/stage_bills.js
  47. 44 4
      app/service/stage_change.js
  48. 3 1
      app/service/stage_pos.js
  49. 3 2
      app/view/change/index.ejs
  50. 8 1
      app/view/change/info.ejs
  51. 2 2
      app/view/change/info_modal.ejs
  52. 67 57
      app/view/ledger/audit_modal.ejs
  53. 137 114
      app/view/ledger/explode_modal.ejs
  54. 206 162
      app/view/material/audit_modal.ejs
  55. 2 1
      app/view/material/index.ejs
  56. 7 2
      app/view/material/info.ejs
  57. 34 1
      app/view/material/info_modal.ejs
  58. 1 1
      app/view/material/material_sub_menu.ejs
  59. 1 1
      app/view/material/material_sub_mini_menu.ejs
  60. 2 1
      app/view/measure/stage.ejs
  61. 2 1
      app/view/report/index.ejs
  62. 2 1
      app/view/revise/index.ejs
  63. 1 1
      app/view/setting/info.ejs
  64. 4 8
      app/view/stage/audit_btn.ejs
  65. 1071 981
      app/view/stage/audit_modal.ejs
  66. 13 11
      app/view/stage/detail.ejs
  67. 17 1
      app/view/stage/detail_modal.ejs
  68. 257 2
      app/view/stage/index.ejs
  69. 155 23
      app/view/stage/modal.ejs
  70. 1 1
      app/view/stage/pay.ejs
  71. 1 1
      app/view/stage/pay_modal.ejs
  72. 34 44
      app/view/stage/stage_sub_menu.ejs
  73. 2 11
      app/view/stage/stage_sub_mini_menu.ejs
  74. 2 2
      app/view/tender/detail.ejs
  75. 1 1
      app/view/tender/tender_sub_menu.ejs
  76. 2 1
      app/view/tender/tender_sub_mini_menu.ejs
  77. 1 0
      config/web.js

+ 2 - 0
app/const/account_group.js

@@ -14,6 +14,7 @@ const accountGroup = {
     SJDW: 4,
     DJDW: 5,
     GZSJ: 6,
+    QT: 7,
 };
 
 const group = [];
@@ -23,6 +24,7 @@ group[accountGroup.JLDW] = '监理单位';
 group[accountGroup.SGDW] = '施工单位';
 group[accountGroup.SJDW] = '设计单位';
 group[accountGroup.GZSJ] = '跟踪审计';
+group[accountGroup.QT] = '其他';
 
 module.exports = {
     type: accountGroup,

+ 3 - 0
app/const/change.js

@@ -68,6 +68,9 @@ module.exports = {
         partyB: {
             value: 2, name: '承包人',
         },
+        partyC: {
+            value: 3, name: '其他',
+        },
     },
     // 变更单位
     units: {

+ 1 - 1
app/const/deal_pay.js

@@ -15,7 +15,7 @@ const payType = {
     wc: 4
 };
 const payTemplate = [
-    {order: 1, name: '本期应付', ptype: payType.yf, minus: false, expr: null, sexpr: null, rexpr: null},
+    {order: 1, name: '本期应付金额', ptype: payType.yf, minus: false, expr: null, sexpr: null, rexpr: null},
     {order: 2, name: '本期实付', ptype: payType.sf, minus: false},
     {order: 3, name: '本期完成计量', ptype: payType.wc, minus: false, expr: 'bqwc'},
     {order: 4, name: '质量保证金', ptype: payType.normal, minus: true},

+ 10 - 10
app/const/spread.js

@@ -26,13 +26,13 @@ const withCl = {
             {title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '签约|数量', colSpan: '2|1', rowSpan: '1|1', field: 'deal_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'deal_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '施工图复核|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '设计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sgfh_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '设计错漏增减|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sjcl_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sjcl_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '其他错漏增减|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qtcl_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qtcl_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '小计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '台账小计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
             {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}
@@ -47,9 +47,9 @@ const withCl = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, formatter: '@'},
-            {title: '数量|施工图复核', colSpan: '4|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 100, type: 'Number'},
-            {title: '数量|设计错漏增减', colSpan: '|1', rowSpan: '|1', field: 'sjcl_qty', hAlign: 2, width: 100, type: 'Number'},
-            {title: '数量|其他错漏增减', colSpan: '|1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 100, type: 'Number'},
+            {title: '台账数量|设计量', colSpan: '4|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 100, type: 'Number'},
+            {title: '|设计错漏增减', colSpan: '|1', rowSpan: '|1', field: 'sjcl_qty', hAlign: 2, width: 100, type: 'Number'},
+            {title: '|其他错漏增减', colSpan: '|1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 100, type: 'Number'},
             {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
         ],
@@ -74,7 +74,7 @@ const withoutCl = {
             {title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '签约|数量', colSpan: '2|1', rowSpan: '1|1', field: 'deal_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'deal_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '施工图复核|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '设计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sgfh_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
             {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}
@@ -89,7 +89,7 @@ const withoutCl = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, formatter: '@'},
-            {title: '施工图复核数量', colSpan: '1', rowSpan: '1', field: 'sgfh_qty', hAlign: 2, width: 120, type: 'Number'},
+            {title: '设计量', colSpan: '1', rowSpan: '1', field: 'sgfh_qty', hAlign: 2, width: 120, type: 'Number'},
             {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
         ],
         emptyRows: 3,
@@ -207,7 +207,7 @@ const stageCl = {
     pos: {
         cols: [
             {title: '部位名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@'},
-            {title: '复核数量|施工图复核', colSpan: '4|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '台账数量|施工图复核', colSpan: '4|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|设计错漏增减', colSpan: '1', rowSpan: '|1', field: 'sjcl_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|其他错漏增减', colSpan: '1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|小计', colSpan: '1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, readOnly: true},
@@ -239,7 +239,7 @@ const stageNoCl = {
             {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '签约|数量', colSpan: '2|1', rowSpan: '1|1', field: 'deal_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'deal_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '施工图复核|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '台账|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
@@ -273,7 +273,7 @@ const stageNoCl = {
     pos: {
         cols: [
             {title: '部位名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@'},
-            {title: '复核数量', colSpan: '1', rowSpan: '2', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '设计量', colSpan: '1', rowSpan: '2', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},

+ 1 - 0
app/const/tender.js

@@ -59,6 +59,7 @@ const measureType = {
 const imType = {
     zl: { value: 0, name: '总量控制' },
     tz: { value: 1, name: '0号台账' },
+    bw: { value: 2, name: '计量单元' },
 };
 
 const typeString = [];

+ 26 - 8
app/controller/material_controller.js

@@ -15,6 +15,7 @@ const tenderConst = require('../const/tender');
 const measureType = tenderConst.measureType;
 const accountGroup = require('../const/account_group').group;
 const materialConst = require('../const/material');
+const MaterialCalculator = require('../lib/material_calc');
 
 module.exports = app => {
     class MaterialController extends app.BaseController {
@@ -227,16 +228,21 @@ module.exports = app => {
                 // 取所有工料表
                 renderData.materialBillsData = await ctx.service.materialBills.getAllDataByCondition({ where: searchsql });
                 // 取对应期的截取上期的调差金额和应耗数量
-                for (const mindex in renderData.materialBillsData) {
-                    const pre_tp = renderData.materialBillsData[mindex].pre_tp !== null ? renderData.materialBillsData[mindex].pre_tp.split(',')[ctx.material.order - 1] : null;
-                    renderData.materialBillsData[mindex].pre_tp = pre_tp;
-                    if (ctx.material.readOnly) {
-                        const quantity = renderData.materialBillsData[mindex].s_quantity.split(',')[ctx.material.order - 1];
+                if (ctx.material.highOrder !== ctx.material.order) {
+                    for (const [mindex, mb] of renderData.materialBillsData.entries()) {
+                        const [quantity, pre_tp] = await ctx.service.materialBillsHistory.getByMbId(ctx.material.id, ctx.material.order, mb.id);
                         renderData.materialBillsData[mindex].quantity = quantity;
+                        renderData.materialBillsData[mindex].pre_tp = pre_tp;
                     }
                 }
                 // 取所有已被调用的工料清单表
                 renderData.materialListData = await ctx.service.materialList.getAllDataByCondition({ tid: ctx.tender.id, mid: ctx.material.id });
+                // 基数
+                // if (!ctx.material.readOnly) {
+                const stage_list = await ctx.service.stage.getStageMsgByStageId(ctx.material.stage_id);
+                renderData.calcBase = await ctx.service.stage.getMaterialCalcBase(stage_list, ctx.tender.info);
+                // }
+
                 renderData.materialType = JSON.stringify(materialConst);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.material.info);
                 await this.layout('material/info.ejs', renderData, 'material/info_modal.ejs');
@@ -262,6 +268,7 @@ module.exports = app => {
                     midList = await ctx.service.material.getPreMidList(ctx.tender.id, ctx.material.order);
                     searchsql.mid = midList;
                 }
+                searchsql.t_type = materialConst.t_type[0].value;
                 renderData.materialBillsData = await ctx.service.materialBills.getAllDataByCondition({ where: searchsql });
                 // 取所有已被调用的工料清单表
                 renderData.materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id, ctx.material.id);
@@ -348,7 +355,7 @@ module.exports = app => {
                         responseData.data = await ctx.service.materialBills.add();
                         break;
                     case 'del':
-                        await ctx.service.materialBills.del(data.id);
+                        responseData.data.m_tp = await ctx.service.materialBills.del(data.id);
                         break;
                     case 'update':
                         if (data.updateData.code === '' || data.updateData.code === null) {
@@ -362,11 +369,11 @@ module.exports = app => {
                             throw '长度不超过15个字符';
                         }
                         // 判断编号是否已存在
-                        const billData = await ctx.service.materialBills.getAllDataByCondition({ where: { mid: ctx.material.id, code: data.updateData.code } });
+                        const billData = await ctx.service.materialBills.getAllDataByCondition({ where: { tid: ctx.tender.id, code: data.updateData.code } });
                         if (billData.length > 1 || (billData.length > 0 && billData[0].id !== data.updateData.id)) {
                             throw '该编号已存在,请重新输入。';
                         }
-                        await ctx.service.materialBills.save(data.updateData);
+                        responseData.data.m_tp = await ctx.service.materialBills.save(data.updateData);
                         break;
                     case 'rate':
                         // 判断数量是否为数字
@@ -378,6 +385,17 @@ module.exports = app => {
                         }
                         await ctx.service.material.changeRate(data.rate);
                         break;
+                    case 'expr':
+                        const materialCalculator = new MaterialCalculator(ctx, ctx.material.stage_id, ctx.tender.info);
+                        const quantity = await materialCalculator.calculateExpr(data.expr);
+                        // 更新quantity值并重新返回计算本期金额,截止本期金额
+                        const updateData = {
+                            id: data.id,
+                            quantity: quantity !== 0 ? quantity : null,
+                            expr: data.expr,
+                        };
+                        responseData.data = await ctx.service.materialBills.updateFYQuantity(updateData);
+                        break;
                     default: throw '参数有误';
                 }
 

+ 1 - 1
app/controller/setting_controller.js

@@ -204,7 +204,7 @@ module.exports = app => {
                 // 获取验证规则
                 const rule = ctx.service.projectAccount.rule('add');
                 ctx.validate(rule);
-
+                ctx.request.body.project_id = projectData.id;
                 const result = await ctx.service.projectAccount.save(ctx.request.body);
                 if (!result) {
                     throw '保存账号数据失败';

+ 121 - 56
app/controller/stage_controller.js

@@ -147,32 +147,33 @@ module.exports = app => {
                 const renderData = await this._getDefaultRenderData(ctx);
                 [renderData.ledgerSpread, renderData.posSpread] = this._getSpreadSetting();
                 renderData.changeConst = changeConst;
-                renderData.ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
-                const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
-                for (const d of dgnData) {
-                    const l = ctx.app._.find(renderData.ledgerData, {id: d.id});
-                    ctx.app._.assignIn(l, d);
-                }
-                let curStageData, preStageData;
-                // 当前操作人查看最新数据,其他人查看历史数据
-                if (ctx.stage.readOnly) {
-                    curStageData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
-                } else {
-                    curStageData = await ctx.service.stageBills.getLastestStageData(ctx.tender.id, ctx.stage.id);
-                }
-                // 查询截止上期数据
-                if (ctx.stage.order > 1) {
-                    preStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
-                    //renderData.preStageData = await ctx.service.stageBills.getEndStageData(ctx.tender.id, ctx.stage.order - 1);
-                } else {
-                    preStageData = [];
-                }
-                this.ctx.helper.assignRelaData(renderData.ledgerData, [
-                    {data: curStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid',},
-                    {data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid',}
-                ]);
+                // renderData.ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
+                // const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
+                // for (const d of dgnData) {
+                //     const l = ctx.app._.find(renderData.ledgerData, {id: d.id});
+                //     ctx.app._.assignIn(l, d);
+                // }
+                // let curStageData, preStageData;
+                // // 当前操作人查看最新数据,其他人查看历史数据
+                // if (ctx.stage.readOnly) {
+                //     curStageData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
+                // } else {
+                //     curStageData = await ctx.service.stageBills.getLastestStageData(ctx.tender.id, ctx.stage.id);
+                // }
+                // // 查询截止上期数据
+                // if (ctx.stage.order > 1) {
+                //     preStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
+                //     //renderData.preStageData = await ctx.service.stageBills.getEndStageData(ctx.tender.id, ctx.stage.order - 1);
+                // } else {
+                //     preStageData = [];
+                // }
+                // this.ctx.helper.assignRelaData(renderData.ledgerData, [
+                //     {data: curStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid',},
+                //     {data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid',}
+                // ]);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.stage.index);
                 renderData.whiteList = this.ctx.app.config.multipart.whitelist;
+                renderData.imType = tenderConst.imType;
                 // 获取附件列表
                 const attData = await ctx.service.stageAtt.getDataByTenderIdAndStageId(ctx.tender.id, ctx.params.order);
                 for (const index in attData) {
@@ -186,6 +187,94 @@ module.exports = app => {
             }
         }
 
+        async _getStageLedgerData(ctx) {
+            const ledgerData = await ctx.service.ledger.getData(ctx.tender.id);
+            const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
+            for (const d of dgnData) {
+                const l = ctx.app._.find(ledgerData, {id: d.id});
+                ctx.app._.assignIn(l, d);
+            }
+            let curStageData, preStageData;
+            // 当前操作人查看最新数据,其他人查看历史数据
+            if (ctx.stage.readOnly) {
+                curStageData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
+            } else {
+                curStageData = await ctx.service.stageBills.getLastestStageData(ctx.tender.id, ctx.stage.id);
+            }
+            // 查询截止上期数据
+            if (ctx.stage.order > 1) {
+                preStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
+                //renderData.preStageData = await ctx.service.stageBills.getEndStageData(ctx.tender.id, ctx.stage.order - 1);
+            } else {
+                preStageData = [];
+            }
+            this.ctx.helper.assignRelaData(ledgerData, [
+                {data: curStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid',},
+                {data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid',}
+            ]);
+            return ledgerData;
+        }
+        async _getStagePosData(ctx) {
+            let curStageData, preStageData;
+            const posData = await ctx.service.pos.getPosDataWithAddStageOrder({tid: ctx.tender.id});
+            // 根据当前人,或指定对象查询数据
+            //console.time('cur');
+            if (ctx.stage.readOnly) {
+                curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id,
+                    ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
+            } else {
+                curStageData = await ctx.service.stagePos.getLastestStageData2(ctx.tender.id, ctx.stage.id);
+            }
+            //console.timeEnd('cur');
+            // 查询截止上期数据
+            //console.time('pre');
+            if (ctx.stage.order > 1) {
+                preStageData = await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
+                //responseData.data.preStageData = await ctx.service.stagePos.getEndStageData(ctx.tender.id, ctx.stage.order - 1);
+            } else {
+                preStageData = [];
+            }
+            //console.timeEnd('pre');
+            //console.time('assign');
+            console.log('cur: ' + curStageData.length);
+            console.log('pre: ' + preStageData.length);
+            this.ctx.helper.assignRelaData(posData, [
+                {data: curStageData, fields: ['contract_qty', 'qc_qty', 'postil'], prefix: '', relaId: 'pid'},
+                {data: preStageData, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
+            ]);
+            return posData;
+        }
+        async _getStageDetailData(ctx) {
+            if (ctx.stage.readOnly) {
+                return await ctx.service.stageDetail.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
+            } else {
+                return await ctx.service.stageDetail.getLastestStageData(ctx.tender.id, ctx.stage.id);
+            }
+        }
+        async _getStageChangeData(ctx) {
+            if (ctx.stage.readOnly) {
+                return await ctx.service.stageChange.getAuditorAllStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
+            } else {
+                return await ctx.service.stageChange.getLastestAllStageData(ctx.tender.id, ctx.stage.id);
+            }
+        }
+
+        async getStageData(ctx) {
+            try {
+                const ledgerData = await this._getStageLedgerData(ctx);
+                const posData = await this._getStagePosData(ctx);
+                const detailData = await this._getStageDetailData(ctx);
+                const changeData = await this._getStageChangeData(ctx);
+
+                ctx.body = {err: 0, msg: '', data: {
+                    ledgerData, posData, detailData, changeData,
+                }};
+            } catch (err) {
+                this.log(err);
+                ctx.body = {err: 1, msg: err.toString(), data: null};
+            }
+        }
+
         /**
          * 获取期数据(截止上期 & 本期) (Ajax)
          * @param ctx
@@ -259,7 +348,6 @@ module.exports = app => {
                         responseData.data.curStageData = await ctx.service.stageBills.updateStageData(data.bills.stage);
                     }
                 }
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 await ctx.service.stage.updateCheckCalcFlag(ctx.stage.id, true);
                 ctx.body = responseData;
             } catch (err) {
@@ -304,10 +392,15 @@ module.exports = app => {
                 let result;
                 if (data.target.pos) {
                     result = await ctx.service.stageChange.posChange(data.target.pos, data.change);
+                    result.change = { target: {lid: data.target.pos.lid, pid: data.target.pos.id } };
+                    result.change.data = await ctx.service.stageChange.getLastestStageData(ctx.tender.id,
+                        ctx.stage.id, data.target.pos.lid, data.target.pos.id);
                 } else {
                     result = await ctx.service.stageChange.billsChange(data.target.bills, data.change);
+                    result.change = { target: { lid: data.target.bills.id, pid: '-1' } };
+                    result.change.data = await ctx.service.stageChange.getLastestStageData(ctx.tender.id,
+                        ctx.stage.id, data.target.bills.id, '-1');
                 }
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 await ctx.service.stage.updateCheckCalcFlag(ctx.stage.id, true);
                 ctx.body = {err: 0, msg: '', data: result};
             } catch(err) {
@@ -363,7 +456,6 @@ module.exports = app => {
 
                 const data = JSON.parse(ctx.request.body.data);
                 await ctx.service.stage.buildDetailData(ctx.tender.id, ctx.stage.order, data);
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
 
                 ctx.body = {err: 0, msg: '', data: null};
             } catch (err) {
@@ -397,7 +489,6 @@ module.exports = app => {
                         this.ctx.helper.assignRelaData(result.pos, [
                             {data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'}
                         ]);
-                        result.stageDetail = await ctx.service.stageDetail.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder);
                     } else {
                         const curStage = await ctx.service.stageBills.getLastestStageData(ctx.tender.id, ctx.stage.id);
                         this.ctx.helper.assignRelaData(result.ledger, [
@@ -407,8 +498,9 @@ module.exports = app => {
                         this.ctx.helper.assignRelaData(result.pos, [
                             {data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'}
                         ]);
-                        result.stageDetail = await ctx.service.stageDetail.getLastestStageData(ctx.tender.id, ctx.stage.id);
                     }
+                    result.stageDetail = await this._getStageDetailData(ctx);
+                    result.changeData = await this._getStageChangeData(ctx);
                     ctx.body = { err: 0, msg: '', data: result };
                 }
             } catch (err) {
@@ -428,7 +520,6 @@ module.exports = app => {
 
                 const data = JSON.parse(ctx.request.body.data);
                 await ctx.service.stage.update(data, { id: ctx.stage.id });
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
 
                 ctx.body = {err: 0, msg: '', data: this.ctx.stage};
             } catch (err) {
@@ -453,7 +544,6 @@ module.exports = app => {
                 } else {
                     responseData.data = await ctx.service.stageDetail.saveDetailData(data);
                 }
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);
@@ -475,7 +565,6 @@ module.exports = app => {
                 const fileInfo = path.parse(stream.filename);
                 const fileName = path.join('public/upload', this.ctx.tender.id.toString(), 'im', 'calcImg_' + create_time + fileInfo.ext);
                 await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, 'app', fileName));
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = {err: 0, msg: '', data: fileName};
             } catch(err) {
                 this.log(err);
@@ -513,7 +602,6 @@ module.exports = app => {
                 await this.ctx.service.stageDetail.saveDetailData(data);
                 const imData = await ctx.service.stageDetail.getLastestImStageData(this.ctx.tender.id, this.ctx.stage.id, data.lid, data.uuid);
                 const responseData = {err: 0, msg: '', data: imData};
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, true);
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);
@@ -521,23 +609,6 @@ module.exports = app => {
             }
         }
 
-        /**
-         * 中间计量 -- 完成中间计量(Post)
-         * @param ctx
-         * @returns {Promise<void>}
-         */
-        async doneDetail(ctx) {
-            try {
-                this._checkStageCanModify(ctx);
-
-                await ctx.service.stage.updateCheckDetailFlag(ctx.stage.id, false);
-                ctx.stage.check_detail = false;
-                ctx.body = {err: 0, msg: '', data: false}
-            } catch (err) {
-                this.log(err);
-                ctx.body = this.ajaxErrorBody(err, '数据错误,刷新页面再试');
-            }
-        }
 
         /**
          * 合同支付 (Get)
@@ -871,9 +942,6 @@ module.exports = app => {
                 if (ctx.stage.status === auditConst.status.checking || ctx.stage.status === auditConst.status.checked) {
                     throw '该期数据当前无法上报';
                 }
-                if (ctx.stage.check_detail) {
-                    throw '上报前,需要完成中间计量。';
-                }
 
                 await ctx.service.stageAudit.start(ctx.stage.id, ctx.stage.times);
 
@@ -906,9 +974,6 @@ module.exports = app => {
                 if (!data.checkType || isNaN(data.checkType)) {
                     throw '提交数据错误';
                 }
-                if (data.checkType === auditConst.status.checked && ctx.stage.check_detail) {
-                    throw '审批通过前,需要中间计量。';
-                }
                 if (data.checkType === auditConst.status.checkNo) {
                     if (!data.checkType || isNaN(data.checkType)) {
                         throw '提交数据错误';

+ 17 - 0
app/extend/helper.js

@@ -764,6 +764,23 @@ module.exports = {
         }
         return t.split("").reverse().join("") + "." + r;
     },
+    transFormToChinese(num) {
+        const changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
+        const unit = ["", "十", "百", "千", "万"];
+        num = parseInt(num);
+        let getWan = (temp) => {
+            let strArr = temp.toString().split("").reverse();
+            let newNum = "";
+            for (var i = 0; i < strArr.length; i++) {
+                newNum = (i == 0 && strArr[i] == 0 ? "" : (i > 0 && strArr[i] == 0 && strArr[i - 1] == 0 ? "" : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i]))) + newNum;
+            }
+            return newNum;
+        }
+        let overWan = Math.floor(num / 10000);
+        let noWan = num % 10000;
+        if (noWan.toString().length < 4) noWan = "0" + noWan;
+        return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(num);
+    },
 
     async sendUserSms(userId, type, judge, msg) {
         const mobiles = [];

+ 68 - 0
app/lib/material_calc.js

@@ -0,0 +1,68 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const math = require('mathjs');
+
+class MaterialCalculate {
+    constructor(ctx, stage_id_list, tenderInfo) {
+        this.ctx = ctx;
+        this.stageList = stage_id_list;
+        this.percentReg = /[0-9]+%/g;
+        this.tenderInfo = tenderInfo;
+    }
+
+    /**
+     * 获取 计算基数
+     * @returns {Promise<void>}
+     */
+    async getCalcBase() {
+        if (this.bases) { return; }
+        const stage_list = await this.ctx.service.stage.getStageMsgByStageId(this.stageList);
+        const bases = await this.ctx.service.stage.getMaterialCalcBase(stage_list, this.tenderInfo);
+        this.bases = bases.sort(function(a, b) {
+            return a.sort - b.sort;
+            // if (a && b) {
+            //     return b.code.indexOf(a.code) >= 0 ? 1 : 0;
+            // } else {
+            //     return 0;
+            // }
+        });
+        for (const b of this.bases) {
+            b.reg = new RegExp(b.code, 'igm');
+        }
+    }
+
+    _calculateExpr(expr) {
+        let formula = expr;
+        for (const b of this.bases) {
+            formula = formula.replace(b.reg, b.value);
+        }
+        const percent = formula.match(this.percentReg);
+        if (percent) {
+            for (const p of percent) {
+                const v = math.eval(p.replace('%', '/100'));
+                formula = formula.replace(p, v);
+            }
+        }
+        try {
+            const value = math.eval(formula);
+            return value;
+        } catch (err) {
+            return 0;
+        }
+    }
+
+    async calculateExpr(expr) {
+        await this.getCalcBase();
+        return this._calculateExpr(expr);
+    }
+}
+
+module.exports = MaterialCalculate;

+ 34 - 1
app/public/css/main.css

@@ -51,6 +51,15 @@ font-size: .875rem;
 .custom-control-label {
   cursor: pointer;
 }
+.popover {
+  background-color: #000
+}
+.popover-body{
+  color:#fff;
+}
+.bs-popover-auto[x-placement^="bottom"] .arrow::after, .bs-popover-bottom .arrow::after{
+  border-bottom-color:#000;
+}
 /*自定义css*/
 .in-1{padding-left:5px!important}
 .in-2{padding-left:21px!important}
@@ -92,6 +101,12 @@ font-size: .875rem;
 .sjs-height-4,.sjs-height-5,.sjs-height-6,.sjs-option-height{
   overflow: auto;
 }
+.sjs-bar-1,.sjs-bar-2,.sjs-bar-3,.sjs-bar-4{
+  height:30px;
+}
+.sjs-bar{
+  height:30px;
+}
 .sjs-bottom{
   height:400px;
   overflow-y: auto;
@@ -103,6 +118,10 @@ font-size: .875rem;
 .form-signin {
     max-width: 500px;
     margin: 150px auto;
+    background: #fff;
+    padding:30px;
+    border:1px solid #ddd;
+    border-radius: .25rem
 }
 .has-danger {
     -webkit-animation: shake 1s .2s ease both;
@@ -426,7 +445,8 @@ font-size: .875rem;
 }
 /*登陆相关*/
 .login-body{
-  background: #fff
+  background:linear-gradient(#33425b,#192948);
+  height:960px
 }
 .login-infoinput {
   margin-top:15%
@@ -697,6 +717,13 @@ font-size: .875rem;
 .add-sign-list-item:hover .btn-link {
   display: block
 }
+/*标段类表折叠收起*/
+.fold-switch {
+  cursor: pointer;
+}
+.fold-switch:hover{
+  color:#0056b3;
+}
 /*界面紧凑相关代码*/
 body{
   font-size:12px;
@@ -728,6 +755,11 @@ body{
 }
 label{
   margin-bottom:.3rem;
+  color:#757575;
+}
+.form-control-plaintext.form-control-lg, .form-control-plaintext.form-control-sm {
+  padding-left:.5rem;
+  background: #f2f2f280
 }
 .invalid-feedback{
   font-size:100%;
@@ -786,6 +818,7 @@ label{
 }
 .panel-content .panel-title{
   padding-left:175px;
+  background: linear-gradient( #ccc,2%, #ffffff);
 }
 .nav-link{
   padding:.3rem .5rem;

+ 2 - 2
app/public/js/change_company.js

@@ -11,7 +11,7 @@
 $(document).ready(() => {
     //提出单位编辑
     $('#addcompany').click(function(){
-        let newinput = '<div class="form-group"><input type="text" class="form-control" placeholder="请输入公司名称"></div>';
+        let newinput = '<div class="form-group"><input type="text" class="form-control" placeholder="请输入名称"></div>';
         $('#companyadddiv').append(newinput);
     });
 
@@ -78,4 +78,4 @@ function selectCOmpanyHtml(data) {
         html.push('<option>'+ s.name +'</option>');
     }
     $('#company').html(html);
-}
+}

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

@@ -21,11 +21,9 @@ function autoFlashHeight(){
     $(".sjs-height-0").height($(window).height()-cHeader-90+45);
     $(".sjs-height-1").height($(window).height()-cHeader-bcontent-90+45);
     $(".sjs-height-2").height($(window).height()-cHeader-sBarz-110);
-    $(".sjs-height-3").height($(window).height()-cHeader-sBar-492+15);
+    $(".sjs-height-3").height($(window).height()-cHeader-sBar-492+15);/*492*/
     $(".sjs-height-4").height($(window).height()-cHeader-pBarz-110+65);
-    $(".sjs-height-5").height($(window).height()-cHeader-sBart-555);
-    $(".sjs-height-6").height($(window).height()-cHeader-bdtopc-156);
-    $(".sjs-height-7").height($(window).height()-cHeader-sBar-110);
+    $(".sjs-height-5").height($(window).height()-cHeader-sBar-492+45);/*492*/
     $(".sp-wrap").height(bcontent-40);
     /*侧栏高度*/
     $(".sjs-sh-1").height($(window).height()-cHeader-sBar1-92+45);

+ 59 - 10
app/public/js/ledger.js

@@ -27,6 +27,7 @@ function transExpr(expr) {
 }
 
 $(document).ready(function() {
+    let stdXmj, stdGcl, dealBills, searchLedger;
     autoFlashHeight();
     // 初始化台账
     const ledgerSpread = SpreadJsObj.createNewSpread($('#ledger-spread')[0]);
@@ -58,7 +59,8 @@ $(document).ready(function() {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'ledger.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');
@@ -69,7 +71,21 @@ $(document).ready(function() {
             }
             autoFlashHeight();
             ledgerSpread.refresh();
-            posSpread.refresh();
+            if (posSpread) {
+                posSpread.refresh();
+            }
+            if (stdXmj) {
+                stdXmj.spread.refresh();
+            }
+            if (stdGcl) {
+                stdGcl.spread.refresh();
+            }
+            if (dealBills) {
+                dealBills.spread.refresh();
+            }
+            if (searchLedger) {
+                searchLedger.spread.refresh();
+            }
         }
     });
 
@@ -131,16 +147,35 @@ $(document).ready(function() {
                     obj.addClass('disabled');
                 }
             };
+            const invalidAll = function () {
+                setObjEnable($('#insert'), false);
+                setObjEnable($('#delete'), false);
+                setObjEnable($('#up-move'), false);
+                setObjEnable($('#down-move'), false);
+                setObjEnable($('#up-level'), false);
+                setObjEnable($('#down-level'), false);
+            };
 
             const sel = selection ? selection[0] : sheet.getSelections()[0];
             const row = sel ? sel.row : -1;
             const tree = sheet.zh_tree;
-            if (!tree) return;
+            if (!tree) {
+                invalidAll();
+                return;
+            }
             const first = sheet.zh_tree.nodes[row];
+            if (!first) {
+                invalidAll();
+                return;
+            }
             let last = first, sameParent = true;
-            if (sel.rowCount > 1) {
+            if (sel.rowCount > 1 && first) {
                 for (let r = 1; r < sel.rowCount; r++) {
-                    const rNode = tree.nodes[sel.row + r];
+                    const rNode = tree.nodes[row + r];
+                    if (!rNode) {
+                        sameParent = false;
+                        break;
+                    }
                     if (rNode.level > first.level) continue;
                     if ((rNode.level < first.level) || (rNode.level === first.level && rNode.pid !== first.pid)) {
                         sameParent = false;
@@ -1406,8 +1441,6 @@ $(document).ready(function() {
         treeOperationObj.loadExprToInput(ledgerSpread.getActiveSheet());
     }, null, true);
 
-    let stdXmj, stdGcl, dealBills, searchLedger;
-
     $.divResizer({
         select: '#right-spr',
         callback: function () {
@@ -1618,7 +1651,14 @@ $(document).ready(function() {
                 }, function (result) {
                     const refreshNode = mainTree.loadPostData(result);
                     treeOperationObj.refreshTree(mainSheet, refreshNode);
-                    mainSheet.setSelection(refreshNode.create[0].index, sel.col, sel.rowCount, sel.colCount);
+                    if (refreshNode.create && refreshNode.create.length > 0) {
+                        mainSheet.setSelection(refreshNode.create[refreshNode.create.length - 1].index, sel.col, sel.rowCount, sel.colCount);
+                    } else {
+                        const node = _.find(ledgerTree.nodes, {code: stdNode.code, name: stdNode.name});
+                        if (node) {
+                            mainSheet.setSelection(ledgerTree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
+                        }
+                    }
                     treeOperationObj.refreshOperationValid(mainSheet);
                 });
             });
@@ -1991,10 +2031,14 @@ $(document).ready(function() {
                 const auditorshtml = [];
                 // 重新上报时。令其它的审批人流程图标转换
                 $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
+                for (let i = 0; i < $('#auditors-list li').length; i++) {
+                    $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
+                }
                 // 添加新审批人
                 auditorshtml.push('<li class="list-group-item" data-auditid="' + data.audit_id + '">');
                 auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
                 auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                auditorshtml.push('<span class="pull-right">终审</span>');
                 auditorshtml.push('</li>');
                 $('#auditors-list').append(auditorshtml.join(''));
 
@@ -2004,8 +2048,9 @@ $(document).ready(function() {
                 // 添加新审批人
                 auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.audit_id + '">');
                 auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
-                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small></h5>');
-                auditorshtml2.push('</li>');
+                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                auditorshtml2.push('<span class="pull-right">终审</span>');
+                auditorshtml2.push('</h5></li>');
                 $('#auditors-list2').append(auditorshtml2.join(''));
             });
         }
@@ -2034,6 +2079,10 @@ $(document).ready(function() {
                 $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
                     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
             }
+            for (let i = 0; i < $('#auditors-list li').length; i++) {
+                $('#auditors-list li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审')
+                $('#auditors-list2 li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2 li').length ? '终' : transFormToChinese(i+1)) + '审')
+            }
         });
     });
     // 选择excel文件后,加载全部sheet

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

@@ -47,7 +47,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'ledger.audit.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 214 - 7
app/public/js/material.js

@@ -19,6 +19,16 @@ function loadUpdateMaterials(newMaterial, fields) {
         }
     }
 }
+
+function resetTpTable() {
+    const rate = $('#changeRate').val();
+    const bqhs = ZhCalc.round(ZhCalc.mul(m_tp, 1+rate/100), 2);
+    const jzbqhs = ZhCalc.round(ZhCalc.mul(ZhCalc.add(pre_tp, m_tp), 1+rate/100), 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 : '');
+}
 $(document).ready(() => {
     autoFlashHeight();
     const materialSpread = SpreadJsObj.createNewSpread($('#material-spread')[0]);
@@ -52,11 +62,42 @@ $(document).ready(() => {
         readOnly: readOnly,
     };
 
+    const spCol = _.find(materialSpreadSetting.cols, {field: 'quantity'});
+    spCol.readOnly = true;
+    spCol.cellType = 'activeImageBtn';
+    spCol.normalImg = '#ellipsis-icon';
+    spCol.indent = 5;
+    spCol.showImage = function (data) {
+        // return !readOnly && data.t_type === 2 && data.mid === materialID;
+        return data.t_type === 2;
+    };
+    materialSpreadSetting.imageClick = function (data) {
+        if (data.t_type === 2) {
+            $('#bcyy').modal('show');
+            $('#materialbillsId').val(data.id);
+            $('#expr').val(data.expr);
+            if (!readOnly && data.mid === materialID) {
+                $('#expr').attr('readOnly', false);
+                $('#expr_btn').show();
+                $('#expr_select').show();
+            } else {
+                $('#expr').attr('readOnly', true);
+                $('#expr_btn').hide();
+                $('#expr_select').hide();
+            }
+        }
+    };
+
     const materialBase = {
         isEdit: function (data) {
-            return materialListData.find(function (item) {
-                return item.mb_id === data.id;
-            });
+            if (data.t_type === 2) {
+                return data.mid === materialID;
+            } else {
+                const mlInfo = materialListData.find(function (item) {
+                    return item.mb_id === data.id;
+                });
+                return data.mid === materialID && mlInfo === undefined;
+            }
         },
         // isStage: function (data) {
         //     return data.mid === materialID;
@@ -79,7 +120,7 @@ $(document).ready(() => {
         },
         readOnly: {
             isEdit: function (data) {
-                return !(!readOnly && materialBase.isEdit(data) === undefined);
+                return !(!readOnly && materialBase.isEdit(data));
             },
             remark: function () {
                 return readOnly;
@@ -102,7 +143,7 @@ $(document).ready(() => {
             const sheet = materialSpread.getActiveSheet();
             const select = SpreadJsObj.getSelectObject(sheet);
             // 还需判断是否已被调差清单调用
-            setObjEnable($('#del'), !readOnly && select && materialBase.isEdit(select) === undefined);
+            setObjEnable($('#del'), !readOnly && select && materialBase.isEdit(select));
         },
         add: function () {
             const sheet = materialSpread.getActiveSheet();
@@ -120,6 +161,8 @@ $(document).ready(() => {
             const sheet = materialSpread.getActiveSheet();
             const select = SpreadJsObj.getSelectObject(sheet);
             postData(window.location.pathname + '/save', {type: 'del', id: select.id}, function (result) {
+                m_tp = result.m_tp;
+                resetTpTable();
                 const index = materialBillsData.indexOf(select);
                 materialBillsData.splice(index, 1);
                 sheet.deleteRows(index, 1);
@@ -202,12 +245,21 @@ $(document).ready(() => {
                         return;
                     }
                 }
+                if (col.field === 't_type') {
+                    if (validText === 1) {
+                        select.quantity = null;
+                        select.expr = null;
+                        select.m_tp = null;
+                    }
+                }
                 select[col.field] = validText;
                 select.msg_spread = materialCol.getValue.msg_spread(select);
                 select.m_spread = materialCol.getValue.m_spread(select);
                 select.m_tp = materialCol.getValue.m_tp(select);
                 // 更新至服务器
                 postData(window.location.pathname + '/save', { type:'update', updateData: select }, function (result) {
+                    m_tp = result.m_tp;
+                    resetTpTable();
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 }, function () {
                     select[col.field] = orgValue;
@@ -250,7 +302,7 @@ $(document).ready(() => {
                         const sheet = materialSpread.getActiveSheet();
                         const select = SpreadJsObj.getSelectObject(sheet);
                         materialSpreadObj.refreshActn();
-                        if (!readOnly && select && materialBase.isEdit(select) === undefined) {
+                        if (!readOnly && select && materialBase.isEdit(select)) {
                             return false;
                         } else {
                             return true;
@@ -267,6 +319,160 @@ $(document).ready(() => {
                 $('#rate_set').find('td').eq(1).text(bqhs !== 0 ? bqhs : '');
                 $('#rate_set').find('td').eq(2).text(jzbqhs !== 0 ? jzbqhs : '');
             });
+        });
+
+        $('#expr_select button').on('click', function () {
+            const code = $(this).text();
+            $('#expr').val($('#expr').val() + code);
+        });
+
+        const ExprObj = {
+            _checkExprValid(expr, invalidParam) {
+                if (!expr) return [true, null];
+                const param = [];
+                let num = '', base = '';
+                for (let i = 0, iLen = expr.length; i < iLen; i++) {
+                    if (/^[\d\.%]+/.test(expr[i])) {
+                        if (base !== '') {
+                            param.push({type: 'base', value: base});
+                            base = '';
+                        }
+                        num = num + expr[i];
+                    } else if (/^[a-z]/.test(expr[i])) {
+                        if (num !== '') {
+                            param.push({type: 'num', value: num});
+                            base = '';
+                        }
+                        base = base + expr[i];
+                    } else if (expr[i] === '(') {
+                        if (num !== '') {
+                            param.push({type: 'num', value: num});
+                            base = '';
+                        }
+                        if (base !== '') {
+                            param.push({type: 'base', value: base});
+                            base = '';
+                        }
+                        param.push({type: 'left', value: '('});
+                    } else if (expr[i] === ')') {
+                        if (num !== '') {
+                            param.push({type: 'num', value: num});
+                            base = '';
+                        }
+                        if (base !== '') {
+                            param.push({type: 'base', value: base});
+                            base = '';
+                        }
+                        param.push({type: 'right', value: ')'});
+                    } else if (/^[\+\-*\/]/.test(expr[i])) {
+                        if (num !== '') {
+                            param.push({type: 'num', value: num});
+                            base = '';
+                        }
+                        if (base !== '') {
+                            param.push({type: 'base', value: base});
+                            base = '';
+                        }
+                        param.push({type: 'calc', value: expr[i]});
+                    } else {
+                        return [false, '输入的表达式含有非法字符: ' + expr[i]];
+                    }
+                }
+                if (num !== '') {
+                    param.push({type: 'num', value: num});
+                    base = '';
+                }
+                if (base !== '') {
+                    param.push({type: 'base', value: base});
+                    base = '';
+                }
+                if (param.length === 0) return true;
+                if (param.length > 1) {
+                    if (param[0].value === '-') {
+                        param[1].value = '-' + param[1];
+                    }
+                    param.unshift();
+                }
+                const iLen = param.length;
+                let iLeftCount = 0, iRightCount = 0;
+                for (const [i, p] of param.entries()) {
+                    if (p.type === 'calc') {
+                        if (i === 0 || i === iLen - 1)
+                            return [false, '输入的表达式非法:计算符号' + p.value + '前后应有数字或计算基数'];
+                    }
+                    if (p.type === 'num') {
+                        num = p.value.replace('%', '');
+                        if (p.value.length - num.length > 1)
+                            return [false, '输入的表达式非法:' + p.value + '不是一个有效的数字'];
+                        num = _.toNumber(num);
+                        if (num === undefined || num === null || _.isNaN(num))
+                            return [false, '输入的表达式非法:' + p.value + '不是一个有效的数字'];
+                        if (i > 0) {
+                            if (param[i - 1].type !== 'calc') {
+                                return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
+                            } else if (param[i - 1].value === '/' && num === 0) {
+                                return [false, '输入的表达式非法:请勿除0'];
+                            }
+                        }
+                    }
+                    if (p.type === 'base') {
+                        const baseParam = _.find(calcBase, {code: p.value});
+                        if (!baseParam)
+                            return [false, '输入的表达式非法:不存在计算基数' + p.value];
+                        if (invalidParam && invalidParam.indexOf(p.value) >= 0)
+                            return [false, '不可使用计算基数' + p.value];
+                        if (i > 0 && param[i - 1].type === 'calc')
+                            return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
+                    }
+                    if (p.type === 'left') {
+                        iLeftCount += 1;
+                        if (i !== 0 && param[i-1].type !== 'calc')
+                            return [false, '输入的表达式非法:(前应有运算符'];
+                    }
+                    if (p.type === 'right') {
+                        iRightCount += 1;
+                        if (i !== iLen - 1 && param[i+1].type !== 'calc')
+                            return [false, '输入的表达式非法:)后应有运算符'];
+                        if (iRightCount > iLeftCount)
+                            return [false, '输入的表达式非法:")"前无对应的"("'];
+                    }
+                }
+                if (iLeftCount > iRightCount)
+                    return [false, '输入的表达式非法:"("后无对应的")"'];
+                return [true, ''];
+            },
+            _checkExpr: function (text) {
+                if (text) {
+                    const num = _.toNumber(text);
+                    if (num) {
+                        console.log(num);
+                    } else {
+                        const expr = text.replace('=', '').toLowerCase();
+                        const [valid, msg] = this._checkExprValid(expr);
+                        if (!valid) return [valid, msg];
+                    }
+                }
+                return [true, ''];
+            },
+        };
+
+        $('#expr_btn').click(function () {
+            const expr = $('#expr').val();
+            // 判断表达式格式
+            const [valid, msg] = ExprObj._checkExpr(expr);
+            if (!valid) {
+                toastr.error(msg);
+            }
+            postData(window.location.pathname + '/save', { type:'expr', id: $('#materialbillsId').val(), expr: expr }, function (result) {
+                m_tp = result.m_tp;
+                resetTpTable();
+                const sheet = materialSpread.getActiveSheet();
+                const select = SpreadJsObj.getSelectObject(sheet);
+                const index = materialBillsData.indexOf(select);
+                materialBillsData.splice(index, 1, result.info);
+                SpreadJsObj.reLoadRowData(sheet, index);
+                $('#bcyy').modal('hide');
+            });
         })
     } else {
         // SpreadJsObj.forbiddenSpreadContextMenu('#material-spread', materialSpread);
@@ -274,7 +480,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.compare.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 4 - 1
app/public/js/material_list.js

@@ -294,6 +294,8 @@ $(document).ready(() => {
                     } else {
                         notJoinList.push(result);
                     }
+                    gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(select);
+                    SpreadJsObj.reLoadRowData(sheet, iRow);
                     sheet.getRange(iRow, -1, 1, -1).backColor(color);
                     loadMaterialData(iGclRow, iRow);
                 });
@@ -567,7 +569,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.compare.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

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

@@ -102,7 +102,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'measure.compare.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 31 - 24
app/public/js/measure_material.js

@@ -19,12 +19,12 @@ $(function () {
             const auditHistory = result.auditHistory;
             // 生成左边列表流程
             const lefthtml = [];
-            lefthtml.push('<li class="list-group-item"><i class="fa fa fa-play-circle fa-rotate-90"></i> '+ materialAuditor.name +'  <small class="text-muted">'+ materialAuditor.role +'</small></li>');
+            lefthtml.push('<li class="list-group-item"><i class="fa fa fa-play-circle fa-rotate-90"></i> '+ materialAuditor.name +'  <small class="text-muted">'+ materialAuditor.role +'</small><span class="pull-right">原报</span></li>');
             for (const [index,a] of auditors.entries()) {
                 if (index+1 === auditors.length) {
-                    lefthtml.push('<li class="list-group-item"><i class="fa fa-stop-circle"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small></li>');
+                    lefthtml.push('<li class="list-group-item"><i class="fa fa-stop-circle"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small><span class="pull-right">终审</span></li>');
                 } else {
-                    lefthtml.push('<li class="list-group-item"><i class="fa fa-chevron-circle-down"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small></li>');
+                    lefthtml.push('<li class="list-group-item"><i class="fa fa-chevron-circle-down"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small><span class="pull-right">' + transFormToChinese(index+1) + '审</span></li>');
                 }
             }
             $('#auditor-list').html(lefthtml.join(''));
@@ -36,41 +36,48 @@ $(function () {
                 for (let iA = 0; iA < ah.length; iA++) {
                     if (iA === 0) {
                         righthtml.push('<li class="list-group-item">');
-                        righthtml.push('<span class="text-success pull-right">'+ (auditHistory.indexOf(ah) > 0 ? '重新' : '') +'上报</span>');
                         righthtml.push('<h5 class="card-title">');
-                        righthtml.push('<i class="fa fa-play-circle fa-rotate-90 text-success"></i> '+ materialAuditor.name +' <small class="text-muted">'+ materialAuditor.role +'</small></h5>');
-                        righthtml.push('<p class="card-text"><small class="text-muted">' + (ah[iA].begin_time ? moment(ah[iA].begin_time).format('YYYY-MM-DD') : '') + '</small></p></li>');
+                        righthtml.push('<i class="fa fa-play-circle fa-rotate-90 text-success"></i> '+ materialAuditor.name +' <small class="text-muted">'+ materialAuditor.role +'</small><span class="pull-right">原报</span></h5>');
+                        righthtml.push('<div class="ml-3">');
+                        righthtml.push('<span class="text-success"><small>' + (ah[iA].begin_time ? moment(ah[iA].begin_time).format('YYYY-MM-DD') : '') + '</small>'+ (auditHistory.indexOf(ah) > 0 ? '重新' : '') + '上报</span>');
+                        righthtml.push('</div></li>');
                         righthtml.push('<li class="list-group-item">');
+                        righthtml.push('<h5 class="card-title"><i class="fa '+ (iA === ah.length - 1 ? 'fa-stop-circle ' : 'fa-chevron-circle-down ') + auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small><span class="pull-right">' + (ah[iA].sort === ah[iA].max_sort ? '终' : transFormToChinese(ah[iA].sort)) + '审</span></h5>');
+                        righthtml.push('<div class="ml-3">');
                         if (ah[iA].status !== auditConst.status.uncheck) {
-                            righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +' pull-right">' + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + materialAuditor.name : '') + '</span>');
-                        }
-                        righthtml.push('<h5 class="card-title"><i class="fa '+ (iA === ah.length - 1 ? 'fa-stop-circle ' : 'fa-chevron-circle-down ') + auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small></h5>');
-                        if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) {
-                            righthtml.push('<p class="card-text mb-1">'+ ah[iA].opinion +'</p>');
-                            righthtml.push('<p class="card-text"><small class="text-muted">'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small></p>');
+                            let timeHtml = '';
+                            if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) {
+                                timeHtml = '<small>'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small> ';
+                            }
+                            righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +'">' + timeHtml + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + materialAuditor.name : '') + '</span>');
                         }
+                        righthtml.push('<p class="card-text">'+ (ah[iA].opinion !== null ? ah[iA].opinion : '') +'</p></div>');
                         righthtml.push('</li>');
                     } else if (iA === ah.length - 1) {
                         righthtml.push('<li class="list-group-item">');
+                        righthtml.push('<h5 class="card-title"><i class="fa fa-stop-circle '+ auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small><span class="pull-right">终审</span></h5>');
+                        righthtml.push('<div class="ml-3">');
                         if (ah[iA].status !== auditConst.status.uncheck) {
-                            righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +' pull-right">' + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + materialAuditor.name : '') + '</span>');
-                        }
-                        righthtml.push('<h5 class="card-title"><i class="fa fa-stop-circle '+ auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small></h5>');
-                        if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) {
-                            righthtml.push('<p class="card-text mb-1">'+ ah[iA].opinion +'</p>');
-                            righthtml.push('<p class="card-text"><small class="text-muted">'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small></p>');
+                            let timeHtml = '';
+                            if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) {
+                                timeHtml = '<small>'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small> ';
+                            }
+                            righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +'">' + timeHtml + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + materialAuditor.name : '') + '</span>');
                         }
+                        righthtml.push('<p class="card-text">'+ (ah[iA].opinion !== null ? ah[iA].opinion : '') +'</p></div>');
                         righthtml.push('</li>');
                     } else {
                         righthtml.push('<li class="list-group-item">');
+                        righthtml.push('<h5 class="card-title"><i class="fa '+ (iA === ah.length - 1 ? 'fa-stop-circle ' : 'fa-chevron-circle-down ') + auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small><span class="pull-right">' + (ah[iA].sort === ah[iA].max_sort ? '终' : transFormToChinese(ah[iA].sort)) + '审</span></h5>');
+                        righthtml.push('<div class="ml-3">');
                         if (ah[iA].status !== auditConst.status.uncheck) {
-                            righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +' pull-right">' + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + materialAuditor.name : '') + '</span>');
-                        }
-                        righthtml.push('<h5 class="card-title"><i class="fa fa-chevron-circle-down '+ auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small></h5>');
-                        if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) {
-                            righthtml.push('<p class="card-text mb-1">'+ ah[iA].opinion +'</p>');
-                            righthtml.push('<p class="card-text"><small class="text-muted">'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small></p>');
+                            let timeHtml = '';
+                            if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) {
+                                timeHtml = '<small>'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small> ';
+                            }
+                            righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +'">' + timeHtml + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + materialAuditor.name : '') + '</span>');
                         }
+                        righthtml.push('<p class="card-text">'+ (ah[iA].opinion !== null ? ah[iA].opinion : '') +'</p></div>');
                         righthtml.push('</li>');
                     }
                 }

+ 30 - 24
app/public/js/measure_stage.js

@@ -19,12 +19,12 @@ $('a[data-target="#sp-list" ]').on('click', function () {
        const auditHistory = result.auditHistory;
        // 生成左边列表流程
        const lefthtml = [];
-       lefthtml.push('<li class="list-group-item"><i class="fa fa fa-play-circle fa-rotate-90"></i> '+ stageAuditor.name +'  <small class="text-muted">'+ stageAuditor.role +'</small></li>');
+       lefthtml.push('<li class="list-group-item"><i class="fa fa fa-play-circle fa-rotate-90"></i> '+ stageAuditor.name +'  <small class="text-muted">'+ stageAuditor.role +'</small><span class="pull-right">原报</span></li>');
        for (const [index,a] of auditors.entries()) {
            if (index+1 === auditors.length) {
-               lefthtml.push('<li class="list-group-item"><i class="fa fa-stop-circle"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small></li>');
+               lefthtml.push('<li class="list-group-item"><i class="fa fa-stop-circle"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small><span class="pull-right">终审</span></li>');
            } else {
-               lefthtml.push('<li class="list-group-item"><i class="fa fa-chevron-circle-down"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small></li>');
+               lefthtml.push('<li class="list-group-item"><i class="fa fa-chevron-circle-down"></i> '+ a.name +'  <small class="text-muted">'+ a.role +'</small><span class="pull-right">' + transFormToChinese(index+1) + '审</span></li>');
            }
        }
        $('#auditor-list').html(lefthtml.join(''));
@@ -36,41 +36,47 @@ $('a[data-target="#sp-list" ]').on('click', function () {
            for (let iA = 0; iA < ah.length; iA++) {
                if (iA === 0) {
                    righthtml.push('<li class="list-group-item">');
-                   righthtml.push('<span class="text-success pull-right">'+ (auditHistory.indexOf(ah) > 0 ? '重新' : '') +'上报</span>');
                    righthtml.push('<h5 class="card-title">');
-                   righthtml.push('<i class="fa fa-play-circle fa-rotate-90 text-success"></i> '+ stageAuditor.name +' <small class="text-muted">'+ stageAuditor.role +'</small></h5>');
-                   righthtml.push('<p class="card-text"><small class="text-muted">' + (ah[iA].begin_time ? moment(ah[iA].begin_time).format('YYYY-MM-DD') : '') + '</small></p></li>');
+                   righthtml.push('<i class="fa fa-play-circle fa-rotate-90 text-success"></i> '+ stageAuditor.name +' <small class="text-muted">'+ stageAuditor.role +'</small><span class="pull-right">原报</span></h5>');
+                   righthtml.push('<div class="ml-3">');
+                   righthtml.push('<span class="text-success"><small>' + (ah[iA].begin_time ? moment(ah[iA].begin_time).format('YYYY-MM-DD') : '') + '</small> '+ (auditHistory.indexOf(ah) > 0 ? '重新' : '') + '上报</span></div></li>');
                    righthtml.push('<li class="list-group-item">');
+                   righthtml.push('<h5 class="card-title"><i class="fa '+ (iA === ah.length - 1 ? 'fa-stop-circle ' : 'fa-chevron-circle-down ') + auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small><span class="pull-right">' + (ah[iA].sort === ah[iA].max_sort ? '终' : transFormToChinese(ah[iA].sort)) + '审</span></h5>');
+                   righthtml.push('<div class="ml-3">');
                    if (ah[iA].status !== auditConst.status.uncheck) {
-                       righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +' pull-right">' + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + stageAuditor.name : '') + '</span>');
-                   }
-                   righthtml.push('<h5 class="card-title"><i class="fa '+ (iA === ah.length - 1 ? 'fa-stop-circle ' : 'fa-chevron-circle-down ') + auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small></h5>');
-                   if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo || ah[iA].status === auditConst.status.checkNoPre) {
-                       righthtml.push('<p class="card-text mb-1">'+ ah[iA].opinion +'</p>');
-                       righthtml.push('<p class="card-text"><small class="text-muted">'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small></p>');
+                       let timeHtml = '';
+                       if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo || ah[iA].status === auditConst.status.checkNoPre) {
+                           timeHtml = '<small>'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small> ';
+                       }
+                       righthtml.push('<span class="' + auditConst.statusClass[ah[iA].status] +'">'+ timeHtml + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + stageAuditor.name : '') + '</span>');
                    }
+                   righthtml.push('<p class="card-text">'+ (ah[iA].opinion !== null ? ah[iA].opinion : '') +'</p></div>');
                    righthtml.push('</li>');
                } else if (iA === ah.length - 1) {
                    righthtml.push('<li class="list-group-item">');
+                   righthtml.push('<h5 class="card-title"><i class="fa fa-stop-circle '+ auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small><span class="pull-right">终审</span></h5>');
+                   righthtml.push('<div class="ml-3">');
                    if (ah[iA].status !== auditConst.status.uncheck) {
-                       righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +' pull-right">' + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + stageAuditor.name : '') + '</span>');
-                   }
-                   righthtml.push('<h5 class="card-title"><i class="fa fa-stop-circle '+ auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small></h5>');
-                   if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo || ah[iA].status === auditConst.status.checkNoPre) {
-                       righthtml.push('<p class="card-text mb-1">'+ ah[iA].opinion +'</p>');
-                       righthtml.push('<p class="card-text"><small class="text-muted">'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small></p>');
+                       let timeHtml = '';
+                       if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo || ah[iA].status === auditConst.status.checkNoPre) {
+                           timeHtml = '<small>'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small> ';
+                       }
+                       righthtml.push('<span class="' + auditConst.statusClass[ah[iA].status] +'">' + timeHtml + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + stageAuditor.name : '') + '</span>');
                    }
+                   righthtml.push('<p class="card-text">'+ (ah[iA].opinion !== null ? ah[iA].opinion : '') +'</p></div>');
                    righthtml.push('</li>');
                } else {
                    righthtml.push('<li class="list-group-item">');
+                   righthtml.push('<h5 class="card-title"><i class="fa '+ (iA === ah.length - 1 ? 'fa-stop-circle ' : 'fa-chevron-circle-down ') + auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small><span class="pull-right">' + (ah[iA].sort === ah[iA].max_sort ? '终' : transFormToChinese(ah[iA].sort)) + '审</span></h5>');
+                   righthtml.push('<div class="ml-3">');
                    if (ah[iA].status !== auditConst.status.uncheck) {
-                       righthtml.push('<span class="'+ auditConst.statusClass[ah[iA].status] +' pull-right">' + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + stageAuditor.name : '') + '</span>');
-                   }
-                   righthtml.push('<h5 class="card-title"><i class="fa fa-chevron-circle-down '+ auditConst.statusClass[ah[iA].status] +'"></i> '+ ah[iA].name +' <small class="text-muted">'+ ah[iA].role +'</small></h5>');
-                   if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo || ah[iA].status === auditConst.status.checkNoPre) {
-                       righthtml.push('<p class="card-text mb-1">'+ ah[iA].opinion +'</p>');
-                       righthtml.push('<p class="card-text"><small class="text-muted">'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small></p>');
+                       let timeHtml = '';
+                       if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo || ah[iA].status === auditConst.status.checkNoPre) {
+                           timeHtml = '<small>'+ (ah[iA].end_time ? moment(ah[iA].end_time).format('YYYY-MM-DD') : '') +'</small> ';
+                       }
+                       righthtml.push('<span class="' + auditConst.statusClass[ah[iA].status] +'">'+ timeHtml + auditConst.statusString[ah[iA].status] + (ah[iA].status === auditConst.status.checkNo ? ' ' + stageAuditor.name : '') + '</span>');
                    }
+                   righthtml.push('<p class="card-text">'+ (ah[iA].opinion !== null ? ah[iA].opinion : '') +'</p></div>');
                    righthtml.push('</li>');
                }
            }

+ 19 - 1
app/public/js/number-precision.js

@@ -148,4 +148,22 @@ var NP = (function (exports) {
 
     return exports;
 
-}({}));
+}({}));
+
+function transFormToChinese(num) {
+    const changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
+    const unit = ["", "十", "百", "千", "万"];
+    num = parseInt(num);
+    let getWan = (temp) => {
+        let strArr = temp.toString().split("").reverse();
+        let newNum = "";
+        for (var i = 0; i < strArr.length; i++) {
+            newNum = (i == 0 && strArr[i] == 0 ? "" : (i > 0 && strArr[i] == 0 && strArr[i - 1] == 0 ? "" : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i]))) + newNum;
+        }
+        return newNum;
+    }
+    let overWan = Math.floor(num / 10000);
+    let noWan = num % 10000;
+    if (noWan.toString().length < 4) noWan = "0" + noWan;
+    return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(num);
+}

+ 72 - 23
app/public/js/revise.js

@@ -14,6 +14,7 @@ function transExpr(expr) {
 }
 
 $(document).ready(() => {
+    let stdXmj, stdGcl, searchLedger;
     autoFlashHeight();
     // 初始化spread
     const billsSpread = SpreadJsObj.createNewSpread($('#bills-spread')[0]);
@@ -23,23 +24,6 @@ $(document).ready(() => {
     const posSheet = posSpread.getActiveSheet();
     SpreadJsObj.initSheet(posSheet, posSpreadSetting);
 
-    $.subMenu({
-        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
-        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        key: 'revise.info.memu.1.0.0',
-        callback: function (info) {
-            if (info.mini) {
-                $('.panel-title').addClass('fluid');
-                $('#sub-menu').removeClass('panel-sidebar');
-            } else {
-                $('.panel-title').removeClass('fluid');
-                $('#sub-menu').addClass('panel-sidebar');
-            }
-            autoFlashHeight();
-            billsSpread.refresh();
-            posSpread.refresh();
-        }
-    });
     const posSearch = $.posSearch({selector: '#pos-search', searchSpread: posSpread});
 
     // 初始化 节点树结构
@@ -117,15 +101,34 @@ $(document).ready(() => {
                     obj.addClass('disabled');
                 }
             };
+            const invalidAll = function () {
+                setObjEnable($('a[type=add]'), false);
+                setObjEnable($('a[type=delete]'), false);
+                setObjEnable($('a[type=up-move]'), false);
+                setObjEnable($('a[type=down-move]'), false);
+                setObjEnable($('a[type=up-level]'), false);
+                setObjEnable($('a[type=down-level]'), false);
+            };
             const sel = selection ? selection[0] : sheet.getSelections()[0];
             const row = sel ? sel.row : -1;
             const tree = sheet.zh_tree;
-            if (!tree) return;
+            if (!tree) {
+                invalidAll();
+                return;
+            }
             const first = sheet.zh_tree.nodes[row];
+            if (!first) {
+                invalidAll();
+                return;
+            }
             let last = first, sameParent = true, nodeUsed = first.used;
-            if (sel.rowCount > 1) {
+            if (sel.rowCount > 1 && first) {
                 for (let r = 1; r < sel.rowCount; r++) {
                     const rNode = tree.nodes[sel.row + r];
+                    if (!rNode) {
+                        sameParent = false;
+                        break;
+                    }
                     nodeUsed = nodeUsed || rNode.used;
                     if (rNode.level > first.level) continue;
                     if ((rNode.level < first.level) || (rNode.level === first.level && rNode.pid !== first.pid)) {
@@ -138,7 +141,7 @@ $(document).ready(() => {
             const preNode = tree.getPreSiblingNode(first);
             const valid = !sheet.zh_setting.readOnly;
 
-            setObjEnable($('a[type=insert]'), valid && first && first.level > 1);
+            setObjEnable($('a[type=add]'), valid && first && first.level > 1);
             setObjEnable($('a[type=delete]'), valid && first && sameParent && first.level > 1 && !nodeUsed);
             setObjEnable($('a[type=up-move]'), valid && first && sameParent && first.level > 1 && preNode);
             setObjEnable($('a[type=down-move]'), valid && first && sameParent && first.level > 1 && !tree.isLastSibling(last));
@@ -1062,8 +1065,15 @@ $(document).ready(() => {
                     }, function (result) {
                         const refreshNode = mainTree.loadPostData(result);
                         billsTreeSpreadObj.refreshTree(mainSheet, refreshNode);
-                        if (sel && refreshNode.create[0]) {
-                            mainSheet.setSelection(mainTree.nodes.indexOf(refreshNode.create[0]), sel.col, sel.rowCount, sel.colCount);
+                        if (sel) {
+                            if (refreshNode.create && refreshNode.create.length > 0) {
+                                mainSheet.setSelection(refreshNode.create[refreshNode.create.length - 1].index, sel.col, sel.rowCount, sel.colCount);
+                            } else {
+                                const node = _.find(mainTree.nodes, {code: stdNode.code, name: stdNode.name});
+                                if (node) {
+                                    mainSheet.setSelection(mainTree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
+                                }
+                            }
                         }
                         billsTreeSpreadObj.refreshOperationValid(mainSheet);
                     });
@@ -1324,7 +1334,6 @@ $(document).ready(() => {
             return result;
         }
     }
-    let stdXmj, stdGcl, searchLedger;
     const dealBills = new DealBills('#deal-bills-spread', {
         cols: [
             {title: '清单编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
@@ -1341,6 +1350,7 @@ $(document).ready(() => {
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
     });
+
     $.divResizer({
         select: '#revise-right-spr',
         callback: function () {
@@ -1354,8 +1364,47 @@ $(document).ready(() => {
             if (stdGcl) {
                 stdGcl.spread.refresh();
             }
+            if (dealBills) {
+                dealBills.spread.refresh();
+            }
+            if (searchLedger) {
+                searchLedger.spread.refresh();
+            }
         }
     });
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+            billsSpread.refresh();
+            if (posSpread) {
+                posSpread.refresh();
+            }
+            if (stdXmj) {
+                stdXmj.spread.refresh();
+            }
+            if (stdGcl) {
+                stdGcl.spread.refresh();
+            }
+            if (dealBills) {
+                dealBills.spread.refresh();
+            }
+            if (searchLedger) {
+                searchLedger.spread.refresh();
+            }
+        }
+    });
+
     const showSideTools = function (show) {
         const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
         if (show) {

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

@@ -24,7 +24,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        key: 'revise.history.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 7 - 0
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -326,6 +326,13 @@ const SpreadJsObj = {
         sheet.getRange(0, 0, sheet.getRowCount(), sheet.getColumnCount()).locked(setting.readOnly);
         this.endMassOperation(sheet);
     },
+    reLoadSheetHeader: function (sheet) {
+        if (sheet.zh_setting) {
+            this.beginMassOperation(sheet);
+            this._initSheetHeader(sheet);
+            this.endMassOperation(sheet);
+        }
+    },
     _loadRowData: function (sheet, data, row) {
         // 单元格重新写入数据
         if (!data) { return }

+ 799 - 34
app/public/js/stage.js

@@ -89,13 +89,6 @@ function initTreeColSettingEvents(setting) {
         }
     }
 }
-function needCheckDetail() {
-    stage.check_detail = true;
-    $('#check_point').show();
-    $('#sub-sp-btn').attr('data-target', '#sub-sp3');
-    $('#sp-done-btn').attr('data-target', '#sub-sp3');
-    $('#sp-list2-btn').attr('data-target', '#sub-sp3');
-}
 
 // 生成所有附件列表
 function getAllList(currPageNum = 1) {
@@ -128,6 +121,7 @@ function getNodeList(node) {
 }
 
 $(document).ready(() => {
+    let detail, searchLedger;
     // 界面布局
     autoFlashHeight();
     // 初始化 台账树结构 数据结构
@@ -262,7 +256,7 @@ $(document).ready(() => {
                     const sel = sheet.getSelections()[0];
                     const sortData = SpreadJsObj.getSortData(sheet);
                     // 仅本期计量可删除
-                    if (sel.col === 5 || sel.colCount === 1) {
+                    if (sel.col === 5 && sel.colCount === 1) {
                         const col = sheet.zh_setting.cols[sel.col];
                         for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow++) {
                             const data = sortData[iRow];
@@ -318,7 +312,11 @@ $(document).ready(() => {
                     const nodes = stageTree.loadPostStageData(result.bills);
                     stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
                     stagePosSpreadObj.loadCurPosData();
-                    needCheckDetail();
+                    if (detail) {
+                        detail.loadStageChangeUpdateData(result);
+                    } else {
+                        stageIm.loadUpdateChangeData(result)
+                    }
                     self.obj.modal('hide');
                 });
             })
@@ -458,15 +456,8 @@ $(document).ready(() => {
         return data && data.end_contract_qty > data.quantity ? '#f8d7da' : defaultColor;
     };
     SpreadJsObj.initSheet(slSpread.getActiveSheet(), ledgerSpreadSetting);
-
-    stageTree.loadDatas(ledgerData);
-    // stageTree.loadCurStageData(curStageData);
-    // stageTree.loadPreStageData(preStageData);
-    // 根据设置 计算 台账树结构
-    treeCalc.calculateAll(stageTree);
-    // 绘制界面
-    SpreadJsObj.loadSheetData(slSpread.getActiveSheet(), 'tree', stageTree);
-    SpreadJsObj.loadTopAndSelect(slSpread.getActiveSheet(), ckBillsSpread);
+    slSpread.getActiveSheet().frozenColumnCount(5);
+    slSpread.getActiveSheet().options.frozenlineColor = '#93b5e4';
 
     //初始化所有附件列表
     getAllList();
@@ -585,9 +576,16 @@ $(document).ready(() => {
                 }
 
                 postData(window.location.href + '/update', {bills: updateData}, function (data) {
+                    // tag update
                     const nodes = stageTree.loadPostStageData(data);
                     stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
-                    needCheckDetail();
+                    if (detail) {
+                        detail.loadStageLedgerUpdateData(data);
+                    } else {
+                        stageIm.loadUpdateLedgerData(data);
+                    }
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
                 });
             }
         },
@@ -595,7 +593,10 @@ $(document).ready(() => {
             if (!info.oldSelections[0] || info.newSelections[0].row !== info.oldSelections[0].row) {
                 stagePosSpreadObj.loadCurPosData();
                 SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
-                posSearch.search();
+                if (posSearch) {
+
+                    posSearch.search();
+                }
             }
             SpreadJsObj.saveTopAndSelect(info.sheet, ckBillsSpread);
             stageTreeSpreadObj.loadExprToInput(info.sheet);
@@ -608,7 +609,8 @@ $(document).ready(() => {
                 const sel = sheet.getSelections()[0];
                 const validCols = [];
                 for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
-                    if (!sheet.zh_setting.cols[iCol].readOnly) {
+                    const colSetting = sheet.zh_setting.cols[iCol];
+                    if (!colSetting.readOnly && colSetting.field !== 'qc_qty') {
                         validCols.push(iCol);
                     }
                 }
@@ -657,7 +659,11 @@ $(document).ready(() => {
                     postData(window.location.href + '/update', {bills: bills}, function (result) {
                         const nodes = stageTree.loadPostStageData(result);
                         stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
-                        needCheckDetail();
+                        if (detail) {
+                            detail.loadStageLedgerUpdateData(result);
+                        } else {
+                            stageIm.loadUpdateLedgerData(result);
+                        }
                     });
                 }
             }
@@ -760,7 +766,14 @@ $(document).ready(() => {
                     postData(window.location.href + '/update', {bills: updateData}, function (data) {
                         const nodes = stageTree.loadPostStageData(data);
                         stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes.concat(filterNodes));
-                        needCheckDetail();
+                        if (detail) {
+                            detail.loadStageLedgerUpdateData(data);
+                        } else {
+                            stageIm.loadUpdateLedgerData(data);
+                        }
+                    }, function () {
+                        // todo
+                        //stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), filterNodes);
                     });
                 } else {
                     stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), filterNodes);
@@ -804,7 +817,11 @@ $(document).ready(() => {
                 const nodes = stageTree.loadPostStageData(result.ledger);
                 stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
                 stagePosSpreadObj.loadCurPosData();
-                needCheckDetail();
+                if (detail) {
+                    detail.loadStagePosUpdateData(result);
+                } else {
+                    stageIm.loadUpdatePosData(result);
+                }
                 toastr.success('已计量' + data.updateData.length + '条');
             }, function () {
                 stagePosSpreadObj.loadCurPosData();
@@ -1092,7 +1109,11 @@ $(document).ready(() => {
                     const refreshData = stageTree.loadPostStageData(result.ledger);
                     stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), refreshData);
                     stagePosSpreadObj.loadCurPosData();
-                    needCheckDetail();
+                    if (detail) {
+                        detail.loadStagePosUpdateData(result);
+                    } else {
+                        stageIm.loadUpdatePosData(result);
+                    }
                 }, function () {
                     stagePosSpreadObj.loadCurPosData();
                 });
@@ -1207,7 +1228,11 @@ $(document).ready(() => {
                     const nodes = stageTree.loadPostStageData(result.ledger);
                     stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
                     stagePosSpreadObj.loadCurPosData();
-                    needCheckDetail();
+                    if (detail) {
+                        detail.loadStagePosUpdateData(result);
+                    } else {
+                        stageIm.loadUpdatePosData(result);
+                    }
                 }, function () {
                     stagePosSpreadObj.loadCurPosData();
                 });
@@ -1221,7 +1246,8 @@ $(document).ready(() => {
                 const sel = sheet.getSelections()[0];
                 const validCols = [];
                 for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
-                    if (!sheet.zh_setting.cols[iCol].readOnly) {
+                    const colSetting = sheet.zh_setting.cols[iCol];
+                    if (!colSetting.readOnly && colSetting.field !== 'qc_qty') {
                         validCols.push(iCol);
                     }
                 }
@@ -1252,7 +1278,11 @@ $(document).ready(() => {
                         }
                         const nodes = stageTree.loadPostStageData(result.ledger);
                         stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
-                        needCheckDetail();
+                        if (detail) {
+                            detail.loadStagePosUpdateData(result);
+                        } else {
+                            stageIm.loadUpdatePosData(result);
+                        }
                         // todo 只加载改变项
                         stagePosSpreadObj.loadCurPosData();
                     });
@@ -1276,7 +1306,11 @@ $(document).ready(() => {
                         const refreshData = stageTree.loadPostStageData(result.ledger);
                         stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), refreshData);
                         stagePosSpreadObj.loadCurPosData();
-                        needCheckDetail();
+                        if (detail) {
+                            detail.loadStagePosUpdateData(result);
+                        } else {
+                            stageIm.loadUpdatePosData(result);
+                        }
                     });
                 }
             }
@@ -1298,13 +1332,23 @@ $(document).ready(() => {
 
     // 加载计量单元数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
     console.time('loadPosFromServer');
-    postData(window.location.pathname + '/pos', null, function (result) {
+    postData(window.location.pathname + '/load', null, function (result) {
         console.timeEnd('loadPosFromServer');
-        console.log('pos: ' + result.length);
-        stagePos.loadDatas(result);
+        // 加载树结构
+        stageTree.loadDatas(result.ledgerData);
+        // stageTree.loadCurStageData(curStageData);
+        // stageTree.loadPreStageData(preStageData);
+        treeCalc.calculateAll(stageTree);
+        SpreadJsObj.loadSheetData(slSpread.getActiveSheet(), 'tree', stageTree);
+        SpreadJsObj.loadTopAndSelect(slSpread.getActiveSheet(), ckBillsSpread);
+        // 加载部位明细
+        stagePos.loadDatas(result.posData);
         stagePos.calculateAll();
         stagePosSpreadObj.loadCurPosData();
         SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
+        // 加载中间计量
+        stageIm.init(stage, imType);
+        stageIm.loadData(result.ledgerData, result.posData, result.detailData, result.changeData);
     }, null, true);
     spSpread.bind(spreadNS.Events.EditEnded, stagePosSpreadObj.editEnded);
     spSpread.bind(spreadNS.Events.ClipboardPasting, stagePosSpreadObj.clipboardPasting);
@@ -1411,7 +1455,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');
@@ -1423,6 +1468,12 @@ $(document).ready(() => {
             autoFlashHeight();
             slSpread.refresh();
             spSpread.refresh();
+            if (searchLedger) {
+                searchLedger.spread.refresh();
+            }
+            if (detail) {
+                detail.spread.refresh();
+            }
         }
     });
 
@@ -1590,7 +1641,6 @@ $(document).ready(() => {
             SpreadJsObj.loadSheetData(this.spread.getActiveSheet(), 'data', this.searchResult);
         }
     }
-    let searchLedger;
 
     const posSearch = (function () {
         let resultArr = [];
@@ -1734,8 +1784,717 @@ $(document).ready(() => {
             if (searchLedger) {
                 searchLedger.spread.refresh();
             }
+            if (detail) {
+                detail.spread.refresh();
+            }
         }
     });
+
+    class Detail {
+        constructor (obj) {
+            const self = this;
+            this.spreadSetting = {
+                cols: [
+                    {title: '编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
+                    {title: '中间计量表号', colSpan: '1', rowSpan: '1', field: 'im_code', hAlign: 0, width: 150, formatter: '@', readOnly: true},
+                    {title: '交工证书/凭证号', colSpan: '1', rowSpan: '1', field: 'doc_code', hAlign: 0, width: 180, formatter: '@'},
+                    {
+                        title: stage.im_type === imType.tz.value ? '本期计量金额' : '本期计量数量',
+                        colSpan: '1', rowSpan: '1', field: 'jl', hAlign: 2, width: 220, formatter: '@', readOnly: true
+                    },
+                ],
+                headRows: 1,
+                emptyRows: 0,
+                headRowHeight: [32],
+                defaultRowHeight: 21,
+                headerFont: '12px 微软雅黑',
+                font: '12px 微软雅黑',
+                readOnly: readOnly,
+            };
+            this.spread = SpreadJsObj.createNewSpread(obj[0]);
+            this.sheet = this.spread.getActiveSheet();
+            this.spread.options.allowUserDragFill = true;
+            this.spread.options.defaultDragFillType = spreadNS.Fill.AutoFillType.fillSeries;
+            SpreadJsObj.initSheet(this.spread.getActiveSheet(), this.spreadSetting);
+
+            this.detailObj = {
+                selectionChanged: function (e, info) {
+                    self.reLoadDetailData();
+                },
+                editEnded: function(e, info) {
+                    if (info.sheet.zh_setting) {
+                        const col = info.sheet.zh_setting.cols[info.col];
+                        if (col.field !== 'doc_code') {
+                            SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                            return;
+                        }
+                        const data = SpreadJsObj.getSelectObject(info.sheet);
+                        if (data) {
+                            const updateData = {lid: data.lid};
+                            if (data.uuid) {
+                                updateData.uuid = data.uuid;
+                            } else {
+                                updateData.code = data.code;
+                                updateData.name = data.name;
+                                updateData.unit = data.unit;
+                                updateData.unit_price = data.unit_price;
+                            }
+                            updateData.doc_code = info.editingText;
+                            postData(window.location.pathname + '/detail/save', updateData, function (result) {
+                                stageIm.loadUpdateDetailData(result);
+                                SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                            }, function () {
+                                SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                            });
+                        } else {
+                            SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        }
+                    }
+                },
+                clipboardPasted: function (e, info) {
+                    if (info.sheet.zh_setting && info.sheet.zh_data) {
+                        const col = info.sheet.zh_setting.cols[info.cellRange.col];
+                        if (info.cellRange.colCount > 1) {
+                            toastr.warning('请勿同时复制粘贴多列数据');
+                            SpreadJsObj.reLoadSheetData(paySpread.getActiveSheet());
+                            return;
+                        }
+                        if (col.field !== 'doc_code') {
+                            SpreadJsObj.reLoadSheetData(paySpread.getActiveSheet());
+                            return;
+                        }
+
+                        const datas = [];
+                        for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                            const curRow = info.cellRange.row + iRow;
+                            const data = info.sheet.zh_data[curRow];
+                            if (data) {
+                                const updateData = {lid: data.lid};
+                                if (data.uuid) {
+                                    updateData.uuid = data.uuid;
+                                } else {
+                                    updateData.code = data.code;
+                                    updateData.name = data.name;
+                                    updateData.unit = data.unit;
+                                    updateData.unit_price = data.unit_price;
+                                }
+                                updateData.doc_code = info.sheet.getText(curRow, info.cellRange.col).replace('\n', '');
+                                datas.push(updateData);
+                            }
+                        }
+                        if (datas.length > 0) {
+                            postData(window.location.pathname + '/detail/save', datas, function (result) {
+                                stageIm.loadUpdateDetailData(result);
+                                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                            }, function () {
+                                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                            })
+                        }
+                    }
+                },
+                deletePress: function (sheet) {
+                    if (sheet.zh_setting) {
+                        const datas = [];
+                        const sel = sheet.getSelections()[0];
+                        for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
+                            const col = sheet.zh_setting.cols[iCol];
+                            for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow++) {
+                                const data = sheet.zh_data[iRow];
+                                if (col.field === 'doc_code') {
+                                    const updateData = {lid: data.lid};
+                                    if (data.uuid) {
+                                        updateData.uuid = data.uuid;
+                                        updateData.doc_code = null;
+                                        datas.push(updateData);
+                                    }
+                                }
+                            }
+                        }
+                        if (datas.length > 0) {
+                            postData(window.location.pathname + '/detail/save', datas, function (result) {
+                                stageIm.loadUpdateDetailData(result);
+                                SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
+                            }, function () {
+                                SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
+                            });
+                        }
+                    }
+                },
+                dragFillBlock: function (e, info) {
+                    info.cancel = true;
+                    if (!info.sheet.zh_setting || !info.sheet.zh_data) return;
+                    const sel = info.sheet.getSelections()[0];
+                    const col = info.sheet.zh_setting.cols[info.fillRange.col];
+                    if (info.fillRange.colCount > 1 || !sel || col.field !== 'doc_code') return;
+                    const text = info.sheet.getText(sel.row + sel.rowCount - 1, sel.col);
+                    if (text === '') return;
+
+                    const regRst = /(\d+)$/g.exec(text), datas = [];
+                    for (let iRow = 0; iRow < info.fillRange.rowCount; iRow++) {
+                        const curRow = info.fillRange.row + iRow;
+                        const data = info.sheet.zh_data[curRow];
+                        if (data) {
+                            const updateData = {lid: data.lid};
+                            if (data.uuid) {
+                                updateData.uuid = data.uuid;
+                            } else {
+                                updateData.code = data.code;
+                                updateData.name = data.name;
+                                updateData.unit = data.unit;
+                                updateData.unit_price = data.unit_price;
+                            }
+                            if (regRst) {
+                                updateData.doc_code = text.substr(0, regRst.index) + (parseInt(regRst[0]) + iRow + 1);
+                            } else {
+                                updateData.doc_code = text.replace('\n', '');
+                            }
+                            datas.push(updateData);
+                        }
+                    }
+                    if (datas.length > 0) {
+                        postData(window.location.pathname + '/detail/save', datas, function (result) {
+                            stageIm.loadUpdateDetailData(result);
+                            SpreadJsObj.reLoadRowData(info.sheet, info.fillRange.row, info.fillRange.rowCount);
+                        }, function () {
+                            SpreadJsObj.reLoadRowData(info.sheet, info.fillRange.row, info.fillRange.rowCount);
+                        })
+                    }
+                },
+            };
+
+            this.spread.bind(spreadNS.Events.SelectionChanged, this.detailObj.selectionChanged);
+            if (!readOnly) {
+                this.spread.bind(spreadNS.Events.EditEnded, this.detailObj.editEnded);
+                this.spread.bind(spreadNS.Events.ClipboardPasted, this.detailObj.clipboardPasted);
+                this.spread.bind(spreadNS.Events.DragFillBlock, this.detailObj.dragFillBlock);
+                SpreadJsObj.addDeleteBind(this.spread, this.detailObj.deletePress);
+            }
+
+            this._initImTypeSetRela();
+            this._initModifyDetail();
+            // 草图相关
+            this._initImageRela();
+            this.reBuildImData();
+        }
+        _initImTypeSetRela() {
+            const self = this;
+            const gatherConfirmPopover = {
+                reBind: function (obj, eventName, fun) {
+                    obj.unbind(eventName);
+                    obj.bind(eventName, fun);
+                },
+                check: function (pos, hint, okCallback) {
+                    const confirmObj = $('#gather-confirm'), hintObj = $('#gather-confirm-hint');
+                    const okObj = $('#gather-confirm-ok'), cancelObj = $('#gather-confirm-cancel');
+                    this.reBind(cancelObj, 'click', function () {
+                        confirmObj.hide();
+                    });
+                    this.reBind(okObj, 'click', function () {
+                        okCallback();
+                        confirmObj.hide();
+                    });
+                    hintObj.text(hint);
+                    confirmObj.css("top", pos.y).css("left", pos.x).show();
+                }
+            };
+            this.gsTree = stageIm.getGsTree();
+
+            if (stage.im_type === imType.tz.value) {
+                $('#type-title-contract').text('本期合同计量金额');
+                $('#type-title-qc').text('本期变更计量金额');
+            } else {
+                $('#type-title-contract').text('本期合同计量数量');
+                $('#type-title-qc').text('本期变更计量数量');
+            }
+
+            // 选择中间计量模式
+            $('div[name="im-type"]').click(function () {
+                function chooseType(obj) {
+                    obj.style.cursor = 'default';
+                    $(obj).children().addClass('text-primary');
+                    $('h5', obj).prepend('<i class="fa fa-check pull-right"></i>');
+                }
+                function validType(obj) {
+                    obj.style.cursor = 'pointer';
+                    $(obj).children().removeClass('text-primary');
+                    $('i', obj).remove();
+                }
+                if (this.style.cursor === 'pointer') {
+                    const typeArr = $('div[name="im-type"]');
+                    for (const t of typeArr) {
+                        if ($(t).attr('im-type') === $(this).attr('im-type')) {
+                            chooseType(t);
+                        } else {
+                            validType(t)
+                        }
+                    }
+                }
+            });
+            $('#choose').on('show.bs.modal', function () {
+                function chooseType(obj) {
+                    obj.style.cursor = 'default';
+                    $(obj).children().addClass('text-primary');
+                    $('i', obj).remove();
+                    $('h5', obj).prepend('<i class="fa fa-check pull-right"></i>');
+                }
+                function validType(obj) {
+                    obj.style.cursor = 'pointer';
+                    $(obj).children().removeClass('text-primary');
+                    $('i', obj).remove();
+                }
+                $('#im-pre').val(stage.im_pre ? stage.im_pre : '');
+                const typeArr = $('div[name="im-type"]');
+                for (const t of typeArr) {
+                    if (parseInt($(t).attr('im-type')) === stage.im_type) {
+                        chooseType(t);
+                    } else {
+                        validType(t)
+                    }
+                }
+            });
+            // 提交 中间计量模式
+            $('#choose-ok').click(() => {
+                const chooseType = _.find($('div[name="im-type"]', '#im-type'), function (it) {
+                    return it.style.cursor !== 'pointer';
+                });
+                const data = {
+                    im_type: parseInt($(chooseType).attr('im-type')),
+                    im_pre: $('#im-pre').val(),
+                };
+                postData(window.location.pathname + '/detail/build', data, function (result) {
+                    stage.im_type = data.im_type;
+                    stage.im_pre = data.im_pre;
+                    if (stage.im_type === imType.tz.value) {
+                        const jlCol = self.spreadSetting.cols.find(function (x) {return x.field === 'jl'});
+                        jlCol.title = '本期计量金额';
+                        SpreadJsObj.reLoadSheetHeader(self.sheet);
+                        $('#type-title-contract').text('本期合同计量金额');
+                        $('#type-title-qc').text('本期变更计量金额');
+                    } else {
+                        const jlCol = self.spreadSetting.cols.find(function (x) {return x.field === 'jl'});
+                        jlCol.title = '本期计量金额';
+                        SpreadJsObj.reLoadSheetHeader(self.sheet);
+                        $('#type-title-contract').text('本期合同计量数量');
+                        $('#type-title-qc').text('本期变更计量数量');
+                    }
+                    // 加载生成数据
+                    self.reBuildImData();
+                    $('#choose').modal('hide');
+                });
+            });
+            // 显示树结构信息
+            $('#choose2').on('shown.bs.modal', function () {
+                if (!self.gsSpread) {
+                    self.gsSpread = SpreadJsObj.createNewSpread($('#im-gather-spread')[0]);
+                    SpreadJsObj.initSheet(self.gsSpread.getActiveSheet(), {
+                        cols: [
+                            {title: '计量\n汇总', colSpan: '1', rowSpan: '1', field: 'check', hAlign: 1, width: 50, formatter: '@', readOnly: true, cellType: 'checkbox'},
+                            {title: '项目节编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 150, formatter: '@', readOnly: true, cellType: 'tree'},
+                            {title: '清单编号', colSpan: '1', rowSpan: '1', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
+                            {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 230, formatter: '@', readOnly: true},
+                            {title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
+                        ],
+                        headRows: 1,
+                        emptyRows: 0,
+                        headRowHeight: [32],
+                        defaultRowHeight: 21,
+                        headerFont: '12px 微软雅黑',
+                        font: '12px 微软雅黑',
+                    });
+                    self.gsSpread.bind(spreadNS.Events.ButtonClicked, function (e, info) {
+                        function checkParent(node) {
+                            const parent = self.gsTree.getParent(node);
+                            if (parent) {
+                                return parent.check ? parent.check : checkParent(parent);
+                            } else {
+                                return false;
+                            }
+                        }
+
+                        function checkChildren(node) {
+                            for (const child of node.children) {
+                                if (child.check) {
+                                    return true;
+                                } else if (checkChildren(child)) {
+                                    return true;
+                                }
+                            }
+                            return false;
+                        }
+
+                        if (!$('#im-gather-check')[0].checked) { return; }
+
+                        const sheet = info.sheet, cellType = sheet.getCellType(info.row, info.col);
+                        if (cellType instanceof  spreadNS.CellTypes.CheckBox) {
+                            if (sheet.isEditing()) {
+                                sheet.endEdit(true);
+                            }
+                        }
+                        if (info.sheet.zh_setting) {
+                            const col = info.sheet.zh_setting.cols[info.col];
+                            if (col.field !== 'check') {
+                                return;
+                            }
+
+                            const sortData = info.sheet.zh_dataType === 'tree' ? info.sheet.zh_tree.nodes : info.sheet.zh_data;
+                            const node = sortData[info.row];
+                            if (!node.check) {
+                                if (checkParent(node)) {
+                                    const rect = info.sheet.getCellRect(info.row, info.col);
+                                    gatherConfirmPopover.check({
+                                        x: rect.x + rect.width / 2 + 25,
+                                        y: rect.y + rect.height / 2 + 3,
+                                    }, '父项已勾选,继续将取消父项勾选。', function () {
+                                        node.check = true;
+                                        const parents = self.gsTree.getFullPathNodes(self.gsTree.getParent(node).full_path);
+                                        const rows = [self.gsTree.nodes.indexOf(node)];
+                                        for (const p of parents) {
+                                            if (p.check) {
+                                                p.check = false;
+                                                rows.push(self.gsTree.nodes.indexOf(p));
+                                            }
+                                        }
+                                        SpreadJsObj.reLoadRowsData(info.sheet, rows);
+                                    });
+                                } else if (checkChildren(node)) {
+                                    const rect = info.sheet.getCellRect(info.row, info.col);
+                                    gatherConfirmPopover.check({
+                                        x: rect.x + rect.width / 2 + 25,
+                                        y: rect.y + rect.height / 2 + 3,
+                                    }, '子项已勾选,继续将取消子项勾选。', function () {
+                                        node.check = true;
+                                        const posterity = self.gsTree.getPosterity(node);
+                                        const rows = [self.gsTree.nodes.indexOf(node)];
+                                        for (const p of posterity) {
+                                            if (p.check) {
+                                                rows.push(self.gsTree.nodes.indexOf(p));
+                                                p.check = false;
+                                            }
+                                        }
+                                        SpreadJsObj.reLoadRowsData(info.sheet, rows);
+                                    });
+                                } else {
+                                    node.check = true;
+                                    SpreadJsObj.reLoadRowsData(info.sheet, [self.gsTree.nodes.indexOf(node)]);
+                                }
+                            } else {
+                                node.check = false;
+                                SpreadJsObj.reLoadRowsData(info.sheet, [self.gsTree.nodes.indexOf(node)]);
+                            }
+                        }
+                    });
+                    const gatherNodes = stage.im_gather_node ? _.map(stage.im_gather_node.split(',')) : [];
+                    for (const node of self.gsTree.datas) {
+                        node.check = gatherNodes.indexOf(node.id + '') !== -1;
+                    }
+                    SpreadJsObj.loadSheetData(self.gsSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, self.gsTree);
+                    self.gsTree.expandByLevel(4);
+                    SpreadJsObj.refreshTreeRowVisible(self.gsSpread.getActiveSheet());
+                    SpreadJsObj.resetFieldReadOnly(self.gsSpread.getActiveSheet, 'check', !$('#im-gather-check')[0].checked);
+                } else {
+                    const gatherNodes = stage.im_gather_node ? _.map(stage.im_gather_node.split(',')) : [];
+                    for (const node of self.gsTree.datas) {
+                        node.check = gatherNodes.indexOf(node.id + '') !== -1;
+                    }
+                    SpreadJsObj.reLoadColsData(self.gsSpread.getActiveSheet(), [0]);
+                }
+            });
+            // 提交 高级设置
+            $('#choose2-ok').click(() => {
+                if (!self.gsTree) { return; }
+                const nodes = [];
+                for (const node of self.gsTree.datas) {
+                    if (node.check) {
+                        nodes.push(node.id);
+                    }
+                }
+                const data = {
+                    im_gather: $('#im-gather-check')[0].checked,
+                    im_gather_node: nodes.join(','),
+                };
+                postData(window.location.pathname + '/detail/adv', data, function (result) {
+                    stage.im_gather = data.im_gather;
+                    stage.im_gather_node = data.im_gather_node;
+                    $('#choose2').modal('hide');
+                });
+            });
+        }
+        _initModifyDetail() {
+            const self = this;
+            // 编辑
+            $('#edit-detail').click(function () {
+                $(this).hide();
+                $('#save-detail').show();
+                $('#cancel-detail').show();
+                $('#detail-show').hide();
+                $('#detail-edit').show();
+            });
+            // 保存
+            $('#save-detail').click(() => {
+                function check(field, obj, org, update) {
+                    const newValue = obj.val();
+                    if (!org[field]) {
+                        if (newValue !== '') {
+                            update[field] = newValue;
+                        }
+                    } else if (newValue !== org[field]){
+                        update[field] = newValue;
+                    }
+                }
+
+                const data = SpreadJsObj.getSelectObject(self.spread.getActiveSheet());
+                const updateData = {lid: data.lid, pid: data.pid};
+                if (data.uuid) {
+                    updateData.uuid = data.uuid;
+                } else {
+                    updateData.code = data.code;
+                    updateData.name = data.name;
+                    updateData.unit = data.unit;
+                    updateData.unit_price = data.unit_price;
+                }
+                updateData.bw = $('#bw-name').val();
+                updateData.peg = $('#peg').val();
+                updateData.xm = $('#xm-name').val();
+                updateData.drawing_code = $('#drawing-code').val();
+                updateData.calc_memo = $('#calc-memo').val();
+                postData(window.location.pathname + '/detail/save', updateData, function (result) {
+                    _.assign(data, result);
+                    self.reLoadDetailData();
+                });
+            });
+            // 取消
+            $('#cancel-detail').click(() => {
+                self.reLoadDetailData();
+            });
+        }
+        _initImageRela() {
+            const self = this;
+            function setdraggrable(){
+                $( ".img-item" ).draggable({ containment: "parent" },{stop: function( event, ui ) {
+                    }}).resizable({ containment: "parent" },{ handles: 'n, e, s, w, ne, se, sw, nw' },{ maxWidth: parseFloat($('#imgwidth').val())},{maxHeight: parseFloat($('#imgheight').val())},{
+                    stop: function( event, ui ) {
+                    }
+                });
+            }
+            // 移动图片
+            const moveImageItem = function (ev) {
+                const item = this;
+                const view = $('.img-view')[0];
+                let oEvent = ev;
+                // 浏览器有一些图片的默认事件,这里要阻止
+                oEvent.preventDefault();
+                let disX = oEvent.clientX - item.offsetLeft;
+                let disY = oEvent.clientY - item.offsetTop;
+                view.onmousemove = function (ev) {
+                    oEvent = ev;
+                    oEvent.preventDefault();
+                    let x = oEvent.clientX -disX;
+                    let y = oEvent.clientY -disY;
+
+                    // 图形移动的边界判断
+                    x = x <= 0 ? 0 : x;
+                    x = x >= view.offsetWidth - item.offsetWidth ? view.offsetWidth - item.offsetWidth : x;
+                    y = y <= 0 ? 0 : y;
+                    y = y >= view.offsetHeight - item.offsetHeight ? view.offsetHeight - item.offsetHeight : y;
+                    item.style.left = x + 'px';
+                    item.style.top = y + 'px';
+                };
+                // 图形移出父盒子取消移动事件,防止移动过快触发鼠标移出事件,导致鼠标弹起事件失效
+                view.onmouseleave = function () {
+                    view.onmousemove = null;
+                    view.onmouseup = null;
+                };
+                // 鼠标弹起后停止移动
+                view.onmouseup=function() {
+                    view.onmousemove = null;
+                    view.onmouseup = null;
+                };
+            };
+            const removeImageItem = function () {
+                $(this).parent().remove();
+            };
+            // 加载草图组成
+            $('#edit-img').on('show.bs.modal', function () {
+                const data = SpreadJsObj.getSelectObject(self.spread.getActiveSheet());
+                const items = data.calc_img_org ? JSON.parse(data.calc_img_org) : [];
+                const html = [];
+                for (const item of items) {
+                    const itemStyle = 'top:' + item.top + ';' + 'left:' + item.left + ';' + 'width:' + item.width + ';' + 'height:' + item.height + ';';
+                    html.push('<div class="img-item" style="' + itemStyle + '">');
+                    html.push('<div class="img-bar">');
+                    html.push('<a href="javascript: void(0);" class="text-danger" title="删除"><i class="fa fa-remove"></i></a>');
+                    html.push('</div>');
+                    html.push('<div class="focus" style="width:100%; height:100%"><img src="', item.src, '" id="draggable" style="width:100%; height:100%"></div>');
+                    html.push('</div>');
+                }
+                $('.img-view').html(html.join(''));
+                $('.img-bar').click(removeImageItem);
+                setdraggrable();
+            });
+            // 上传图片
+            $('#upload-img').click(function () {
+                $('#upload-img-file').trigger('click');
+            });
+            $('#upload-img-file').change(function () {
+                const file = this.files[0];
+                const ext = file.name.toLowerCase().split('.').splice(-1)[0];
+                const imgStr = /(jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
+                if (!imgStr.test(ext)) {
+                    toastr.error('请上传正确的图片格式文件');
+                    return
+                }
+                if ($(this).val()) {
+                    const formData = new FormData();
+                    formData.append('file', this.files[0]);
+                    postDataWithFile(window.location.pathname + '/detail/add-img', formData, function (result) {
+                        const html = [];
+                        html.push('<div class="img-item">');
+                        html.push('<div class="img-bar">');
+                        html.push('<a href="javascript: void(0);" class="text-danger" title="删除"><i class="fa fa-remove"></i></a>');
+                        html.push('</div>');
+                        html.push('<div class="focus" style="width:100%; height:100%"><img src="', '/' + result, '" id="draggable" style="width:100%; height:100%"></div>');
+                        html.push('</div>');
+                        $('.img-view').append(html.join(''));
+                        $('.img-bar').click(removeImageItem);
+                        setdraggrable();
+                    });
+                }
+            });
+
+            // 保存草图修改结果
+            $('#edit-img-ok').click(function () {
+                // 记录上传的图片的信息
+                const items = $('.img-item');
+                const data = SpreadJsObj.getSelectObject(self.spread.getActiveSheet());
+                if (items.length > 0) {
+                    const itemInfo = [];
+                    for (const item of items) {
+                        const itemData = {
+                            src: $('img', item).attr('src'),
+                            left: item.style.left,
+                            top: item.style.top,
+                            width: item.style.width,
+                            height: item.style.height,
+                        };
+                        itemInfo.push(itemData);
+                    }
+                    // 获取合并好的图片数据
+                    const canvas = document.createElement('canvas');
+                    const view = $('.img-view')[0];
+                    canvas.height = view.clientHeight;
+                    canvas.width = view.clientWidth;
+                    const ctx = canvas.getContext('2d');
+                    ctx.fillStyle = '#ffffff';
+                    ctx.fillRect(0, 0, canvas.width, canvas.height);
+                    for (const b of $('.img-item')) {
+                        const pos = $(b).position();
+                        const img = $('img', b)[0];
+                        ctx.drawImage(img, pos.left, pos.top, img.width, img.height);
+                    }
+                    // 生成上传数据
+                    const updateData = {updateType: 'update', lid: data.lid};
+                    if (data.uuid) {
+                        updateData.uuid = data.uuid;
+                    } else {
+                        updateData.code = data.code;
+                        updateData.name = data.name;
+                        updateData.unit = data.unit;
+                        updateData.unit_price = data.unit_price;
+                    }
+                    updateData.img = canvas.toDataURL('image/jpeg');
+                    updateData.imgInfo = itemInfo;
+                    postData(window.location.pathname + '/detail/merge-img', updateData, function (result) {
+                        _.assign(data, result);
+                        self.reLoadDetailData();
+                        $('#edit-img').modal('hide');
+                    });
+                } else if (data.calc_img) {
+                    postData(window.location.pathname + '/detail/merge-img', {updateType: 'clear', lid: data.lid, uuid: data.uuid}, function (result) {
+                        _.assign(data, result);
+                        self.reLoadDetailData();
+                        $('#edit-img').modal('hide');
+                    });
+                }
+            });
+        }
+        reBuildImData() {
+            const imData = stageIm.buildImData();
+            SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, imData);
+            this.reLoadDetailData();
+        }
+        loadStageLedgerUpdateData(data) {
+            const imData = stageIm.loadUpdateLedgerData(data);
+            SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, imData);
+            this.reLoadDetailData();
+        }
+        loadStagePosUpdateData(data) {
+            const imData = stageIm.loadUpdatePosData(data);
+            SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, imData);
+            this.reLoadDetailData();
+        }
+        loadStageChangeUpdateData(data) {
+            const imData = stageIm.loadUpdateChangeData(data);
+            SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, imData);
+            this.reLoadDetailData();
+        }
+        reLoadDetailData() {
+            const data = SpreadJsObj.getSelectObject(this.spread.getActiveSheet());
+
+            if (data) {
+                $('#edit-detail').show();
+                $('#modify-img').show();
+            } else {
+                $('#edit-detail').hide();
+                $('#modify-img').hide();
+            }
+            $('#save-detail').hide();
+            $('#cancel-detail').hide();
+
+            $('#detail-show').show();
+            $('#detail-edit').hide();
+
+            const contractJl = data && data.contract_jl ? data.contract_jl : '';
+            $('#show-contract-jl').text(contractJl);
+            $('#contract-jl').val(contractJl);
+
+            const qcJl = data && data.qc_jl ? data.qc_jl : '';
+            $('#show-qc-jl').text(qcJl);
+            $('#qc-jl').val(qcJl);
+
+            const bglCode = data && data.bgl_code ? data.bgl_code : '';
+            $('#show-bgl-code').text(bglCode);
+            $('#bgl-code').val(bglCode);
+
+            const bglDrawingCode = data && data.bgl_drawing_code ? data.bgl_drawing_code : '';
+            $('#show-bgl-drawing-code').text(bglDrawingCode);
+            $('#bgl-drawing-code').val(bglDrawingCode);
+
+            const bwName = data && data.bw ? data.bw : '';
+            $('#show-bw-name').text(bwName);
+            $('#bw-name').val(bwName);
+
+            const peg = data && data.peg ? data.peg : '';
+            $('#show-peg').text(peg);
+            $('#peg').val(peg);
+
+            const xmName = data && data.xm ? data.xm: '';
+            $('#show-xm-name').text(xmName);
+            $('#xm-name').val(xmName);
+
+            const drawingCode = data && data.drawing_code ? data.drawing_code: '';
+            $('#show-drawing-code').text(drawingCode);
+            $('#drawing-code').val(drawingCode);
+
+            const calcMemo = data && data.calc_memo ? data.calc_memo: '';
+            $('#show-calc-memo').html(calcMemo.replace(/\n/g, '<br/>'));
+            $('#calc-memo').val(calcMemo);
+
+            const calcImgSrc = data && data.calc_img ? '/' + data.calc_img : '';
+            $('#show-calc-img').attr('src', calcImgSrc);
+            $('#calc-img').attr('src', calcImgSrc);
+            $('#view-calc-img').attr('src', calcImgSrc);
+        }
+    }
     // 展开收起附件
     $('a', '.right-nav').bind('click', function () {
         //const main = $('#main-view'), tool = $('#tools-view');
@@ -1777,6 +2536,12 @@ $(document).ready(() => {
                 const node = SpreadJsObj.getSelectObject(slSpread.getActiveSheet());
                 getNodeList(node.id);
             }
+            if (tab.attr('content') === '#zhongjian') {
+                if (!detail) {
+                    detail = new Detail($('#detail-spread'));
+                    detail.spread.refresh();
+                }
+            }
         } else {
             tab.removeClass('active');
             tabPanel.removeClass('active');

+ 12 - 7
app/public/js/stage_audit.js

@@ -84,10 +84,14 @@ $(document).ready(function () {
                 const auditorshtml = [];
                 // 重新上报时。令其它的审批人流程图标转换
                 $('#auditors-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
+                for (let i = 0; i < $('#auditors-list li').length; i++) {
+                    $('#auditors-list li').eq(i).find('.pull-right').text(transFormToChinese(i+1) + '审');
+                }
                 // 添加新审批人
                 auditorshtml.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
                 auditorshtml.push('<i class="fa fa-stop-circle"></i> ');
                 auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                auditorshtml.push('<span class="pull-right">终审</span>');
                 auditorshtml.push('</li>');
                 $('#auditors-list').append(auditorshtml.join(''));
 
@@ -97,8 +101,9 @@ $(document).ready(function () {
                 // 添加新审批人
                 auditorshtml2.push('<li class="list-group-item" data-auditid="' + data.aid + '">');
                 auditorshtml2.push('<h5 class="card-title"><i class="fa fa-stop-circle"></i> ');
-                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small></h5>');
-                auditorshtml2.push('</li>');
+                auditorshtml2.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+                auditorshtml2.push('<span class="pull-right">终审</span>');
+                auditorshtml2.push('</h5></li>');
                 $('#auditors-list2').append(auditorshtml2.join(''));
             });
         }
@@ -128,6 +133,10 @@ $(document).ready(function () {
                 $('#auditors-list2 li').eq($('#auditors-list2 li').length-1).children('i')
                     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
             }
+            for (let i = 0; i < $('#auditors-list li').length; i++) {
+                $('#auditors-list li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i+1)) + '审');
+                $('#auditors-list2 li').eq(i).find('.pull-right').text((i+1 === $('#auditors-list2 li').length ? '终' : transFormToChinese(i+1)) + '审');
+            }
         });
     });
     // 退回选择修改审批人流程
@@ -135,11 +144,7 @@ $(document).ready(function () {
         $('#sp-list2').modal('hide');
     });
     $('a[f-target]').click(function () {
-        if (stage.check_detail) {
-            $('#sub-sp3').modal('show');
-        } else {
-            $($(this).attr('f-target')).modal('show');
-        }
+        $($(this).attr('f-target')).modal('show');
     })
 });
 // 检查上报情况

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

@@ -134,7 +134,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.change.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

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

@@ -92,7 +92,8 @@ $(document).ready(function () {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.compare.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 19 - 36
app/public/js/stage_detail.js

@@ -51,7 +51,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.detail.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');
@@ -71,7 +72,7 @@ $(document).ready(() => {
         loadPosData: function () {
             const data = SpreadJsObj.getSelectObject(detailSpread.getActiveSheet());
             const html = [];
-            if (data) {
+            if (data && data.leafXmjs) {
                 const rowIndex = parseInt($('#leaf-xmj-list').attr('rowIndex'));
                 const leafXmj = data.leafXmjs[rowIndex];
                 if (leafXmj) {
@@ -123,16 +124,18 @@ $(document).ready(() => {
             $('#save-detail').hide();
             $('#cancel-detail').hide();
             $('#bgl-code').val(data && data.bgl_code ? data.bgl_code : '').attr('readonly', '');
+            $('#bgl-drawing-code').val(data && data.bgl_drawing_code ? data.bgl_drawing_code : '').attr('readonly', '');
             $('#bw-name').val(data && data.bw ? data.bw : '').attr('readonly', '');
-            $('#start-peg').val(data && data.start_peg ? data.start_peg : '').attr('readonly', '');
-            $('#end-peg').val(data && data.end_peg ? data.end_peg : '').attr('readonly', '');
-            $('#unit-name').val(data && data.jldy ? data.jldy : '').attr('readonly', '');
+            $('#peg').val(data && data.peg ? data.peg : '').attr('readonly', '');
+            $('#xm-name').val(data && data.xm ? data.xm : '').attr('readonly', '');
             $('#drawing-code').val(data && data.drawing_code ? data.drawing_code : '').attr('readonly', '');
             $('#calc-memo').val(data && data.calc_memo ? data.calc_memo : '').attr('readonly', '');
             if (data && data.calc_img) {
-                $('#calc-img').html('<img src="/' + data.calc_img + '" class="d-100" width="100%">');
+                $('#calc-img').attr('src', '/' + data.calc_img );
+                $('#view-calc-img').attr('src', '/' + data.calc_img );
             } else {
-                $('#calc-img').html('');
+                $('#calc-img').attr('');
+                $('#view-calc-img').attr('');
             }
         },
         selectionChanged: function (e, info) {
@@ -148,7 +151,7 @@ $(document).ready(() => {
                 }
                 const data = SpreadJsObj.getSelectObject(info.sheet);
                 if (data) {
-                    const updateData = {lid: data.lid}
+                    const updateData = {lid: data.lid};
                     if (data.uuid) {
                         updateData.uuid = data.uuid;
                     } else {
@@ -305,8 +308,7 @@ $(document).ready(() => {
     console.time('loadDetailRela');
     postData(window.location.pathname + '/load', { loadType: 'all' }, function (data) {
         console.timeEnd('loadDetailRela');
-        //stageIm.loadData(data.ledger, data.curStage, data.pos, data.curPosStage, data.stageDetail);
-        stageIm.loadData(data.ledger, data.pos, data.stageDetail);
+        stageIm.loadData(data.ledger, data.pos, data.stageDetail, data.changeData);
         reBuildImData();
     });
 
@@ -536,10 +538,10 @@ $(document).ready(() => {
         $('#save-detail').show();
         $('#cancel-detail').show();
         $('#bgl-code').removeAttr('readonly');
+        $('#bgl-drawing-code').removeAttr('readonly');
         $('#bw-name').removeAttr('readonly');
-        $('#start-peg').removeAttr('readonly');
-        $('#end-peg').removeAttr('readonly');
-        $('#unit-name').removeAttr('readonly');
+        $('#peg').removeAttr('readonly');
+        $('#xm-name').removeAttr('readonly');
         $('#drawing-code').removeAttr('readonly');
         $('#calc-memo').removeAttr('readonly');
     });
@@ -567,10 +569,10 @@ $(document).ready(() => {
             updateData.unit_price = data.unit_price;
         }
         updateData.bgl_code = $('#bgl-code').val();
+        updateData.bgl_drawing_code = $('#bgl-drawing-code').val();
         updateData.bw = $('#bw-name').val();
-        updateData.start_peg = $('#start-peg').val();
-        updateData.end_peg = $('#end-peg').val();
-        updateData.jldy = $('#unit-name').val();
+        updateData.peg = $('#peg').val();
+        updateData.xm = $('#xm-name').val();
         updateData.drawing_code = $('#drawing-code').val();
         updateData.calc_memo = $('#calc-memo').val();
         //check('bgl_code', $('#bgl-code'), data, updateData);
@@ -582,31 +584,12 @@ $(document).ready(() => {
         //check('calc_memo', $('#calc-memo'), data, updateData);
         postData(window.location.pathname + '/save', updateData, function (result) {
             _.assign(data, result);
-            $('#edit-detail').show();
-            $('#save-detail').hide();
-            $('#cancel-detail').hide();
-            $('#bgl-code').attr('readonly', '');
-            $('#bw-name').attr('readonly', '');
-            $('#start-peg').attr('readonly', '');
-            $('#end-peg').attr('readonly', '');
-            $('#unit-name').attr('readonly', '');
-            $('#drawing-code').attr('readonly', '');
-            $('#calc-memo').attr('readonly', '');
+            detailOperationObj.reLoadDetailData();
             needCheckDetail();
         });
     });
     // 取消
     $('#cancel-detail').click(() => {
-        $('#edit-detail').show();
-        $('#cancel-detail').hide();
-        $('#save-detail').hide();
-        $('#bgl-code').attr('readonly', '');
-        $('#bw-name').attr('readonly', '');
-        $('#start-peg').attr('readonly', '');
-        $('#end-peg').attr('readonly', '');
-        $('#unit-name').attr('readonly', '');
-        $('#drawing-code').attr('readonly', '');
-        $('#calc-memo').attr('readonly', '');
         detailOperationObj.reLoadDetailData();
     });
 

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

@@ -27,7 +27,8 @@ $(document).ready(function () {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.gather.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 406 - 72
app/public/js/stage_im.js

@@ -9,9 +9,9 @@
  */
 
 const stageIm = (function () {
-    const imFields = ['uuid', 'doc_code', 'bgl_code', 'start_peg', 'end_peg', 'bw', 'jldy', 'drawing_code', 'calc_memo', 'calc_img'];
+    const imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img'];
     const splitChar = '-';
-    let stage, imType, details, ImData, pre;
+    let stage, imType, details, changes, ImData, pre;
     const gsTreeSetting = {
         id: 'ledger_id',
         pid: 'ledger_pid',
@@ -57,14 +57,14 @@ const stageIm = (function () {
     }
 
     function initCheck () {
-        const gatherNodes = stage.im_gather_node ? _.map(stage.im_gather_node.split(','), _.toNumber) : [];
+        const gatherNodes = stage.im_gather_node ? stage.im_gather_node.split(',') : [];
         for (const node of gsTree.datas) {
             node.check = gatherNodes.indexOf(node.id) !== -1;
         }
 
     }
 
-    function loadData (ledger, pos, stageDetail) {
+    function loadData (ledger, pos, stageDetail, stageChange) {
         gsTree.loadDatas(ledger);
         treeCalc.calculateAll(gsTree);
 
@@ -73,6 +73,8 @@ const stageIm = (function () {
 
         initCheck();
         details = stageDetail;
+
+        changes = stageChange;
     }
 
     // function loadData (ledger, curStage, pos, curPosStage, stageDetail) {
@@ -135,10 +137,40 @@ const stageIm = (function () {
     }
 
     function CheckPeg(text) {
-        const pegReg = /[kK][0-9][++][0-9]{3}/;
+        const pegReg = /[a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?/;
+        console.log(text);
+        console.log(text.match(pegReg));
         return pegReg.test(text);
     }
 
+    function getPegStr(text) {
+        const pegReg1 = /[a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?[~~—][a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?/;
+        const result1 = text.match(pegReg1);
+        console.log(result1);
+        if (result1) {
+            return result1[0];
+        } else {
+            const pegReg2 = /[a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?-[a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?/;
+            const result2 = text.match(pegReg2);
+            if (result2) {
+                return result2[0];
+            } else {
+                const pegReg3 = /[a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?/;
+                const result3 = text.match(pegReg3);
+                return result3 ? result3[0] : '';
+            }
+        }
+        //const pegReg = /[a-zA-Z]?[kK][0-9]+[++][0-9]{3}([.][0-9]+)?/g;
+        // const result = text.match(pegReg);
+        // if (result.length === 1) {
+        //     return result[0]
+        // } else {
+        //     const iBegin = text.indexOf(result[0]);
+        //     const iEnd = text.indexOf(result[result.length - 1]);
+        //     return text.substring(iBegin, iEnd) + result[result.length - 1];
+        // }
+    }
+
     function getPegNode (node) {
         if (node) {
             if (CheckPeg(node.name)) {
@@ -161,73 +193,208 @@ const stageIm = (function () {
         }
     }
 
+    function getZlNormalBw(node, peg) {
+        if (peg) {
+            const subPeg1 = getNodeByLevel(node, peg.level + 1);
+            const subPeg2 = getNodeByLevel(node, peg.level + 2);
+            let result = peg.name;
+            if (subPeg1 && subPeg1.id !== peg.id) {
+                result = result + '-' + subPeg1.name;
+                if (subPeg2 && subPeg2.id !== subPeg1.id) {
+                    result = result + '-' + subPeg2.name;
+                }
+            }
+            return result;
+        } else {
+            if (node.level === 2) {
+                return node.name;
+            } else if (node.level >= 3) {
+                let parent = node, result = parent.name;
+                while (parent.level > 3 && parent) {
+                    parent = getNodeByLevel(node, parent.level - 1);
+                    result = parent.name + '-' + result;
+                }
+                return result;
+            } else {
+                return '';
+            }
+        }
+    }
+
+    function getZlGatherBw(node, peg) {
+        if (peg) {
+            const subPeg1 = getNodeByLevel(node, peg.level + 1);
+            let result = peg.name;
+            if (subPeg1 && subPeg1.id !== peg.id) {
+                result = result + '-' + subPeg1.name;
+            }
+            return result;
+        } else {
+            if (node.level < 3) {
+                return node.name;
+            } else {
+                let parent = node, result = parent.name;
+                while (parent.level > 3 && parent) {
+                    parent = getNodeByLevel(node, parent.level - 1);
+                    result = parent.name + '-' + result;
+                }
+                return result;
+            }
+        }
+    }
+
     function checkCustomDetail(im) {
         const cd = _.find(details, function (d) {
             return im.lid === d.lid &&
                 (!im.code || im.code === d.code) &&
                 (!im.name || im.name === d.name) &&
                 (!im.unit || im.unit === d.unit) &&
-                checkZero(ZhCalc.sub(im.unit_price, d.unit_price));
+                checkZero(ZhCalc.sub(im.unit_price, d.unit_price)) &&
+                (!im.pid || im.pid === d.pid);
         });
         if (cd) {
             _.assignInWith(im, cd, function (oV, sV, key) {
-                return imFields.indexOf(key) > -1 && sV !== undefined ? sV : oV;
+                return imFields.indexOf(key) > -1 && sV !== undefined && sV !== null ? sV : oV;
             });
         }
     }
 
-    function generatePosData(node, lx) {
-        if (!lx.pos) {
-            lx.pos = [];
+    function getCalcMemo(im) {
+        if (im.calc_memo !== undefined && im.calc_memo !== null && im.calc_memo !== '') return;
+
+        if (im.leafXmjs && im.leafXmjs.length > 0) {
+            const memo = ['本期计量:' + im.jl + ' ' + im.unit];
+            for (const lx of im.leafXmjs) {
+                for (const p of lx.pos) {
+                    memo.push(p.name + ':' + p.jl + ' ' + im.unit);
+                }
+            }
+            im.calc_memo = memo.join('\n');
+        } else if (im.gclBills && im.gclBills.length > 0) {
+            const memo = [];
+            for (const [i, b] of im.gclBills.entries()) {
+                if (b.pos && b.pos.length > 0) {
+                    memo.push('清单' + (i+1) + b.b_code + ' ' + b.name);
+                    for (const p of b.pos) {
+                        memo.push(p.name + ':' + p.jl + ' ' + b.unit);
+                    }
+                } else {
+                    memo.push('清单' + (i+1) + b.b_code + ' ' + b.name + ':' + b.jl + ' ' + b.unit);
+                }
+            }
+            im.calc_memo = memo.join('\n');
+        } else {
+            im.calc_memo =  '';
+        }
+    }
+    function getChangeInfo(im) {
+        if (im.changes && im.changes.length > 0) {
+            const code = _.uniq(_.map(im.changes, 'c_code'));
+            if (!im.bgl_code || im.bgl_code === '') im.bgl_code = code.join(';');
+            const new_code = _.uniq(_.map(im.changes, 'c_new_code'));
+            if (!im.bgl_drawing_code || im.bgl_drawing_code === '') im.bgl_drawing_code = new_code.join(';');
+        }
+    }
+    function compareCode(str1, str2, symbol = '-') {
+        if (!str1) {
+            return -1;
+        } else if (!str2) {
+            return 1;
+        }
+
+        const path1 = str1.split(symbol);
+        const path2 = str2.split(symbol);
+        const reg = /^[0-9]*$/;
+        for (let i = 0, iLen = Math.min(path1.length, path2.length); i < iLen; i++) {
+            if (reg.test(path1[i]) && reg.test(path2[i])) {
+                const num1 = parseInt(path1[i]);
+                const num2 = parseInt(path2[i]);
+                if (num1 !== num2)  {
+                    return num1 - num2;
+                }
+            } else if (path1[i] < path2[i]) {
+                return -1;
+            } else if (path1[i] > path2[i]) {
+                return 1;
+            }
+        }
+        return path1.length - path2.length;
+    }
+
+    function generateTzPosData(node, gclBills) {
+        if (!gclBills.pos) {
+            gclBills.pos = [];
         }
         const posRange = gsPos.getLedgerPos(node.id);
         if (!posRange) { return }
         for (const p of posRange) {
             if (!p.gather_qty || checkZero(p.gather_qty)) { continue; }
-            let lp = _.find(lx.pos, {name: p.name});
+            let lp = _.find(gclBills.pos, {name: p.name});
             if (!lp) {
-                lp = {name: p.name, qty: p.quantity};
-                lx.pos.push(lp);
+                lp = {name: p.name};
+                gclBills.pos.push(lp);
             }
             lp.jl = ZhCalc.add(lp.jl, p.gather_qty);
+            lp.contract_jl = ZhCalc.add(lp.contract_jl, p.contract_qty);
+            lp.qc_jl = ZhCalc.add(lp.qc_jl, p.qc_qty);
         }
     }
-
-    /**
-     * 生成所属项目节数据(取最底层项目节)
-     * @param node - 生成数据基于的台账节点
-     * @param im - 中间计量数据
-     */
-    function generateLeafXmjData(node, im, jlField) {
-        if (!im.leafXmjs) {
-            im.leafXmjs = [];
+    function generateTzGclBillsData(node, im) {
+        if (!im.gclBills) {
+            im.gclBills = [];
         }
-        const leafXmj = gsTree.getLeafXmjParent(node);
-        if (!leafXmj) { return }
-        let lx = _.find(im.leafXmjs, {lxid: leafXmj.id});
-        if (!lx) {
-            lx = {
-                lxid: leafXmj.id,
-                code: leafXmj.code,
-                name: leafXmj.name
-            };
-            im.leafXmjs.push(lx);
+        const posterity = gsTree.getPosterity(node);
+        for (const p of posterity) {
+            if (p.children && p.children.length > 0) {
+                continue;
+            }
+            if ((!p.contract_tp || p.contract_tp === 0) && (!p.qc_tp || p.qc_tp === 0)) {
+                continue;
+            }
+            let b = _.find(im.gclBills, {bid: p.id});
+            if (!b) {
+                b = {bid: p.id, b_code: p.b_code, name: p.name, unit: p.unit};
+                im.gclBills.push(b);
+            }
+            b.jl = ZhCalc.add(b.jl, p.gather_qty);
+            b.contract_jl = ZhCalc.add(b.contract_jl, p.contract_qty);
+            b.qc_jl = ZhCalc.add(b.qc_jl, p.qc_qty);
+            generateTzPosData(p, b);
         }
-        lx.jl = ZhCalc.add(lx.jl, node[jlField]);
-        generatePosData(node, lx);
     }
-
-    function getCalcMemo(im) {
-        if (im.calc_memo !== undefined && im.calc_memo !== null && im.calc_memo !== '') return;
-        const memo = ['本期计量:' + im.jl + ' ' + im.unit];
-        for (const lx of im.leafXmjs) {
-            for (const p of lx.pos) {
-                memo.push(p.name + ':' + p.qty + ' ' + im.unit);
+    function generateTzChangeData(node, im) {
+        if (!im.changes) {
+            im.changes = [];
+        }
+        const posterity = gsTree.getPosterity(node);
+        for (const p of posterity) {
+            if (p.children && p.children.length > 0) {
+                continue;
+            }
+            if ((!p.qc_tp || p.qc_tp === 0)) {
+                continue;
+            }
+            const posRange = gsPos.getLedgerPos(p.id);
+            if (!posRange) {
+                for (const c of changes) {
+                    if (c.lid === p.id && c.pid == -1 && c.qty && c.qty !== 0) {
+                        im.changes.push(c);
+                    }
+                }
+            } else {
+                for (const pp of posRange) {
+                    if ((!pp.qc_tp || pp.qc_tp === 0)) {
+                        continue;
+                    }
+                    for (const c of changes) {
+                        if (c.lid === p.id && c.pid === pp.id && c.qty && c.qty !== 0) {
+                            im.changes.push(c);
+                        }
+                    }
+                }
             }
         }
-        return memo.join('\n');
     }
-
     /**
      * 生成 0号台账 中间计量数据
      * @param {Object} node - 生成中间计量表的节点
@@ -236,27 +403,92 @@ const stageIm = (function () {
         if (node.gather_tp) {
             const peg = getPegNode(node);
             const im = {
-                lid: node.id,
-                code: node.code,
-                jl: node.gather_tp,
+                lid: node.id, code: node.code,
+                jl: node.gather_tp, contract_jl: node.contract_tp, qc_jl: node.qc_tp,
                 im_code: getNewImCode(),
-                fbfx: getFbfx(node, peg),
-                peg: peg ? peg.name : '',
-                drawing_code: getDrawingCode(node),
+                peg: peg ? getPegStr(peg.name) : '', drawing_code: getDrawingCode(node),
             };
             if (stage.im_gather && node.check) {
-                im.bw = node.name;
+                im.bw = getZlGatherBw(node, peg);
+                im.xm = '';
             } else {
-                im.jldy = node.name;
-                // to do
-                im.bw = node.name
+                im.bw = getZlNormalBw(node, peg);
+                im.xm = node.name;
             }
             checkCustomDetail(im);
-            generateLeafXmjData(node, im, 'gather_tp');
+            if (!stage.im_gather || !node.check) {
+                generateTzGclBillsData(node, im);
+            }
             ImData.push(im);
+            generateTzChangeData(node, im);
         }
     }
 
+    function generateZlPosData(node, lx) {
+        if (!lx.pos) {
+            lx.pos = [];
+        }
+        const posRange = gsPos.getLedgerPos(node.id);
+        if (!posRange) { return }
+        for (const p of posRange) {
+            if (!p.gather_qty || checkZero(p.gather_qty)) { continue; }
+            let lp = _.find(lx.pos, {name: p.name});
+            if (!lp) {
+                lp = {name: p.name};
+                lx.pos.push(lp);
+            }
+            lp.jl = ZhCalc.add(lp.jl, p.gather_qty);
+            lp.contract_jl = ZhCalc.add(lp.contract_jl, p.contract_qty);
+            lp.qc_jl = ZhCalc.add(lp.qc_jl, p.qc_qty);
+        }
+    }
+    function generateZlLeafXmjData(node, im) {
+        if (!im.leafXmjs) {
+            im.leafXmjs = [];
+        }
+        const leafXmj = gsTree.getLeafXmjParent(node);
+        if (!leafXmj) { return }
+        let lx = _.find(im.leafXmjs, {lxid: leafXmj.id});
+        if (!lx) {
+            lx = {
+                lxid: leafXmj.id,
+                code: leafXmj.code,
+                name: leafXmj.name
+            };
+            im.leafXmjs.push(lx);
+        }
+        lx.jl = ZhCalc.add(lx.jl, node.gather_qty);
+        lx.contract_jl = ZhCalc.add(lx.contract_jl, node.contract_qty);
+        lx.qc_jl = ZhCalc.add(lx.qc_jl, node.qc_qty);
+        generateZlPosData(node, lx);
+    }
+    function generateZlChangeData(node, im) {
+        if (!im.changes) {
+            im.changes = [];
+        }
+        if ((!node.qc_qty || node.qc_qty === 0)) {
+            return;
+        }
+        const posRange = gsPos.getLedgerPos(node.id);
+        if (!posRange) {
+            for (const c of changes) {
+                if (c.lid === node.id && c.pid == -1 && c.qty && c.qty !== 0) {
+                    im.changes.push(c);
+                }
+            }
+        } else {
+            for (const p of posRange) {
+                if ((!p.qc_qty || p.qc_qty === 0)) {
+                    continue;
+                }
+                for (const c of changes) {
+                    if (c.lid === node.id && c.pid === p.id && c.qty && c.qty !== 0) {
+                        im.changes.push(c);
+                    }
+                }
+            }
+        }
+    }
     /**
      * 生成 总量控制 中间计量数据
      * @param {Object} node - 生成中间计量表的节点
@@ -268,34 +500,94 @@ const stageIm = (function () {
             if (!p.b_code || p.b_code === '') { continue }
             if (!p.gather_qty || p.gather_qty === 0 ) { continue; }
             let im = nodeImData.find(function (d) {
-                return d.code === p.b_code && p.name === d.name && p.unit === d.unit && checkZero(ZhCalc.sub(p.unit_price, d.unit_price));
+                return d.lid === node.id &&
+                    d.code === p.b_code && p.name === d.name && p.unit === d.unit && checkZero(ZhCalc.sub(p.unit_price, d.unit_price));
             });
             if (!im) {
                 const peg = getPegNode(node);
                 im = {
-                    lid: node.id,
-                    code: p.b_code,
-                    name: p.name,
-                    unit: p.unit,
-                    unit_price: p.unit_price,
-                    jl: 0,
+                    lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
+                    jl: 0, contract_jl: 0, qc_jl: 0,
                     im_code: getNewImCode(),
-                    fbfx: getFbfx(node, peg),
-                    peg: peg ? peg.name : '',
-                    drawing_code: getDrawingCode(node),
-                    bw: node.name,
+                    peg: peg ? getPegStr(peg.name) : '', drawing_code: getDrawingCode(node),
                 };
                 if (stage.im_gather && node.check) {
-
+                    im.bw = getZlGatherBw(node, peg);
+                    im.xm = '';
                 } else {
-                    im.jldy = p.name;
+                    im.bw = getZlNormalBw(node, peg);
+                    im.xm = node.name;
                 }
                 nodeImData.push(im);
                 checkCustomDetail(im);
                 ImData.push(im);
             }
-            generateLeafXmjData(p, im, 'gather_qty');
+            if (!stage.im_gather || !node.check) {
+                generateZlLeafXmjData(p, im, 'gather_qty');
+            }
+            generateZlChangeData(p, im);
             im.jl = ZhCalc.add(im.jl, p.gather_qty);
+            im.contract_jl = ZhCalc.add(im.contract_jl, p.contract_qty);
+            im.qc_jl = ZhCalc.add(im.qc_jl, p.qc_qty);
+        }
+    }
+
+    function generateBwImData (node) {
+        const posterity = gsTree.getPosterity(node);
+        for (const p of posterity) {
+            if (p.children && p.children.length > 0 ) { continue; }
+            if (!p.b_code || p.b_code === '') { continue }
+            const peg = getPegNode(node);
+            const pPos = gsPos.getLedgerPos(p.id);
+            const bw = getZlNormalBw(node, peg);
+            if (pPos && pPos.length > 0) {
+                for (const pp of pPos) {
+                    if ((!pp.contract_qty || pp.contract_qty === 0) && (!pp.qc_qty || pp.qc_qty === 0)) { continue }
+                    const im = {
+                        lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, pid: pp.id,
+                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty,
+                        im_code: getNewImCode(),
+                        bw: bw,
+                        peg: CheckPeg(pp.name) ? getPegStr(pp.name) : (peg ? getPegStr(peg.name) : ''),
+                        xm: pp.name,
+                        drawing_code: pp.drawing_code,
+                        changes: [],
+                    };
+                    im.calc_memo = '本期计量:' + im.jl + ' ' + im.unit;
+                    checkCustomDetail(im);
+                    ImData.push(im);
+                    if (pp.qc_qty && pp.qc_qty !== 0) {
+                        for (const c of changes) {
+                            if (c.lid === p.id && c.pid === pp.id && c.qty && c.qty !== 0) {
+                                im.changes.push(c);
+                            }
+                        }
+                    }
+                }
+            } else {
+                if ((!p.contract_qty || p.contract_qty === 0) && (!p.qc_qty || p.qc_qty === 0)) { continue }
+
+                const im = {
+                    lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, pid: '',
+                    jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty,
+                    im_code: getNewImCode(),
+                    bw: bw,
+                    peg: peg ? getPegStr(peg.name) : '',
+                    xm: node.name,
+                    drawing_code: getDrawingCode(node),
+                    changes: [],
+                };
+                im.calc_memo = '本期计量:' + im.jl + ' ' + im.unit;
+                checkCustomDetail(im);
+                ImData.push(im);
+                if (p.qc_qty && p.qc_qty !== 0) {
+                    for (const c of changes) {
+                        if (c.lid === p.id && c.pid == -1 && c.qty && c.qty !== 0) {
+                            im.changes.push(c);
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -306,11 +598,13 @@ const stageIm = (function () {
     function recursiveBuildImData (nodes) {
         if (!nodes || nodes.length === 0) { return; }
         for (const node of nodes) {
-            if (gsTree.isLeafXmj(node) || (stage.im_gather && node.check)) {
+            if (gsTree.isLeafXmj(node) || (stage.im_type !== imType.bw.value && stage.im_gather && node.check)) {
                 if (stage.im_type === imType.tz.value) {
                     generateTzImData(node);
-                } else {
+                } else if (stage.im_type === imType.zl.value) {
                     generateZlImData(node);
+                } else if (stage.im_type === imType.bw.value) {
+                    generateBwImData(node);
                 }
             } else {
                 recursiveBuildImData(node.children);
@@ -332,7 +626,13 @@ const stageIm = (function () {
         // 生成数据
         recursiveBuildImData(gsTree.children);
         for (const im of ImData) {
-            im.calc_memo = getCalcMemo(im);
+            getCalcMemo(im);
+            getChangeInfo(im);
+        }
+        if (stage.im_type !== imType.tz.value) {
+            ImData.sort(function (x, y) {
+                return compareCode(x.code, y.code);
+            });
         }
         return ImData;
     }
@@ -358,18 +658,52 @@ const stageIm = (function () {
         }
     }
 
+    function loadUpdateLedgerData(data) {
+        gsTree.loadPostStageData(data);
+        if (data.change) {
+            _.remove(changes, data.change.target);
+            for (const c of data.change.data) {
+                changes.push(c);
+            }
+        }
+        return buildImData();
+    }
+    function loadUpdatePosData(data) {
+        if (data.pos) {
+            gsPos.updateDatas(data.pos.pos);
+            gsPos.loadCurStageData(data.pos.curStageData);
+        }
+        gsTree.loadPostStageData(data.ledger);
+        return buildImData();
+    }
+    function loadUpdateChangeData(data) {
+        if (data.pos) {
+            gsPos.loadCurStageData(data.pos.curStageData);
+        }
+        gsTree.loadPostStageData(data.bills);
+        if (data.change) {
+            _.remove(changes, data.change.target);
+            for (const c of data.change.data) {
+                changes.push(c);
+            }
+        }
+        return buildImData();
+    }
+
     return {
         init,
         initCheck,
         loadData,
         buildImData,
         loadUpdateDetailData,
+        loadUpdateLedgerData,
+        loadUpdatePosData,
+        loadUpdateChangeData,
         getGsTree: function () {
             return gsTree;
         },
         getImData: function () {
             return ImData;
         },
-
     }
 })();

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

@@ -90,7 +90,8 @@ $(document).ready(() => {
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'stage.pay.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 12 - 1
app/public/js/sub_menu.js

@@ -11,6 +11,7 @@
     $.subMenu = function (setting) {
         const menu = $(setting.menu), miniMenu = $(setting.miniMenu);
         const toMenu = $(setting.toMenu), toMiniMenu = $(setting.toMiniMenu);
+        const miniHint = $(setting.miniHint);
 
         const showMenu = function () {
             menu.show();
@@ -23,7 +24,7 @@
             setting.callback({mini: true});
         };
         const menuType = setting.key ? getLocalCache(setting.key) : null;
-        if (menuType && menuType === 'mini-menu') {
+        if (menuType && menuType === 'miniMenu') {
             showMiniMenu();
         } else {
             showMenu();
@@ -39,9 +40,19 @@
             if (setting.key) {
                 setLocalCache(setting.key, 'miniMenu');
             }
+
+            const hint = setting.hintKey ? getLocalCache(setting.hintKey) : '';
+            if (hint !== '1') {
+                miniHint.popover('show');
+            }
         });
         miniMenu.mouseenter(function () {
             $(setting.miniMenuList).show();
+
+            miniHint.popover('hide');
+            if (setting.hintKey) {
+                setLocalCache(setting.hintKey, '1');
+            }
         });
         miniMenu.mouseleave(function () {
             $(setting.miniMenuList).hide();

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

@@ -309,7 +309,7 @@ function getTenderTreeHtml () {
         html.push('<th>', '名称', '</th>');
         html.push('<th width="120">', '计量期数', '</th>');
         html.push('<th>', '总价 <i class="fa fa-question-circle text-primary"  data-placement="bottom" data-toggle="tooltip" data-original-title="0号台账+截止本期数量变更"></i>', '</th>');
-        html.push('<th>', '截止本期累计完成/本期完成/未完成', '</th>');
+        html.push('<th>', '截止上期完成/本期完成/未完成', '</th>');
         html.push('</tr>', '</thead>');
         for (const t of tenderTree) {
             html.push(recursiveGetTenderNodeHtml(t, tenderTree));

+ 2 - 2
app/router.js

@@ -42,7 +42,7 @@ module.exports = app => {
     app.get('/setting/user/permission/set', sessionAuth, 'settingController.userPermissionSet');
     // 账号停用和启用
     app.post('/setting/user/switch', sessionAuth, 'settingController.userSwitch');
-    app.post('/setting/user/add', sessionAuth, 'settingController.addUser');
+    app.post('/setting/user/add', sessionAuth, datetimeFill, 'settingController.addUser');
     app.post('/setting/user/update', sessionAuth, 'settingController.updateUser');
     app.post('/setting/user/permission', sessionAuth, 'settingController.permission');
     app.post('/setting/user/reset/password', sessionAuth, 'settingController.resetUserPassword');
@@ -141,6 +141,7 @@ module.exports = app => {
     // 期计量详细
     // 本期计量台账
     app.get('/tender/:id/measure/stage/:order', sessionAuth, tenderCheck, stageCheck, 'stageController.index');
+    app.post('/tender/:id/measure/stage/:order/load', sessionAuth, tenderCheck, stageCheck, 'stageController.getStageData');
     app.post('/tender/:id/measure/stage/:order/pos', sessionAuth, tenderCheck, stageCheck, 'stageController.getStagePosData');
     app.post('/tender/:id/measure/stage/:order/update', sessionAuth, tenderCheck, stageCheck, 'stageController.updateStageData');
     app.post('/tender/:id/measure/stage/:order/valid-change', sessionAuth, tenderCheck, stageCheck, 'stageController.searchValidChange');
@@ -158,7 +159,6 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/detail/save', sessionAuth, tenderCheck, stageCheck, 'stageController.saveDetailData');
     app.post('/tender/:id/measure/stage/:order/detail/add-img', sessionAuth, tenderCheck, stageCheck, 'stageController.addCalcImage');
     app.post('/tender/:id/measure/stage/:order/detail/merge-img', sessionAuth, tenderCheck, stageCheck, 'stageController.mergeCalcImage');
-    app.post('/tender/:id/measure/stage/:order/detail/done', sessionAuth, tenderCheck, stageCheck, 'stageController.doneDetail');
     // 合同支付
     app.get('/tender/:id/measure/stage/:order/pay', sessionAuth, tenderCheck, stageCheck, 'stageController.pay');
     app.post('/tender/:id/measure/stage/:order/pay/detail', sessionAuth, tenderCheck, stageCheck, 'stageController.chapterDetail');

+ 12 - 6
app/service/ledger_audit.js

@@ -50,12 +50,18 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getAuditors(tenderId, times = 1) {
-            const sql = 'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`audit_order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time` ' +
-                'FROM ?? AS la, ?? AS pa ' +
-                'WHERE la.`tender_id` = ? and la.`times` = ?' +
-                '    and la.`audit_id` = pa.`id` order by la.`audit_order`';
-            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, tenderId, times];
-            return await this.db.query(sql, sqlParam);
+            const sql = 'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`audit_order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, g.`sort` ' +
+                'FROM ?? AS la, ?? AS pa, (SELECT `audit_id`,(@i:=@i+1) as `sort` FROM ??, (select @i:=0) as it WHERE `tender_id` = ? AND `times` = ? GROUP BY `audit_id`) as g ' +
+                'WHERE la.`tender_id` = ? and la.`times` = ? and la.`audit_id` = pa.`id` and g.`audit_id` = la.`audit_id` order by la.`audit_order`';
+            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.tableName, tenderId, times, tenderId, times];
+            const result = await this.db.query(sql, sqlParam);
+            const sql2 = 'SELECT COUNT(a.`audit_id`) as num FROM (SELECT `audit_id` FROM ?? WHERE `tender_id` = ? AND `times` = ? GROUP BY `audit_id`) as a';
+            const sqlParam2 = [this.tableName, tenderId, times];
+            const count = await this.db.queryOne(sql2, sqlParam2);
+            for (const i in result) {
+                result[i].max_sort = count.num;
+            }
+            return result;
         }
 
         /**

+ 19 - 3
app/service/material.js

@@ -147,9 +147,14 @@ module.exports = app => {
                     await this.ctx.service.materialListNotjoin.copyNewStageNotJoinList(transaction, preNotJoinList, newMaterial.id);
                     // 复制调差清单工料关联表
                     await this.ctx.service.materialList.copyPreMaterialList(transaction, preMaterial, newMaterial);
-                    // 修改本期应耗数量值和有效价差,需要剔除不参与调差的清单数据
-                    await this.ctx.service.materialBills.updateNewMaterial(transaction, preNotJoinList);
+                    // 修改本期应耗数量值和有效价差,需要剔除不参与调差的清单数据,并返回总金额
+                    const m_tp = await this.ctx.service.materialBills.updateNewMaterial(transaction, this.ctx.tender.id, newMaterial.id, this.ctx, newMaterial.stage_id);
                     // 计算得出本期总金额
+                    const updateMaterialData = {
+                        id: newMaterial.id,
+                        m_tp,
+                    };
+                    await transaction.update(this.tableName, updateMaterialData);
                 }
 
                 await transaction.commit();
@@ -169,11 +174,22 @@ module.exports = app => {
         async deleteMaterial(id) {
             const transaction = await this.db.beginTransaction();
             try {
-                await transaction.delete(this.tableName, { id });
                 await transaction.delete(this.ctx.service.materialAudit.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialBills.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialList.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialListNotjoin.tableName, { mid: id });
+                await transaction.delete(this.ctx.service.materialBillsHistory.tableName, { mid: id });
+                // 如果存在上一期,把上一期的quantity,pre_tp添加到bill中
+                const materialInfo = await this.getDataById(id);
+                if (materialInfo.order > 1) {
+                    const sql = 'UPDATE ' + this.ctx.service.materialBills.tableName + ' as mb, ' +
+                        this.ctx.service.materialBillsHistory.tableName + ' as mbh ' +
+                        'SET mb.`quantity` = mbh.`quantity`, mb.`pre_tp` = mbh.`pre_tp` ' +
+                        '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);
+                }
+                await transaction.delete(this.tableName, { id });
                 await transaction.commit();
                 return true;
             } catch (err) {

+ 32 - 16
app/service/material_audit.js

@@ -9,6 +9,7 @@
  */
 
 const auditConst = require('../const/audit').material;
+const materialConst = require('../const/material');
 // const smsTypeConst = require('../const/sms_type');
 const SMS = require('../lib/sms');
 
@@ -50,11 +51,18 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getAuditors(materialId, times = 1) {
-            const sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time` ' +
-                'FROM ?? AS la, ?? AS pa ' +
-                'WHERE la.`mid` = ? and la.`times` = ? and la.`aid` = pa.`id` order by la.`order`';
-            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, materialId, times];
-            return await this.db.query(sql, sqlParam);
+            const sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, g.`sort` ' +
+                'FROM ?? AS la, ?? AS pa, (SELECT `aid`,(@i:=@i+1) as `sort` FROM ??, (select @i:=0) as it WHERE `mid` = ? AND `times` = ? GROUP BY `aid`) as g ' +
+                'WHERE la.`mid` = ? and la.`times` = ? and la.`aid` = pa.`id` and g.`aid` = la.`aid` order by la.`order`';
+            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.tableName, materialId, times, materialId, times];
+            const result = await this.db.query(sql, sqlParam);
+            const sql2 = 'SELECT COUNT(a.`aid`) as num FROM (SELECT `aid` FROM ?? WHERE `mid` = ? AND `times` = ? GROUP BY `aid`) as a';
+            const sqlParam2 = [this.tableName, materialId, times];
+            const count = await this.db.queryOne(sql2, sqlParam2);
+            for (const i in result) {
+                result[i].max_sort = count.num;
+            }
+            return result;
         }
 
         /**
@@ -188,19 +196,21 @@ module.exports = app => {
                     id: materialId, status: auditConst.status.checking,
                 });
 
-                // 把material_bills本期应耗数量设置成s_quantity里的历史本期应耗数量
-                const materialBillsData = await this.ctx.service.materialBills.getAllDataByCondition({ tid: this.ctx.tender.id });
+                // 本期应耗数量和上期调差金额插入到material_bills_history表里
+                const materialBillsData = await this.ctx.service.materialBills.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+                const mbhList = [];
                 for (const mb of materialBillsData) {
-                    const order = this.ctx.material.order;
-                    const s_quantity = mb.s_quantity !== null ? mb.s_quantity.split(',') : [];
-                    const quantity = mb.quantity !== null ? mb.quantity : '';
-                    if (s_quantity.length === order) {
-                        s_quantity[order - 1] = quantity;
-                    } else {
-                        s_quantity.push(quantity);
-                    }
-                    await transaction.update(this.ctx.service.materialBills.tableName, { id: mb.id, s_quantity: s_quantity.join(',') });
+                    const newMbh = {
+                        tid: this.ctx.tender.id,
+                        mid: this.ctx.material.id,
+                        order: this.ctx.material.order,
+                        mb_id: mb.id,
+                        quantity: mb.quantity,
+                        pre_tp: mb.pre_tp,
+                    };
+                    mbhList.push(newMbh);
                 }
+                await transaction.insert(this.ctx.service.materialBillsHistory.tableName, mbhList);
 
                 // 添加短信通知-需要审批提醒功能
                 // const smsUser = await this.ctx.service.projectAccount.getDataById(audit.aid);
@@ -336,6 +346,12 @@ module.exports = app => {
                 });
                 // 拷贝新一次审核流程列表
                 await transaction.insert(this.tableName, auditors);
+                // 删除material_bills_history信息
+                await transaction.delete(this.ctx.service.materialBillsHistory.tableName, {
+                    tid: this.ctx.tender.id,
+                    order: this.ctx.material.order,
+                });
+
                 // 计算该审批人最终数据
                 // await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                 // 复制一份最新数据给原报

+ 125 - 3
app/service/material_bills.js

@@ -9,6 +9,8 @@
  */
 
 const auditConst = require('../const/audit').material;
+const materialConst = require('../const/material');
+const MaterialCalculator = require('../lib/material_calc');
 
 module.exports = app => {
     class MaterialBills extends app.BaseService {
@@ -54,8 +56,22 @@ module.exports = app => {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
-            // 判断是否可删
-            return await this.deleteById(id);
+            // 判断t_type是否为费用,且存在quantity,m_spread值
+            const transaction = await this.db.beginTransaction();
+            try {
+                const mbInfo = await this.getDataById(id);
+                await transaction.delete(this.tableName, { id });
+                let m_tp = this.ctx.material.m_tp;
+                if (mbInfo.t_type === materialConst.t_type[1].value && mbInfo.quantity !== null && mbInfo.m_spread !== null) {
+                    // 金额发生变化,则重新计算本期金额
+                    m_tp = await this.calcMaterialMTp(transaction);
+                }
+                await transaction.commit();
+                return m_tp;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
         }
 
         /**
@@ -68,8 +84,114 @@ module.exports = app => {
                 throw '数据错误';
             }
             delete data.in_time;
+            delete data.m_tp;
             // 判断是否可修改
-            return await this.db.update(this.tableName, data);
+            // 判断t_type是否为费用
+            const transaction = await this.db.beginTransaction();
+            try {
+                await transaction.update(this.tableName, data);
+                const m_tp = await this.calcMaterialMTp(transaction);
+                await transaction.commit();
+                return m_tp;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 更新新一期的quantity和截止上期金额并返回本期总金额
+         * @param transaction
+         * @param tid
+         * @param mid
+         * @returns {Promise<number>}
+         */
+        async updateNewMaterial(transaction, tid, mid, ctx, stage_id) {
+            const materialBillsData = await this.getAllDataByCondition({ where: { tid } });
+            let m_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);
+                m_tp = this.ctx.helper.add(m_tp, one_tp);
+            }
+            return m_tp;
+        }
+
+        /**
+         * 修改quantity,m_spread值和返回单条调差金额(新增一期)
+         * @param transaction
+         * @param mid
+         * @param mb
+         * @returns {Promise<*>}
+         */
+        async calcQuantityByMB(transaction, mid, mb, materialCalculator) {
+            if (mb.t_type === materialConst.t_type[0].value) {
+                const sql = 'SELECT SUM(`gather_qty`*`quantity`) as quantity FROM ' + this.ctx.service.materialList.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1';
+                const sqlParam = [mid, mb.id];
+                const mb_quantity = await transaction.queryOne(sql, sqlParam);
+                console.log(mb_quantity);
+                // 取历史期记录获取截止上期调差金额
+                const updateData = {
+                    id: mb.id,
+                    quantity: this.ctx.helper.round(mb_quantity.quantity, 3),
+                    pre_tp: mb.quantity && mb.m_spread !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, this.ctx.helper.mul(mb.quantity, mb.m_spread)), 2) : mb.pre_tp,
+                };
+                await transaction.update(this.tableName, updateData);
+                return await this.ctx.helper.round(this.ctx.helper.mul(mb_quantity.quantity, mb.m_spread), 2);
+            } else if (mb.t_type === materialConst.t_type[1].value) {
+                const quantity = await materialCalculator.calculateExpr(mb.expr);
+                const updateData = {
+                    id: mb.id,
+                    quantity: quantity !== 0 && quantity !== null ? this.ctx.helper.round(quantity, 3) : null,
+                    pre_tp: mb.quantity && mb.m_spread !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, this.ctx.helper.mul(mb.quantity, mb.m_spread)), 2) : mb.pre_tp,
+                };
+                await transaction.update(this.tableName, updateData);
+                return await this.ctx.helper.round(this.ctx.helper.mul(quantity, mb.m_spread), 2);
+            }
+        }
+
+        /**
+         * 修改 expr和quantity值,返回本期金额和单条数据
+         * @param data
+         * @returns {Promise<void>}
+         */
+        async updateFYQuantity(data) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            const transaction = await this.db.beginTransaction();
+            try {
+                const mbInfo = await this.getDataById(data.id);
+                await transaction.update(this.tableName, data);
+                let m_tp = this.ctx.material.m_tp;
+                if (mbInfo.quantity !== data.quantity) {
+                    m_tp = await this.calcMaterialMTp(transaction);
+                }
+                await transaction.commit();
+                const returnData = {
+                    m_tp,
+                    info: await this.getDataById(data.id),
+                }
+                return returnData;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        // 更改计算总金额并返回值
+        async calcMaterialMTp(transaction) {
+            // 金额发生变化,则重新计算本期金额
+            const sql = 'SELECT SUM(`m_spread`*`quantity`) as total_price FROM ' + this.tableName + ' WHERE `tid` = ?';
+            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,
+            };
+            await transaction.update(this.ctx.service.material.tableName, updateData2);
+            return tp.total_price;
         }
     }
 

+ 41 - 0
app/service/material_bills_history.js

@@ -0,0 +1,41 @@
+'use strict';
+
+/**
+ * 工料历史期数据表 数据模型
+ *
+ * @author Mai
+ * @date 2018/8/13
+ * @version
+ */
+
+
+module.exports = app => {
+    class MaterialBillsHistory extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'material_bills_history';
+        }
+
+        /**
+         * 获取历史本期应耗数量和上期调差金额
+         * @param mid
+         * @param order
+         * @param mb_id
+         * @returns {Promise<*[]>}
+         */
+        async getByMbId(mid, order, mb_id) {
+            const result = await this.getDataByCondition({ mid, order, mb_id });
+            if (result) {
+                return [result.quantity, result.pre_tp];
+            }
+            return [null, null];
+        }
+    }
+    return MaterialBillsHistory;
+};

+ 3 - 3
app/service/material_list.js

@@ -155,14 +155,13 @@ module.exports = app => {
             if (!mbInfo) {
                 throw '不存在该工料';
             }
-            const sql = 'SELECT SUM(`gather_qty`*`quantity`) as quantity FROM ' + this.tableName + ' WHERE `mid`=? AND `mb_id`=?';
+            const sql = 'SELECT SUM(`gather_qty`*`quantity`) as quantity FROM ' + this.tableName + ' WHERE `mid`=? AND `mb_id`=? AND `is_join`=1';
             const sqlParam = [this.ctx.material.id, mb_id];
             const mb_quantity = await transaction.queryOne(sql, sqlParam);
             console.log(mb_quantity);
-            mbInfo.quantity = this.ctx.helper.round(mb_quantity.quantity, 3);
             const updateData = {
                 id: mb_id,
-                quantity: mbInfo.quantity,
+                quantity: this.ctx.helper.round(mb_quantity.quantity, 3),
             };
             await transaction.update(this.ctx.service.materialBills.tableName, updateData);
             // 计算本期总金额
@@ -221,6 +220,7 @@ module.exports = app => {
                     mx_id: ml.mx_id,
                     gather_qty,
                     quantity: ml.quantity,
+                    is_join: ml.is_join,
                     in_time: new Date(),
                 };
                 copyMLArray.push(newMaterialList);

+ 75 - 16
app/service/material_list_notjoin.js

@@ -30,21 +30,30 @@ module.exports = app => {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
-            const newListNotJoin = {
-                tid: this.ctx.tender.id,
-                mid: this.ctx.material.id,
-                gcl_id: data.gcl_id,
-                xmj_id: data.id,
-                mx_id: data.mx_id !== undefined ? data.mx_id : '',
-                in_time: new Date(),
-            };
-
-            // 新增不参与调差清单
-            const result = await this.db.insert(this.tableName, newListNotJoin);
-            if (result.affectedRows === 0) {
-                throw '新增不参与调差清单数据失败';
+            const transaction = await this.db.beginTransaction();
+            try {
+                const newListNotJoin = {
+                    tid: this.ctx.tender.id,
+                    mid: this.ctx.material.id,
+                    gcl_id: data.gcl_id,
+                    xmj_id: data.id,
+                    mx_id: data.mx_id !== undefined ? data.mx_id : null,
+                    in_time: new Date(),
+                };
+                data.xmj_id = data.id;
+                data.mx_id = data.mx_id !== undefined ? data.mx_id : null;
+                await this.updateAllMaterials(transaction, data, 'add');
+                // 新增不参与调差清单
+                const result = await transaction.insert(this.tableName, newListNotJoin);
+                if (result.affectedRows === 0) {
+                    throw '新增不参与调差清单数据失败';
+                }
+                await transaction.commit();
+                return await this.getDataById(result.insertId);
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
             }
-            return await this.getDataById(result.insertId);
         }
 
         /**
@@ -56,8 +65,58 @@ module.exports = app => {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
-            // 判断是否可删
-            return await this.deleteById(id);
+            const transaction = await this.db.beginTransaction();
+            try {
+                const notJoinInfo = await this.getDataById(id);
+                await this.updateAllMaterials(transaction, notJoinInfo, 'del');
+                // 判断是否可删
+                const result = await transaction.delete(this.tableName, { id });
+                await transaction.commit();
+                return result;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
+         * 修改调差list和bill和material对应值
+         * @param transaction
+         * @returns {Promise<void>}
+         */
+        async updateAllMaterials(transaction, data, type) {
+            // 先判断material_list是否存在值并quantity不为null
+            const searchSql = {
+                mid: this.ctx.material.id,
+                gcl_id: data.gcl_id,
+                xmj_id: data.xmj_id,
+            };
+            if (data.mx_id !== null) {
+                searchSql.mx_id = data.mx_id;
+            }
+            const materialListData = await this.ctx.service.materialList.getAllDataByCondition({
+                where: searchSql,
+            });
+            console.log(data);
+            console.log(materialListData);
+            if (materialListData && materialListData.length !== 0) {
+                // 对应修改更新本期应耗数量值和总的本期金额计算
+                const mbIdList = [];
+                for (const ml of materialListData) {
+                    const updateData = {
+                        id: ml.id,
+                        is_join: type === 'add' ? 0 : 1,
+                    };
+                    if (mbIdList.indexOf(ml.mb_id) === -1) {
+                        mbIdList.push(ml.mb_id);
+                    }
+                    await transaction.update(this.ctx.service.materialList.tableName, updateData);
+                }
+                // 重新计算金额
+                for (const mb_id of mbIdList) {
+                    await this.service.materialList.calcQuantityByML(transaction, mb_id);
+                }
+            }
         }
 
         /**

+ 1 - 1
app/service/project_account.js

@@ -331,7 +331,7 @@ module.exports = app => {
                 const accountData = await this.db.select(this.tableName, {
                     where: {
                         account: data.account,
-                        project_id: data.enterprise_id,
+                        project_id: data.project_id,
                     },
                 });
                 if (accountData.length > 0) {

+ 59 - 12
app/service/stage.js

@@ -12,6 +12,7 @@ const auditConst = require('../const/audit').stage;
 const payConst = require('../const/deal_pay.js');
 const fs = require('fs');
 const path = require('path');
+const _ = require('lodash');
 
 module.exports = app => {
     class Stage extends app.BaseService {
@@ -176,7 +177,6 @@ module.exports = app => {
                 times: 1,
                 status: auditConst.status.uncheck,
                 user_id: this.ctx.session.sessionUser.accountId,
-                check_detail: true,
                 check_calc: false,
             };
             if (preStage) {
@@ -292,17 +292,6 @@ module.exports = app => {
             return calcBase;
         }
 
-        /**
-         * 更新 check_detail 标识
-         * @param {Integer}sid - 期id
-         * @param {Boolean}check - 标记
-         * @returns {Promise<void>}
-         */
-        async updateCheckDetailFlag(sid, check) {
-            const result = await this.db.update(this.tableName, {id: sid, check_detail: check});
-            return result.affectedRows === 1;
-        }
-
         async updateCheckCalcFlag(sid, check) {
             const result = await this.db.update(this.tableName, {id: sid, check_calc: check});
             return result.affectedRows === 1;
@@ -358,6 +347,64 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        /**
+         * 获取 多期的 计算基数 -(材料调差调用)
+         * @returns {Promise<any>}
+         */
+        async getMaterialCalcBase(stage_list, tenderInfo) {
+            const calcBase = JSON.parse(JSON.stringify(payConst.calcBase));
+            const param = tenderInfo.deal_param;
+            for (const cb of calcBase) {
+                switch (cb.code) {
+                    case 'htj':
+                        cb.value = param.contractPrice;
+                        break;
+                    case 'zlje':
+                        cb.value = param.zanLiePrice;
+                        break;
+                    case 'htjszl':
+                        cb.value = this.ctx.helper.sub(param.contractPrice, param.zanLiePrice);
+                        break;
+                    case 'kgyfk':
+                        cb.value = param.startAdvance;
+                        break;
+                    case 'clyfk':
+                        cb.value = param.materialAdvance;
+                        break;
+                    case 'bqwc':
+                        const sum = await this.ctx.service.stageBills.getSumTotalPriceByMaterial(stage_list);
+                        cb.value = this.ctx.helper.add(sum.contract_tp, sum.qc_tp);
+                        break;
+                    case 'ybbqwc':
+                        const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGclByMaterial(stage_list, '^1[0-9]{2}-');
+                        cb.value = this.ctx.helper.add(sumGcl.contract_tp, sumGcl.qc_tp);
+                        break;
+                    default:
+                        cb.value = 0;
+                }
+            }
+            return calcBase;
+        }
+
+        /**
+         * 获取必要的stage信息调用curTimes, curOrder, id , times, curAuditor(材料调差)
+         * @param stage_id_list
+         * @returns {Promise<void>}
+         */
+        async getStageMsgByStageId(stage_id_list) {
+            const list = [];
+            stage_id_list = stage_id_list.split(',');
+            for (const sid of stage_id_list) {
+                const stage = await this.getDataById(sid);
+                stage.auditors = await this.service.stageAudit.getAuditors(stage.id, stage.times);
+                stage.curAuditor = await this.service.stageAudit.getCurAuditor(stage.id, stage.times);
+                stage.curOrder = _.max(_.map(stage.auditors, 'order'));
+                stage.curTimes = stage.times;
+                list.push(stage);
+            }
+            return list;
+        }
     }
 
     return Stage;

+ 12 - 5
app/service/stage_audit.js

@@ -50,11 +50,18 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getAuditors(stageId, times = 1) {
-            const sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time` ' +
-                'FROM ?? AS la, ?? AS pa ' +
-                'WHERE la.`sid` = ? and la.`times` = ? and la.`aid` = pa.`id` order by la.`order`';
-            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, stageId, times];
-            return await this.db.query(sql, sqlParam);
+            const sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, g.`sort` ' +
+                'FROM ?? AS la, ?? AS pa, (SELECT `aid`,(@i:=@i+1) as `sort` FROM ??, (select @i:=0) as it WHERE `sid` = ? AND `times` = ? GROUP BY `aid`) as g ' +
+                'WHERE la.`sid` = ? and la.`times` = ? and la.`aid` = pa.`id` and g.`aid` = la.`aid` order by la.`order`';
+            const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.tableName, stageId, times, stageId, times];
+            const result = await this.db.query(sql, sqlParam);
+            const sql2 = 'SELECT COUNT(a.`aid`) as num FROM (SELECT `aid` FROM ?? WHERE `sid` = ? AND `times` = ? GROUP BY `aid`) as a';
+            const sqlParam2 = [this.tableName, stageId, times];
+            const count = await this.db.queryOne(sql2, sqlParam2);
+            for (const i in result) {
+                result[i].max_sort = count.num;
+            }
+            return result;
         }
 
         /**

+ 43 - 1
app/service/stage_bills.js

@@ -416,10 +416,52 @@ module.exports = app => {
                     ' WHERE Bills.lid = ?';
                 const sqlParam = [tid, sid, lid];
                 const result = await this.db.queryOne(sql, sqlParam);
-                gather_qty = this.ctx.helper.add(gather_qty, this.ctx.helper.add(result.contract_qty, result.qc_qty));
+                if (result) {
+                    gather_qty = this.ctx.helper.add(gather_qty, this.ctx.helper.add(result.contract_qty, result.qc_qty));
+                }
             }
             return gather_qty !== 0 ? gather_qty : null;
         }
+
+        async getSumTotalPriceByMaterial(stage_list) {
+            let contract_tp = 0;
+            let qc_tp = 0;
+            for (const stage of stage_list) {
+                const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp` FROM ' + this.tableName + ' As Bills ' +
+                    '  INNER JOIN ( ' +
+                    '    SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `lid` From ' + this.tableName +
+                    '      WHERE `times` <= ? AND `order` <= ?' +
+                    '      GROUP BY `lid`' +
+                    '  ) As MaxFilter ' +
+                    '  ON (Bills.times * ' + timesLen + ' + `order`) = MaxFilter.flow And Bills.lid = MaxFilter.lid' +
+                    '  WHERE Bills.sid = ?';
+                const sqlParam = [stage.curTimes, stage.curOrder, stage.id];
+                const result = await this.db.queryOne(sql, sqlParam);
+                if (result) {
+                    contract_tp = this.ctx.helper.add(contract_tp, result.contract_tp);
+                    qc_tp = this.ctx.helper.add(qc_tp, result.qc_tp);
+                }
+            }
+            return { contract_tp, qc_tp };
+        }
+
+        async getSumTotalPriceGclByMaterial(stage_list, regText) {
+            let contract_tp = 0;
+            let qc_tp = 0;
+            for (const stage of stage_list) {
+                let result = null;
+                if (regText) {
+                    result = await this.getSumTotalPriceFilter(stage, 'REGEXP', regText);
+                } else {
+                    result = await this.getSumTotalPriceFilter(stage, '<>', this.db.escape(''));
+                }
+                if (result) {
+                    contract_tp = this.ctx.helper.add(contract_tp, result.contract_tp);
+                    qc_tp = this.ctx.helper.add(qc_tp, result.qc_tp);
+                }
+            }
+            return { contract_tp, qc_tp };
+        }
     }
 
     return StageBills;

+ 44 - 4
app/service/stage_change.js

@@ -36,13 +36,17 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getLastestStageData(tid, sid, lid, pid) {
-            const sql = 'SELECT c.* FROM ' + this.tableName + ' As c ' +
+            const sql = 'SELECT c.*,' +
+                '  oc.code As c_code, oc.new_code As c_new_code' +
+                '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
                 '    SELECT MAX(`stimes`) As `stimes`, MAX(`sorder`) As `sorder`, `lid`, `pid`, `sid` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ? And lid = ? And pid = ?' +
                 '      GROUP By `lid`, `pid`' +
                 '  ) As m ' +
-                '  ON c.stimes = m.stimes And c.sorder = m.sorder And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`';
+                '  ON c.stimes = m.stimes And c.sorder = m.sorder And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`' +
+                '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
+                '  ON c.cid = oc.cid';
             const sqlParam = [tid, sid, lid, pid ? pid : -1];
             return await this.db.query(sql, sqlParam);
         }
@@ -58,17 +62,53 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getAuditorStageData(tid, sid, times, order, lid, pid) {
-            const sql = 'SELECT c.* FROM ' + this.tableName + ' As c ' +
+            const sql = 'SELECT c.*,' +
+                '  oc.code As c_code, oc.new_code As c_new_code' +
+                '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
                 '    SELECT MAX(`stimes`) As `stimes`, MAX(`sorder`) As `sorder`, `lid`, `pid`, `sid` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?)) And lid = ? And pid = ?' +
                 '      GROUP By `lid`, `pid`' +
                 '  ) As m ' +
-                '  ON c.stimes = m.stimes And c.sorder = m.sorder And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`';
+                '  ON c.stimes = m.stimes And c.sorder = m.sorder And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid`' +
+                '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
+                '  ON c.cid = oc.cid';
             const sqlParam = [tid, sid, times, times, order, lid, pid ? pid : -1];
             return await this.db.query(sql, sqlParam);
         }
 
+        async getLastestAllStageData(tid, sid) {
+            const sql = 'SELECT c.*,' +
+                '  oc.code As c_code, oc.new_code As c_new_code' +
+                '  FROM ' + this.tableName + ' As c ' +
+                '  INNER JOIN ( ' +
+                '    SELECT MAX(`stimes`) As `stimes`, MAX(`sorder`) As `sorder`, `lid`, `pid`, `sid` From ' + this.tableName +
+                '      WHERE tid = ? And sid = ?' +
+                '      GROUP By `lid`, `pid`' +
+                '  ) As m ' +
+                '  ON c.stimes = m.stimes And c.sorder = m.sorder And c.`sid` = m.`sid`' +
+                '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
+                '  ON c.cid = oc.cid';
+            const sqlParam = [tid, sid];
+            return await this.db.query(sql, sqlParam);
+        }
+
+        async getAuditorAllStageData(tid, sid, times, order) {
+            const sql = 'SELECT c.*, ' +
+                '  oc.code As c_code, oc.new_code As c_new_code' +
+                '  FROM ' + this.tableName + ' As c ' +
+                '  INNER JOIN ( ' +
+                '    SELECT MAX(`stimes`) As `stimes`, MAX(`sorder`) As `sorder`, `lid`, `pid`, `sid` From ' + this.tableName +
+                '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?))' +
+                '      GROUP By `lid`, `pid`' +
+                '  ) As m ' +
+                '  ON c.stimes = m.stimes And c.sorder = m.sorder And c.`sid` = m.`sid`' +
+                '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
+                '  ON c.cid = oc.cid';
+            const sqlParam = [tid, sid, times, times, order];
+            return await this.db.query(sql, sqlParam);
+        }
+
         /**
          * 台账,调用变更令
          *

+ 3 - 1
app/service/stage_pos.js

@@ -505,7 +505,9 @@ module.exports = app => {
                     ' WHERE Pos.lid = ? AND Pos.pid = ?';
                 const sqlParam = [tid, sid, tid, sid, lid, pid];
                 const result = await this.db.queryOne(sql, sqlParam);
-                gather_qty = this.ctx.helper.add(gather_qty, this.ctx.helper.add(result.contract_qty, result.qc_qty));
+                if (result) {
+                    gather_qty = this.ctx.helper.add(gather_qty, this.ctx.helper.add(result.contract_qty, result.qc_qty));
+                }
             }
             return gather_qty !== 0 ? gather_qty : null;
         }

+ 3 - 2
app/view/change/index.ejs

@@ -27,7 +27,7 @@
             <input id="tenderName" value="<%= tender.name %>" type="hidden">
             <input id="tenderId" value="<%= tender.id %>" type="hidden">
             <div class="sjs-height-0">
-                <table class="table">
+                <table class="table table-bordered">
                     <thead>
                     <tr>
                         <th width="32%">申请编号/变更令号</th><th width="30%">工程名称</th>
@@ -84,7 +84,8 @@
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'change.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 8 - 1
app/view/change/info.ejs

@@ -79,7 +79,7 @@
     <div class="scrollbar-auto">
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
-                <li class=""><a href="/tender/<%- tender.id %>/change"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
+                <li class=""><a class="text-primary" href="/tender/<%- tender.id %>/change"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
             </ul>
         </div>
         <div class="nav-box">
@@ -169,6 +169,7 @@
     </div>
     <div class="content-wrap tab-content">
         <div class="c-body tab-pane active" role="tabpanel" id="info">
+            <div class="sjs-height-0 container-fluid">
             <!--变更信息-->
             <% if (auditStatus === 1 || auditStatus === 2) { %>
             <form action="/change/save?_csrf=<%= ctx.csrf %>" method="post" id="change_form">
@@ -400,9 +401,11 @@
                 </div>
             </div>
             <% } %>
+            </div>
         </div>
 
         <div class="c-body tab-pane first-bill-pane" role="tabpanel" id="bills">
+            <div class="sjs-height-0">
             <!--变更清单-->
             <% if (auditStatus === 1 || auditStatus === 2) { %>
             <table class="table table-striped table-bordered nowrap qd-table table-list" id="tablelist" cellspacing="0" style="width:100%">
@@ -677,9 +680,11 @@
                     </tfoot>
                 </table>
             <% } %>
+            </div>
         </div>
 
         <div class="c-body tab-pane" role="tabpanel" id="files">
+            <div class="sjs-height-0">
             <table class="table table-bordered">
                 <thead>
                 <tr>
@@ -708,6 +713,7 @@
                 <% } %>
                 </tbody>
             </table>
+            </div>
         </div>
     </div>
 </div>
@@ -715,6 +721,7 @@
     let table = '';
     const totalPriceUnit = '<%- tpUnit %>';
     const unitPriceUnit = '<%- upUnit %>';
+    autoFlashHeight();
 </script>
 <script src="/public/js/datatable/jquery.dataTables.min.js"></script>
 <script src="/public/js/datatable/dataTables.bootstrap4.min.js"></script>

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

@@ -18,7 +18,7 @@
                     <% } %>
                 </div>
                 <div class="alert alert-warning" role="alert">修改后,已创建的变更不受影响。</div>
-                <p><button class="btn btn-primary btn-sm" id="addcompany" role="button" title="填写公司"><b class="fa fa-plus"></b></button></p>
+                <p><button class="btn btn-primary btn-sm" id="addcompany" role="button" title="填写名称"><b class="fa fa-plus"></b></button></p>
                 <div id="companyadddiv">
                     <!--<input type="text" class="form-control form-control-sm" placeholder="请输入公司名称">-->
                 </div>
@@ -580,7 +580,7 @@
             </div>
             <div class="modal-body">
                 <p>大小限制:30MB,支持office等文档格式、图片格式、压缩包格式</p>
-                <p><input class="btn btn-primary btn-sm" value="选择文件" type="file" id="upload-file" multiple /></p>
+                <p><input value="选择文件" type="file" id="upload-file" multiple /></p>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">取消</button>

+ 67 - 57
app/view/ledger/audit_modal.ejs

@@ -90,14 +90,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- user.name %>  <small class="text-muted"><%- user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- user.name %>  <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
                                 </li>
                                 <% for (let i = 0; i < auditors.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < auditors.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1)%>审</span>
                                     <% } else {%>
-                                    <i class="fa fa fa-stop-circle"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -111,41 +111,47 @@
                                 <% for (let iA = 0; iA < ah.length; iA++) { %>
                                     <% if (iA === 0) { %>
                                         <li class="list-group-item">
-                                            <span class="text-success pull-right"><% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
-                                            <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                            <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
+                                            <h5 class="card-title">
+                                                <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <span class="text-success"><small><%- ah[iA].begin_time.toLocaleDateString() %></small> <% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
+                                            </div>
                                         </li>
                                         <li class="list-group-item">
-                                            <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                            <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                            <% } %>
-                                            <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                            <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                            <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                            <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                            <% } %>
+                                            <h5 class="card-title">
+                                                <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
                                         </li>
                                     <% } else if (iA === ah.length - 1) { %>
                                         <li class="list-group-item">
-                                            <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                            <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                            <% } %>
-                                            <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                            <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                            <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                            <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                            <% } %>
+                                            <h5 class="card-title">
+                                                <i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right">终审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
                                         </li>
                                     <% } else { %>
                                         <li class="list-group-item">
-                                            <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                            <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                            <% } %>
-                                            <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                            <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                            <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                            <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                            <% } %>
+                                            <h5 class="card-title">
+                                                <i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
                                         </li>
                                     <% } %>
                                 <% } %>
@@ -158,41 +164,45 @@
                                 <% for (let iA = 0; iA < auditors.length; iA++) { %>
                                     <% if (iA === 0) { %>
                                     <li class="list-group-item">
-                                        <span class="text-success pull-right"><% if (tender.ledger_times > 1) { %>重新<% } %>上报</span>
-                                        <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].begin_time.toLocaleDateString() %></small></p>
+                                        <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span></h5>
+                                        <div class="ml-3">
+                                            <span class="text-success"><small><%- auditors[iA].begin_time.toLocaleDateString() %></small> <% if (tender.ledger_times > 1) { %>重新<% } %>上报</span>
+                                        </div>
                                     </li>
                                     <li class="list-group-item">
-                                        <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                        <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                        <% } %>
-                                        <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                        <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                        <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                        <% } %>
+                                        <h5 class="card-title">
+                                            <i class="fa <%if (iA === auditors.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%- auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
+                                        </h5>
+                                        <div class="ml-3">
+                                            <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                                <span class="<%- auditConst.statusClass[auditors[iA].status] %>"> <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                            <% } %>
+                                            <p class="card-text"><%- auditors[iA].opinion %></p>
+                                        </div>
                                     </li>
                                     <% } else if (iA === auditors.length - 1) { %>
                                     <li class="list-group-item">
-                                        <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                        <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                        <% } %>
-                                        <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                        <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                        <p class="card-text"><%- auditors[iA].opinion %></p>
-                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                        <% } %>
+                                        <h5 class="card-title">
+                                            <i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right">终审</span>
+                                        </h5>
+                                        <div class="ml-3">
+                                            <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                                <span class="<%- auditConst.statusClass[auditors[iA].status] %>"> <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                            <% } %>
+                                            <p class="card-text"><%- auditors[iA].opinion %></p>
+                                        </div>
                                     </li>
                                     <% } else { %>
                                     <li class="list-group-item">
-                                        <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                        <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                        <% } %>
-                                        <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                        <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                        <p class="card-text"><%- auditors[iA].opinion %></p>
-                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                        <% } %>
+                                        <h5 class="card-title">
+                                            <i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%- auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
+                                        </h5>
+                                        <div class="ml-3">
+                                            <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                                <span class="<%- auditConst.statusClass[auditors[iA].status] %>"> <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                            <% } %>
+                                            <p class="card-text"><%- auditors[iA].opinion %></p>
+                                        </div>
                                     </li>
                                     <% } %>
                                 <% } %>

+ 137 - 114
app/view/ledger/explode_modal.ejs

@@ -147,16 +147,16 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- user.name %>  <small class="text-muted"><%- user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- user.name %>  <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
                                 </li>
                             </ul>
                             <ul class="list-group list-group-flush" id="auditors-list">
                                 <% for (let i = 0; i < auditorList.length; i++) { %>
                                     <li class="list-group-item" data-auditid="<%- auditorList[i].audit_id %>">
                                         <% if (i < auditorList.length - 1) { %>
-                                            <i class="fa fa-chevron-circle-down"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small>
+                                            <i class="fa fa-chevron-circle-down"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1)%>审</span>
                                         <% } else {%>
-                                            <i class="fa fa fa-stop-circle"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small>
+                                            <i class="fa fa fa-stop-circle"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small><span class="pull-right">终审</span>
                                         <% } %>
                                     </li>
                                 <% } %>
@@ -170,41 +170,47 @@
                                     <% for (let iA = 0; iA < ah.length; iA++) { %>
                                         <% if (iA === 0) { %>
                                             <li class="list-group-item">
-                                                <span class="text-success pull-right"><% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
-                                                <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                                <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
+                                                <h5 class="card-title">
+                                                    <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
+                                                </h5>
+                                                <div class="ml-3">
+                                                    <span class="text-success"><small><%- ah[iA].begin_time.toLocaleDateString() %></small> <% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
+                                                </div>
                                             </li>
                                             <li class="list-group-item">
-                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                                <% } %>
-                                                <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                                <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                                <% } %>
+                                                <h5 class="card-title">
+                                                    <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                                </h5>
+                                                <div class="ml-3">
+                                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                        <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                    <% } %>
+                                                    <p class="card-text"><%- ah[iA].opinion %></p>
+                                                </div>
                                             </li>
                                         <% } else if (iA === ah.length - 1) { %>
                                             <li class="list-group-item">
-                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                                <% } %>
-                                                <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                                <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                                <% } %>
+                                                <h5 class="card-title">
+                                                    <i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right">终审</span>
+                                                </h5>
+                                                <div class="ml-3">
+                                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                        <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                    <% } %>
+                                                    <p class="card-text"><%- ah[iA].opinion %></p>
+                                                </div>
                                             </li>
                                         <% } else { %>
                                             <li class="list-group-item">
-                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                                <% } %>
-                                                <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                                <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                                <% } %>
+                                                <h5 class="card-title">
+                                                    <i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                                </h5>
+                                                <div class="ml-3">
+                                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                        <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                    <% } %>
+                                                    <p class="card-text"><%- ah[iA].opinion %></p>
+                                                </div>
                                             </li>
                                         <% } %>
                                     <% } %>
@@ -215,20 +221,27 @@
                             <div class="card mt-3">
                                 <ul class="list-group list-group-flush">
                                     <li class="list-group-item">
-                                        <span class="pull-right">重新上报中</span>
-                                        <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                        <p class="card-text"><small class="text-muted"></small></p>
+                                        <h5 class="card-title">
+                                            <i class="fa fa-play-circle fa-rotate-90"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
+                                        </h5>
+                                        <div class="ml-3">
+                                            <span>重新上报中</span>
+                                        </div>
                                     </li>
                                 </ul>
                                 <ul class="list-group list-group-flush" id="auditors-list2">
                                     <% for (let iA = 0; iA < auditorList.length; iA++) { %>
                                         <% if (iA === auditorList.length - 1) { %>
                                             <li class="list-group-item" data-auditid="<%- auditorList[iA].audit_id %>">
-                                                <h5 class="card-title"><i class="fa fa-stop-circle"></i> <%- auditorList[iA].name %> <small class="text-muted"><%- auditorList[iA].role %></small></h5>
+                                                <h5 class="card-title">
+                                                    <i class="fa fa-stop-circle"></i> <%- auditorList[iA].name %> <small class="text-muted"><%- auditorList[iA].role %></small><span class="pull-right">终审</span>
+                                                </h5>
                                             </li>
                                         <% } else { %>
                                             <li class="list-group-item" data-auditid="<%- auditorList[iA].audit_id %>">
-                                                <h5 class="card-title"><i class="fa fa-chevron-circle-down"></i> <%- auditorList[iA].name %> <small class="text-muted"><%- auditorList[iA].role %></small></h5>
+                                                <h5 class="card-title">
+                                                    <i class="fa fa-chevron-circle-down"></i> <%- auditorList[iA].name %> <small class="text-muted"><%- auditorList[iA].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(iA+1) %>审</span>
+                                                </h5>
                                             </li>
                                         <% } %>
                                     <% } %>
@@ -261,14 +274,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- user.name %>  <small class="text-muted"><%- user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- user.name %>  <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
                                 </li>
                                 <% for (let i = 0; i < auditors.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < auditors.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                     <% } else {%>
-                                    <i class="fa fa fa-stop-circle"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- auditors[i].name %>  <small class="text-muted"><%- auditors[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -280,45 +293,51 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <% for (let iA = 0; iA < ah.length; iA++) { %>
-                                <% if (iA === 0) { %>
-                                <li class="list-group-item">
-                                    <span class="text-success pull-right"><% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
-                                </li>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else if (iA === ah.length - 1) { %>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else { %>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
+                                    <% if (iA === 0) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <span class="text-success"><small><%- ah[iA].begin_time.toLocaleDateString() %></small> <% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
+                                            </div>
+                                        </li>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else if (iA === ah.length - 1) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right">终审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
                                     <% } %>
-                                </li>
-                                <% } %>
                                 <% } %>
                             </ul>
                         </div>
@@ -327,45 +346,49 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <% for (let iA = 0; iA < auditors.length; iA++) { %>
-                                <% if (iA === 0) { %>
-                                <li class="list-group-item">
-                                    <span class="text-success pull-right"><% if (tender.ledger_times > 1) { %>重新<% } %>上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].begin_time.toLocaleDateString() %></small></p>
-                                </li>
-                                <li class="list-group-item">
-                                    <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                    <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else if (iA === auditors.length - 1) { %>
-                                <li class="list-group-item">
-                                    <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                    <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else { %>
-                                <li class="list-group-item">
-                                    <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                    <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
+                                    <% if (iA === 0) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small><span class="pull-right">原报</span></h5>
+                                            <div class="ml-3">
+                                                <span class="text-success"><small><%- auditors[iA].begin_time.toLocaleDateString() %></small> <% if (tender.ledger_times > 1) { %>重新<% } %>上报</span>
+                                            </div>
+                                        </li>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa <%if (iA === auditors.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%- auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %>"> <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else if (iA === auditors.length - 1) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right">终审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %>"> <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%- auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %>"> <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- auditors[iA].opinion %></p>
+                                            </div>
+                                        </li>
                                     <% } %>
-                                </li>
-                                <% } %>
                                 <% } %>
                             </ul>
                         </div>

+ 206 - 162
app/view/material/audit_modal.ejs

@@ -65,14 +65,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small><div class="pull-right">原报</div>
                                 </li>
                                 <% for (let i = 0; i < ctx.material.auditors2.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < ctx.material.auditors2.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                     <% } else { %>
-                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -83,29 +83,41 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <span class="text-success pull-right"><small><%- ctx.material.auditors[0].begin_time.toLocaleDateString() %></small> 上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small></h5>
+                                    <h5 class="card-title">
+                                        <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <span class="text-success"><small><%- ctx.material.auditors[0].begin_time.toLocaleDateString() %></small> 上报</span>
+                                    </div>
                                 </li>
                                 <% for (let iA = 0; iA < ctx.material.auditors.length; iA++) { %>
                                 <% const auditors = ctx.material.auditors; %>
                                 <li class="list-group-item">
                                     <% if (auditors[iA].status === auditConst.status.checked) { %>
-                                    <span class="text-success pull-right"><small><%- auditors[iA].end_time.toLocaleString() %></small> 审批通过</span>
                                     <h5 class="card-title">
-                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-success' : 'fa fa-stop-circle text-success') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small>
+                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-success' : 'fa fa-stop-circle text-success') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%= auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
                                     </h5>
+                                    <div class="ml-3">
+                                        <span class="text-success"><small><%- auditors[iA].end_time.toLocaleDateString() %></small> 审批通过</span>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                     <% } else if (auditors[iA].stauts == auditConst.status.checking) { %>
-                                    <span class="pull-right">审批中</span>
                                     <h5 class="card-title">
-                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small>
+                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%= auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
                                     </h5>
+                                    <div class="ml-3">
+                                        <span>审批中</span>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                     <% } else { %>
                                     <h5 class="card-title">
-                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small>
+                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%= auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
                                     </h5>
+                                    <div class="ml-3">
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                     <% } %>
                                     <% if (auditors[iA].status === auditConst.status.checked) { %>
-                                    <p class="card-text"><%- auditors[iA].opinion %></p>
                                     <% } else if (auditors[iA].status === auditConst.status.checking) { %>
                                     <div class="form-group">
                                         <label>审批意见<b class="text-danger">*</b></label>
@@ -141,14 +153,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
                                 </li>
                                 <% for (let i = 0; i < ctx.material.auditors2.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < ctx.material.auditors2.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                     <% } else { %>
-                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -166,22 +178,30 @@
                                 <% const auditors = ctx.material.auditors; %>
                                 <li class="list-group-item">
                                     <% if (auditors[iA].status === auditConst.status.checked) { %>
-                                    <span class="text-success pull-right"><small><%- auditors[iA].end_time.toLocaleString() %></small> 审批通过</span>
                                     <h5 class="card-title">
-                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-success' : 'fa fa-stop-circle text-success') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small>
+                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down text-success' : 'fa fa-stop-circle text-success') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%= auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
                                     </h5>
+                                    <div class="ml-3">
+                                        <span class="text-success"><small><%- auditors[iA].end_time.toLocaleDateString() %></small> 审批通过</span>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                     <% } else if (auditors[iA].stauts == auditConst.status.checking) { %>
-                                    <span class="pull-right">审批中</span>
                                     <h5 class="card-title">
-                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small>
+                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%= auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
                                     </h5>
+                                    <div class="ml-3">
+                                        <span>审批中</span>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                     <% } else { %>
                                     <h5 class="card-title">
-                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small>
+                                        <i class="<%- (iA < auditors.length - 1 ? 'fa fa-chevron-circle-down' : 'fa fa-stop-circle') %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right"><%= auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
                                     </h5>
+                                    <div class="ml-3">
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                     <% } %>
                                     <% if (auditors[iA].status === auditConst.status.checked) { %>
-                                    <p class="card-text"><%- auditors[iA].opinion %></p>
                                     <% } else if (auditors[iA].status === auditConst.status.checking) { %>
                                     <div class="form-group">
                                         <label>审批意见<b class="text-danger">*</b></label>
@@ -218,14 +238,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
                                 </li>
                                 <% for (let i = 0; i < ctx.material.auditors2.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < ctx.material.auditors2.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                     <% } else { %>
-                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -239,41 +259,47 @@
                                 <% for (let iA = 0; iA < ah.length; iA++) { %>
                                 <% if (iA === 0) { %>
                                 <li class="list-group-item">
-                                    <span class="text-success pull-right"><% if (ctx.material.auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small></h5>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
+                                    <h5 class="card-title">
+                                        <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <span class="text-success"><small><%- ah[iA].begin_time.toLocaleDateString() %></small> <% if (ctx.material.auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
+                                    </div>
                                 </li>
                                 <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
+                                    <h5 class="card-title">
+                                        <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                            <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                        <% } %>
+                                        <p class="card-text"><%- ah[iA].opinion %></p>
+                                    </div>
                                 </li>
                                 <% } else if (iA === ah.length - 1) { %>
                                 <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
+                                    <h5 class="card-title">
+                                        <i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right">终审</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                            <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                        <% } %>
+                                        <p class="card-text"><%- ah[iA].opinion %></p>
+                                    </div>
                                 </li>
                                 <% } else { %>
                                 <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
+                                    <h5 class="card-title">
+                                        <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                            <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                        <% } %>
+                                        <p class="card-text"><%- ah[iA].opinion %></p>
+                                    </div>
                                 </li>
                                 <% } %>
                                 <% } %>
@@ -287,41 +313,47 @@
                                 <% for (let iA = 0; iA < auditors.length; iA++) { %>
                                 <% if (iA === 0) { %>
                                 <li class="list-group-item">
-                                    <span class="text-success pull-right"><% if (ctx.material.times > 1) { %>重新<% } %>上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small></h5>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].begin_time.toLocaleDateString() %></small></p>
+                                    <h5 class="card-title">
+                                        <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <span class="text-success"><small><%- auditors[iA].begin_time.toLocaleDateString() %></small> <% if (ctx.material.times > 1) { %>重新<% } %>上报</span>
+                                    </div>
                                 </li>
                                 <li class="list-group-item">
-                                    <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa <%if (iA === auditors.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                    <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
+                                    <h5 class="card-title">
+                                        <i class="fa <%if (iA === auditors.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><%- auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                            <span class="<%- auditConst.statusClass[auditors[iA].status] %>"><% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                        <% } %>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                 </li>
                                 <% } else if (iA === auditors.length - 1) { %>
                                 <li class="list-group-item">
-                                    <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                    <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
+                                    <h5 class="card-title">
+                                        <i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><span class="pull-right">终审</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                            <span class="<%- auditConst.statusClass[auditors[iA].status] %>"><% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                        <% } %>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                 </li>
                                 <% } else { %>
                                 <li class="list-group-item">
-                                    <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[auditors[iA].status] %> pull-right"><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
-                                    <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- auditors[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
+                                    <h5 class="card-title">
+                                        <i class="fa <%if (iA === auditors.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small><%- auditors[iA].sort === auditors[iA].max_sort ? '终' : ctx.helper.transFormToChinese(auditors[iA].sort) %>审</span>
+                                    </h5>
+                                    <div class="ml-3">
+                                        <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
+                                            <span class="<%- auditConst.statusClass[auditors[iA].status] %>"><% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %><small><%- auditors[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[auditors[iA].status]%><% if (auditors[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                        <% } %>
+                                        <p class="card-text"><%- auditors[iA].opinion %></p>
+                                    </div>
                                 </li>
                                 <% } %>
                                 <% } %>
@@ -352,14 +384,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
                                 </li>
                                 <% for (let i = 0; i < ctx.material.auditors2.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < ctx.material.auditors2.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                     <% } else { %>
-                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -371,45 +403,51 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <% for (let iA = 0; iA < ah.length; iA++) { %>
-                                <% if (iA === 0) { %>
-                                <li class="list-group-item">
-                                    <span class="text-success pull-right"><% if (ctx.material.auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small></h5>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
-                                </li>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else if (iA === ah.length - 1) { %>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else { %>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
+                                    <% if (iA === 0) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <span class="text-success"><small><%- ah[iA].begin_time.toLocaleDateString() %></small> <% if (ctx.material.auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
+                                            </div>
+                                        </li>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else if (iA === ah.length - 1) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right">终审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else { %>
+                                    <li class="list-group-item">
+                                        <h5 class="card-title">
+                                            <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                        </h5>
+                                        <div class="ml-3">
+                                            <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                            <% } %>
+                                            <p class="card-text"><%- ah[iA].opinion %></p>
+                                        </div>
+                                    </li>
                                     <% } %>
-                                </li>
-                                <% } %>
                                 <% } %>
                             </ul>
                         </div>
@@ -437,14 +475,14 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <li class="list-group-item">
-                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small>
+                                    <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
                                 </li>
                                 <% for (let i = 0; i < ctx.material.auditors2.length; i++) { %>
                                 <li class="list-group-item">
                                     <% if (i < ctx.material.auditors2.length - 1) { %>
-                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa-chevron-circle-down"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                     <% } else { %>
-                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small>
+                                    <i class="fa fa fa-stop-circle"></i> <%- ctx.material.auditors2[i].name %>  <small class="text-muted"><%- ctx.material.auditors2[i].role %></small><span class="pull-right">终审</span>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -456,45 +494,51 @@
                         <div class="card mt-3">
                             <ul class="list-group list-group-flush">
                                 <% for (let iA = 0; iA < ah.length; iA++) { %>
-                                <% if (iA === 0) { %>
-                                <li class="list-group-item">
-                                    <span class="text-success pull-right"><% if (ctx.material.auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
-                                    <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small></h5>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
-                                </li>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else if (iA === ah.length - 1) { %>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
-                                    <% } %>
-                                </li>
-                                <% } else { %>
-                                <li class="list-group-item">
-                                    <% if (ah[iA].status !== auditConst.status.uncheck) { %>
-                                    <span class="<%- auditConst.statusClass[ah[iA].status] %> pull-right"><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
-                                    <% } %>
-                                    <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
-                                    <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text mb-1"><%- ah[iA].opinion %></p>
-                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
+                                    <% if (iA === 0) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- ctx.material.user.name %> <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <span class="text-success"><small><%- ah[iA].begin_time.toLocaleDateString() %></small> <% if (ctx.material.auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
+                                            </div>
+                                        </li>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else if (iA === ah.length - 1) { %>
+                                        <li class="list-group-item">
+                                            <h5 class="card-title">
+                                                <i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right">终审</span>
+                                            </h5>
+                                            <div class="ml-3">
+                                                <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                    <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                                <% } %>
+                                                <p class="card-text"><%- ah[iA].opinion %></p>
+                                            </div>
+                                        </li>
+                                    <% } else { %>
+                                    <li class="list-group-item">
+                                        <h5 class="card-title">
+                                            <i class="fa <%if (iA === ah.length - 1) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small><span class="pull-right"><%= ah[iA].sort === ah[iA].max_sort ? '终' : ctx.helper.transFormToChinese(ah[iA].sort) %>审</span>
+                                        </h5>
+                                        <div class="ml-3">
+                                            <% if (ah[iA].status !== auditConst.status.uncheck) { %>
+                                                <span class="<%- auditConst.statusClass[ah[iA].status] %>"><% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %><small><%- ah[iA].end_time.toLocaleDateString() %></small> <% } %><%- auditConst.statusString[ah[iA].status]%><% if (ah[iA].status === auditConst.status.checkNo) { %> <%- ctx.material.user.name %><% } %></span>
+                                            <% } %>
+                                            <p class="card-text"><%- ah[iA].opinion %></p>
+                                        </div>
+                                    </li>
                                     <% } %>
-                                </li>
-                                <% } %>
                                 <% } %>
                             </ul>
                         </div>
@@ -523,7 +567,7 @@
                             <div class="card mt-3">
                                 <ul class="list-group list-group-flush">
                                     <li class="list-group-item">
-                                        <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small>
+                                        <i class="fa fa fa-play-circle fa-rotate-90"></i> <%- ctx.material.user.name %>  <small class="text-muted"><%- ctx.material.user.role %></small><span class="pull-right">原报</span>
                                     </li>
                                 </ul>
                                 <ul class="list-group list-group-flush" id="auditors-list">
@@ -531,9 +575,9 @@
                                     <% for (let i = 0; i < auditorList.length; i++) { %>
                                         <li class="list-group-item" data-auditid="<%- auditorList[i].aid %>">
                                             <% if (i < auditorList.length - 1) { %>
-                                                <i class="fa fa-chevron-circle-down"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small>
+                                                <i class="fa fa-chevron-circle-down"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small><span class="pull-right"><%= ctx.helper.transFormToChinese(i+1) %>审</span>
                                             <% } else { %>
-                                                <i class="fa fa fa-stop-circle"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small>
+                                                <i class="fa fa fa-stop-circle"></i> <%- auditorList[i].name %>  <small class="text-muted"><%- auditorList[i].role %></small><span class="pull-right">终审</span>
                                             <% } %>
                                         </li>
                                     <% } %>

+ 2 - 1
app/view/material/index.ejs

@@ -74,7 +74,8 @@
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'measure.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 7 - 2
app/view/material/info.ejs

@@ -48,7 +48,7 @@
                         <div class="col-4 p-0">
                             <table class="table table-sm table-bordered">
                                 <tr><th></th><th>本期金额</th><th>截止本期金额</th></tr>
-                                <tr><td>材料价差费用</td><td><%= material.m_tp %></td><td><%= material.m_tp !== null ? ctx.helper.round(ctx.helper.add(material.pre_tp, material.m_tp), 2) : null %></td></tr>
+                                <tr id="tp_set"><td>材料价差费用</td><td><%= material.m_tp %></td><td><%= material.m_tp !== null ? ctx.helper.round(ctx.helper.add(material.pre_tp, material.m_tp), 2) : null %></td></tr>
                                 <tr id="rate_set"><td>材料价差费用(含税)</td><td><%= material.m_tp !== null ? ctx.helper.mul(material.m_tp, 1+material.rate/100) : null %></td><td><%= material.m_tp !== null ? ctx.helper.round(ctx.helper.mul(ctx.helper.add(material.pre_tp, material.m_tp), 1+material.rate/100), 2) : null %></td></tr>
                             </table>
                         </div>
@@ -58,6 +58,10 @@
         </div>
     </div>
 </div>
+<div style="display: none">
+    <img src="/public/images/ellipsis_horizontal.png" id="ellipsis-icon" />
+    <img src="/public/images/icon-ok.png" id="icon-ok" />
+</div>
 <% if ((material.status === auditConst.status.uncheck || material.status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === material.user_id) {%>
 <script>
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
@@ -69,6 +73,7 @@
     const materialListData = JSON.parse('<%- JSON.stringify(materialListData) %>');
     const readOnly = <%- material.readOnly %>;
     const materialID = <%- material.id %>;
-    const m_tp = <%= material.m_tp !== null ? material.m_tp : 0 %>;
+    let m_tp = <%= material.m_tp !== null ? material.m_tp : 0 %>;
     const pre_tp = <%= material.pre_tp !== null ? material.pre_tp : 0 %>;
+    const calcBase = JSON.parse('<%- JSON.stringify(calcBase) %>');
 </script>

+ 34 - 1
app/view/material/info_modal.ejs

@@ -1,2 +1,35 @@
-
+<!--消耗量计算-->
+<div class="modal fade" id="bcyy" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">消耗量计算</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <input class="form-control" value="" id="expr" type="text">
+                    <p class="form-text" id="expr_select">
+                        <button class="btn btn-outline-primary btn-sm">+</button>
+                        <button class="btn btn-outline-primary btn-sm">-</button>
+                        <button class="btn btn-outline-primary btn-sm">*</button>
+                        <button class="btn btn-outline-primary btn-sm">/</button>
+                        <button class="btn btn-outline-primary btn-sm">(</button>
+                        <button class="btn btn-outline-primary btn-sm">)</button>
+                    </p>
+                </div>
+                <table class="table table-sm table-bordered">
+                    <tr><th>基数</th><th>代号</th><th>值</th></tr>
+                    <% for (let iBase = 0; iBase < calcBase.length; iBase++) { %>
+                    <tr><td><%- calcBase[iBase].name %></td><td><%- calcBase[iBase].code %></td><td><%- calcBase[iBase].value %></td></tr>
+                    <% } %>
+                </table>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" id="materialbillsId" value="" />
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary" id="expr_btn">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
 <% include ./audit_modal.ejs %>

+ 1 - 1
app/view/material/material_sub_menu.ejs

@@ -7,7 +7,7 @@
     <div class="scrollbar-auto">
         <div class="nav-box">
                 <ul class="nav-list list-unstyled">
-                    <li class=""><a href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
+                    <li class=""><a class="text-primary" href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
                 </ul>
             </div>
         <div class="nav-box">

+ 1 - 1
app/view/material/material_sub_mini_menu.ejs

@@ -6,7 +6,7 @@
     <div class="side-menu" id="mini-menu-list" style="display: none">
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
-                <li class=""><a href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
+                <li class=""><a class="text-primary" href="/tender/<%- ctx.tender.id %>/measure/material"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
             </ul>
         </div>
         <div class="nav-box">

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

@@ -82,7 +82,8 @@
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'measure.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 2 - 1
app/view/report/index.ejs

@@ -142,7 +142,8 @@
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'report.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 2 - 1
app/view/revise/index.ejs

@@ -80,7 +80,8 @@
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'revise.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');

+ 1 - 1
app/view/setting/info.ejs

@@ -25,7 +25,7 @@
                             <input class="form-control form-control-sm" value="<%= projectData.user_account %>" type="text" readonly>
                         </div>
                         <div class="form-group">
-                            <label>销售负责人</label>
+                            <label>负责人</label>
                             <div class="card w-50">
                                 <div class="card-body">
                                     <h4 class="card-title"><%= salesmanData.username %></h4>

+ 4 - 8
app/view/stage/audit_btn.ejs

@@ -1,13 +1,9 @@
 <div class="contarl-box">
     <% if (ctx.stage.status === auditConst.status.uncheck) { %>
-        <% if (ctx.session.sessionUser.accountId === ctx.stage.user_id && ctx.stage.check_detail === 0) { %>
-            <a id="sub-sp-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm btn-block">上报审批</a>
-        <% } else if (ctx.session.sessionUser.accountId === ctx.stage.user_id && ctx.stage.check_detail === 1) {%>
-            <a id="sub-sp-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sub-sp3" class="btn btn-primary btn-sm btn-block">上报审批</a>
-        <% } %>
+    <a id="sub-sp-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm btn-block">上报审批</a>
     <% } else if (ctx.stage.status === auditConst.status.checking) { %>
         <% if (ctx.stage.curAuditor && ctx.stage.curAuditor.aid === ctx.session.sessionUser.accountId) { %>
-            <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="<%- (ctx.stage.check_detail === 0 ? '#sp-done' : '#sub-sp3') %>" class="btn btn-success btn-sm btn-block">审批通过</a>
+            <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm btn-block">审批通过</a>
             <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm btn-block">审批退回</a>
         <% } else { %>
             <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm btn-block">审批中</a>
@@ -17,12 +13,12 @@
     <% } else if (ctx.stage.status === auditConst.status.checkNo) { %>
         <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm btn-block text-muted">审批退回</a>
         <% if (ctx.session.sessionUser.accountId === ctx.stage.user_id) { %>
-            <a id="sp-list2-btn" href="javascript: void(0);" data-toggle="modal" data-target="<%- (ctx.stage.check_detail === 0 ? '#sp-list2' : '#sub-sp3') %>" class="btn btn-primary btn-sm btn-block">重新上报</a>
+            <a id="sp-list2-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-list2" class="btn btn-primary btn-sm btn-block">重新上报</a>
         <% } %>
     <% } else if (ctx.stage.status === auditConst.status.checkNoPre) { %>
         <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm btn-block text-muted">审批退回</a>
         <% if (ctx.session.sessionUser.accountId === ctx.stage.curAuditor.aid) { %>
-            <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="<%- (ctx.stage.check_detail === 0 ? '#sp-done' : '#sub-sp3') %>" class="btn btn-success btn-sm btn-block">审批通过</a>
+            <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm btn-block">审批通过</a>
             <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm btn-block">审批退回</a>
         <% } %>
     <% } %>

File diff suppressed because it is too large
+ 1071 - 981
app/view/stage/audit_modal.ejs


+ 13 - 11
app/view/stage/detail.ejs

@@ -55,24 +55,24 @@
                                 <input class="form-control form-control-sm" type="text" readonly="" id="bgl-code">
                             </div>
                             <div class="form-group">
-                                <label>部位:</label>
-                                <input class="form-control form-control-sm" type="text" readonly="" value="" id="bw-name">
+                                <label>变更图号:</label>
+                                <input class="form-control  form-control-sm" type="text" readonly="" id="bgl-drawing-code">
                             </div>
                             <div class="form-group">
-                                <label>起始桩号:</label>
-                                <input class="form-control form-control-sm" type="text" readonly="" value="" id="start-peg">
+                                <label>部位:</label>
+                                <input class="form-control form-control-sm" type="text" readonly="" id="bw-name">
                             </div>
                             <div class="form-group">
-                                <label>止桩号:</label>
-                                <input class="form-control form-control-sm" type="text" readonly="" value="" id="end-peg">
+                                <label>止桩号:</label>
+                                <input class="form-control form-control-sm" type="text" readonly="" id="peg">
                             </div>
                             <div class="form-group">
-                                <label>计量单元:</label>
-                                <input class="form-control form-control-sm" type="text" readonly="" value="" id="unit-name">
+                                <label>细目:</label>
+                                <input class="form-control form-control-sm" type="text" readonly="" id="xm-name">
                             </div>
                             <div class="form-group">
-                                <label>图号:</label>
-                                <input class="form-control form-control-sm" type="text" readonly="" value="" id="drawing-code">
+                                <label>图:</label>
+                                <input class="form-control form-control-sm" type="text" readonly="" id="drawing-code">
                             </div>
                             <div class="form-group">
                                 <label>计算式说明:</label>
@@ -85,7 +85,9 @@
                                     <a href="#edit-img" data-toggle="modal" data-target="#edit-img" id="modify-img" style="display: none;">添加草图</a>
                                     <% } %>
                                 </div>
-                                <p id="calc-img"><img src="" class="d-100" width="100%"></p>
+                                <p>
+                                    <a href="#imgview" data-toggle="modal" data-target="#imgview"><img src="" class="d-100" width="100%" id="calc-img"></a>
+                                </p>
                             </div>
                         </div>
                     </div>

+ 17 - 1
app/view/stage/detail_modal.ejs

@@ -11,7 +11,7 @@
                     <div class="row" id="im-type">
                         <% for (const i in imType) { %>
                         <% console.log(ctx.stage.im_type === imType[i].value); %>
-                        <div class="col-6">
+                        <div class="col-4">
                             <div class="card border-primary" name="im-type" im-type="<%- imType[i].value %>" <% if (ctx.stage.im_type !== imType[i].value) { %>style="cursor:pointer;"<% } %>>
                                 <div class="card-body<% if (ctx.stage.im_type === imType[i].value) { %> text-primary<% } %>">
                                     <h5 class="card-title mb-0" im-type="<%- imType[i].value %>">
@@ -144,4 +144,20 @@
         </div>
     </div>
 </div>
+<!--草图预览-->
+<div class="modal fade" id="imgview" data-backdrop="static">
+    <div class="modal-dialog modal-lgx" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">查看草图</h5>
+            </div>
+            <div class="modal-body">
+                <img src="" id="view-calc-img">
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
 <% include ./audit_modal.ejs %>

File diff suppressed because it is too large
+ 257 - 2
app/view/stage/index.ejs


+ 155 - 23
app/view/stage/modal.ejs

@@ -197,6 +197,123 @@
         </div>
     </div>
 </div>
+<!--上传附件-->
+<div class="modal fade" id="upload" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">上传附件</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label for="formGroupExampleInput">大小限制:10MB,支持<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="doc,docx,xls,xlsx,ppt,pptx,pdf">office等文档格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="jpg,png,bmp">图片格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="rar,zip">压缩包格式</span></label>
+                    <input type="file" class="" id="upload-file" multiple>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary btn-sm" id="upload-file-btn">确认</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<% if (stage.revising) { %>
+<!--正在修订提示-->
+<div class="modal fade" id="unedit" data-backdrop="static">
+    <div class="modal-dialog " role="document" >
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">提示</h5>
+            </div>
+            <div class="modal-body">
+                <h5>台帐正在进行修订,本期计量无法进行任何操作。</h5>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">好的</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script type="text/javascript">$('#unedit').modal('show');</script>
+<% } %>
+
+<!--设置生成规则-->
+<div class="modal fade" id="choose" data-backdrop="static">
+    <div class="modal-dialog " role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">设置中间计量生成规则</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>中间计量模式 <a href="/public/images/example/jiliangmoshi.png" target="_blank" data-toggle="tooltip" data-placement="bottom" data-original-title="点击查看相关报表"><i class="fa fa-question-circle-o"></i></a></label>
+                    <div class="row" id="im-type">
+                        <% for (const i in imType) { %>
+                        <div class="col-4">
+                            <div class="card border-primary" name="im-type" im-type="<%- imType[i].value %>" <% if (ctx.stage.im_type !== imType[i].value) { %>style="cursor:pointer;"<% } %>>
+                                <div class="card-body<% if (ctx.stage.im_type === imType[i].value) { %> text-primary<% } %>">
+                                    <h5 class="card-title mb-0" im-type="<%- imType[i].value %>">
+                                        <% if (ctx.stage.im_type === imType[i].value) { %><i class="fa fa-check pull-right"></i><% } %>
+                                        <%- imType[i].name %>
+                                    </h5>
+                                </div>
+                            </div>
+                        </div>
+                        <% }%>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>中间计量表号前缀</label>
+                    <input type="text" class="form-control form-control-sm" value="<%- ctx.stage.im_pre ? ctx.stage.im_pre : '' %>" id="im-pre" maxlength="10">
+                </div>
+                <div class="form-group">
+                    <label> </label>
+                    <a  href="#choose2" data-toggle="modal" data-target="#choose2">高级设置</a>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <% if (!stage.readOnly && stage.user_id === ctx.session.sessionUser.accountId) { %>
+                <button type="button" class="btn btn-primary btn-sm" id="choose-ok">重新生成</button>
+                <% } %>
+            </div>
+        </div>
+    </div>
+</div>
+<!--设置生成规则2-->
+<div class="modal fade" id="choose2" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">高级设置</h5>
+            </div>
+            <div class="modal-body">
+                <div class="custom-control custom-checkbox mb-2">
+                    <input type="checkbox" class="custom-control-input" id="im-gather-check" <% if (ctx.stage.im_gather) { %> checked="checked"<% } %>>
+                    <label class="custom-control-label" for="im-gather-check">汇总计量节点</label>
+                </div>
+                <div class="modal-height-500" id="im-gather-spread">
+                </div>
+                <div class="popover bs-popover-right" role="tooltip" id="gather-confirm" style="display: none">
+                    <div class="arrow" style="top:30px"></div>
+                    <div class="popover-body">
+                        <p id="gather-confirm-hint">父项已勾选,继续将取消父项勾选。</p>
+                        <p class="mb-0 d-flex justify-content-end">
+                            <button class="btn btn-sm btn-secondary" id="gather-confirm-cancel">取消</button>&nbsp;<button class="btn btn-sm btn-success" id="gather-confirm-ok">继续</button>
+                        </p>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <% if (!stage.readOnly && stage.user_id === ctx.session.sessionUser.accountId) { %>
+                <button type="button" class="btn btn-primary btn-sm" id="choose2-ok">确定</button>
+                <% } %>
+            </div>
+        </div>
+    </div>
+</div>
 <!--添加草图-->
 <div class="modal fade" id="edit-img" data-backdrop="static">
     <div class="modal-dialog modal-lgx" role="document">
@@ -205,48 +322,63 @@
                 <h5 class="modal-title">添加草图</h5>
             </div>
             <div class="modal-body">
-                <p><a href="" class="btn btn-outline-primary btn-sm">上传图片</a></p>
+                <p>
+                    <input type="file" id="upload-img-file" style="display: none;">
+                    <a href="javascript: void(0);" class="btn btn-outline-primary btn-sm" id="upload-img">上传图片</a>
+                </p>
                 <div class="img-view">
-                    <div class="img-item">
-                        <div class="img-bar">
-                            <a href="" class="text-danger" title="删除"><i class="fa fa-remove"></i></a>
-                        </div>
-                        <!--<img src="img/sketch/1.png" id="draggable">-->
-                    </div>
-                    <div class="img-item" style="left:300px;">
-                        <div class="img-bar">
-                            <a href="" class="text-danger" title="删除"><i class="fa fa-remove"></i></a>
-                        </div>
-                        <!--<img src="img/sketch/2.png" id="draggable">-->
-                    </div>
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary btn-sm" >确认</button>
+                <button type="button" class="btn btn-primary btn-sm" id="edit-img-ok">确认</button>
             </div>
         </div>
     </div>
 </div>
-<!--上传附件-->
-<div class="modal fade" id="upload" data-backdrop="static">
-    <div class="modal-dialog" role="document">
+<!--计量汇总-->
+<div class="modal fade" id="choose" data-backdrop="static">
+    <div class="modal-dialog modal-lg" 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="form-group">
-                    <label for="formGroupExampleInput">大小限制:10MB,支持<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="doc,docx,xls,xlsx,ppt,pptx,pdf">office等文档格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="jpg,png,bmp">图片格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="rar,zip">压缩包格式</span></label>
-                    <input type="file" class="form-control form-control-sm" id="upload-file" multiple>
+                <div class="modal-height-500">
+                    <table class="table table-sm table-bordered">
+                        <tr><th width="70">计量汇总</th><th>项目节编号</th><th>清单编号</th><th>名称</th><th>单位</th></tr>
+                        <tr><td><input type="checkbox"></td><td>1</td><td></td><td>第一部分 建筑安装工程费</td><td></td></tr>
+                        <tr><td><input type="checkbox"></td><td>1-2</td><td></td><td>路基工程</td><td></td></tr>
+                        <tr><td><input type="checkbox"></td><td>1-2-2</td><td></td><td>挖方</td><td></td></tr>
+                        <tr><td><input type="checkbox"></td><td>1-2-2-1</td><td></td><td>挖土方</td><td></td></tr>
+                        <tr><td><input type="checkbox"></td><td>1-2-2-1-1</td><td></td><td>挖路基土方</td><td></td></tr>
+                        <tr><td><input type="checkbox"></td><td></td><td>203-1-a</td><td>挖土方</td><td></td></tr>
+                    </table>
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary btn-sm" id="upload-file-btn">确认</button>
+                <% if (!stage.readOnly) { %>
+                <button type="button" class="btn btn-primary btn-sm" >确认</button>
+                <% } %>
+            </div>
+        </div>
+    </div>
+</div>
+<!--草图预览-->
+<div class="modal fade" id="imgview" data-backdrop="static">
+    <div class="modal-dialog modal-lgx" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">查看草图</h5>
+            </div>
+            <div class="modal-body">
+                <img src="" id="view-calc-img">
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
             </div>
         </div>
     </div>
 </div>
-
 <% include ./audit_modal.ejs %>

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

@@ -29,7 +29,7 @@
                 </div>
             </div>
             <div class="c-body col">
-                <div class="side-bar-1 sjs-bar"></div>
+                <div class="side-bar-1"></div>
                 <div class="sjs-sh-1">
                     <table class="table table-bordered">
                         <tr><th></th><th>可选基数</th><th>计算代号</th><th>值</th></tr>

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

@@ -78,7 +78,7 @@
                 <% if (uploadPermission) { %>
                 <div class="form-group">
                     <label for="formGroupExampleInput">大小限制:10MB,支持<span data-toggle="tooltip" data-placement="bottom" title="doc,docx,xls,xlsx,ppt,pptx,pdf">office等文档格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="jpg,png,bmp">图片格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="rar,zip">压缩包格式</span></label>
-                    <input type="file" class="form-control form-control-sm" id="upload-file" multiple>
+                    <input type="file" class="" id="upload-file" multiple>
                 </div>
                 <% } %>
                 <div class="modal-height-500" style="overflow:auto;">

+ 34 - 44
app/view/stage/stage_sub_menu.ejs

@@ -6,55 +6,45 @@
     </div>
     <div class="scrollbar-auto">
         <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class=""><a href="/tender/<%- ctx.tender.id %>/measure/stage"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
-                </ul>
-            </div>
-        <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order) { %>active<% } %>">
-                        <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>"><span class="ml-3">计量台帐</span></a>
-                    </li>
-                </ul>
-            </div>
+            <ul class="nav-list list-unstyled">
+                <li><a class="text-primary" href="/tender/<%- ctx.tender.id %>/measure/stage"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
+            </ul>
+        </div>
         <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/detail') { %>active<% } %>">
-                        <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/detail"><span class="ml-3">中间计量</span></a>
-                        <span class=" position-absolute tips-dot" data-toggle="tooltip" data-placement="bottom" data-original-title="完成中间计量" id="check_point" <% if (!ctx.stage.check_detail) { %>style="display: none;"<% } %>>
-                            <i class="fa fa-circle text-danger"></i>
-                        </span>
-                    </li>
-                </ul>
-            </div>
+            <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order) { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- ctx.stage.order %>"><span class="ml-3">计量台帐</span></a>
+                </li>
+            </ul>
+        </div>
         <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/pay') { %>active<% } %>">
-                        <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/pay"><span class="ml-3">合同支付</span></a>
-                    </li>
-                </ul>
-            </div>
+            <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/pay') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/pay"><span class="ml-3">合同支付</span></a>
+                </li>
+            </ul>
+        </div>
         <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/change') { %>active<% } %>">
-                        <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/change"><span class="ml-3">变更概况</span></a>
-                    </li>
-                </ul>
-            </div>
+            <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/change') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/change"><span class="ml-3">变更概况</span></a>
+                </li>
+            </ul>
+        </div>
         <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/gather') { %>active<% } %>">
-                        <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/gather"><span class="ml-3">清单汇总</span></a>
-                    </li>
-                </ul>
-            </div>
+            <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/gather') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/gather"><span class="ml-3">清单汇总</span></a>
+                </li>
+            </ul>
+        </div>
         <div class="nav-box">
-                <ul class="nav-list list-unstyled">
-                    <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/compare') { %>active<% } %>">
-                        <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/compare"><span class="ml-3">审核比较</span></a>
-                    </li>
-                </ul>
-            </div>
+            <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/compare') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/compare"><span class="ml-3">审核比较</span></a>
+                </li>
+            </ul>
+        </div>
         <% include ./audit_btn.ejs %>
         <div class="side-fold"><a href="javascript: void(0)" data-toggle="tooltip" data-placement="top" data-original-title="折叠侧栏" id="to-mini-menu"><i class="fa fa-upload fa-rotate-270"></i></a></div>
     </div>

+ 2 - 11
app/view/stage/stage_sub_mini_menu.ejs

@@ -1,12 +1,13 @@
 <!--折起的菜单-->
 <div class="min-side" id="sub-mini-menu" style="display: none;">
+    <div id="sub-mini-hint" class="side-switch" data-container="body" data-toggle="popover" data-placement="bottom" data-content="这里打开收起的菜单栏"></div>
     <div class="side-switch">
         <i class="fa fa-bars"></i>
     </div>
     <div class="side-menu" id="mini-menu-list" style="display: none">
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
-                <li class=""><a href="/tender/<%- ctx.tender.id %>/measure/stage"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
+                <li class=""><a class="text-primary" href="/tender/<%- ctx.tender.id %>/measure/stage"><i class="fa fa-chevron-left "></i> <span>返回</span></a></li>
             </ul>
         </div>
         <div class="nav-box">
@@ -18,16 +19,6 @@
         </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
-                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/detail') { %>active<% } %>">
-                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/detail"><span class="ml-3">中间计量</span></a>
-                    <span class=" position-absolute tips-dot" data-toggle="tooltip" data-placement="bottom" data-original-title="完成中间计量" id="check_point" <% if (!ctx.stage.check_detail) { %>style="display: none;"<% } %>>
-                            <i class="fa fa-circle text-danger"></i>
-                        </span>
-                </li>
-            </ul>
-        </div>
-        <div class="nav-box">
-            <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/pay') { %>active<% } %>">
                     <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/pay"><span class="ml-3">合同支付</span></a>
                 </li>

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

@@ -551,7 +551,8 @@
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
-        //key: 'tender.memu.1.0.0',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
         callback: function (info) {
             if (info.mini) {
                 $('.panel-title').addClass('fluid');
@@ -772,6 +773,5 @@
 <script>
     let property = JSON.parse('<%- JSON.stringify(tenderInfo) %>');
     let ledgerChecked = <%- tender.ldeger_status === audit.ledger.status.checked %>;
-    <% console.log(lastStage) %>
     let firstStageChecked = <%- lastStage !== undefined && lastStage !== null && (lastStage.order > 1 || (lastStage.order === 1 && lastStage.status === audit.stage.status.checked)) %>;
 </script>

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

@@ -21,7 +21,7 @@
             </ul>
         </div>
         <div class="nav-box">
-            <h3><i class="fa fa-calendar-check-o"></i> 计量台帐</h3>
+            <h3><i class="fa fa-calendar-check-o"></i> 计量支付</h3>
             <ul class="nav-list list-unstyled sub-list">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/stage"><span>期列表</span></a></li>
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/compare') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/compare"><span>多期比较</span></a></li>

+ 2 - 1
app/view/tender/tender_sub_mini_menu.ejs

@@ -1,5 +1,6 @@
 <!--折起的菜单-->
 <div class="min-side" id="sub-mini-menu" style="display: none;">
+    <div id="sub-mini-hint" class="side-switch" data-container="body" data-toggle="popover" data-placement="bottom" data-content="这里打开收起的菜单栏"></div>
     <div class="side-switch">
         <i class="fa fa-bars"></i>
     </div>
@@ -18,7 +19,7 @@
             </ul>
         </div>
         <div class="nav-box">
-            <h3><i class="fa fa-calendar-check-o"></i> 计量台帐</h3>
+            <h3><i class="fa fa-calendar-check-o"></i> 计量支付</h3>
             <ul class="nav-list list-unstyled sub-list">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/stage"><span>期列表</span></a></li>
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/compare') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/measure/compare"><span>多期比较</span></a></li>

+ 1 - 0
config/web.js

@@ -219,6 +219,7 @@ const JsFiles = {
                     "/public/js/spreadjs_rela/spreadjs_zh.js",
                     "/public/js/zh_calc.js",
                     "/public/js/path_tree.js",
+                    "/public/js/stage_im.js",
                     "/public/js/stage.js",
                     "/public/js/stage_audit.js",
                 ],