소스 검색

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

Tony Kang 1 년 전
부모
커밋
d2352067af
59개의 변경된 파일3077개의 추가작업 그리고 2610개의 파일을 삭제
  1. 122 0
      app/const/audit.js
  2. 1 1
      app/const/project_setting.js
  3. 182 6
      app/const/spread.js
  4. 112 505
      app/controller/change_controller.js
  5. 1 1
      app/controller/dashboard_controller.js
  6. 1 1
      app/controller/revise_controller.js
  7. 2 7
      app/controller/schedule_controller.js
  8. 1 1
      app/controller/setting_controller.js
  9. 23 0
      app/controller/stage_controller.js
  10. 6 3
      app/controller/tender_controller.js
  11. 39 23
      app/controller/wap_controller.js
  12. 43 0
      app/lib/ledger.js
  13. 76 0
      app/lib/revise_price.js
  14. 30 9
      app/middleware/change_audit_check.js
  15. 29 15
      app/middleware/change_check.js
  16. 3 0
      app/public/css/main.css
  17. 133 1
      app/public/js/change.js
  18. 58 62
      app/public/js/change_audit.js
  19. 10 10
      app/public/js/change_information.js
  20. 4 15
      app/public/js/change_information_approval.js
  21. 8 4
      app/public/js/change_information_show.js
  22. 5 4
      app/public/js/ledger_check.js
  23. 18 3
      app/public/js/profile_cert.js
  24. 2 1
      app/public/js/revise.js
  25. 6 3
      app/public/js/schedule_stage_tp.js
  26. 2 2
      app/public/js/setting.js
  27. 19 2
      app/public/js/shares/cs_tools.js
  28. 2 2
      app/public/js/shenpi.js
  29. 1 1
      app/public/js/spreadjs_rela/spreadjs_zh.js
  30. 1 0
      app/public/js/stage.js
  31. 2 2
      app/public/js/stage_audit.js
  32. 6 6
      app/router.js
  33. 481 476
      app/service/change.js
  34. 1 0
      app/service/change_apply_audit.js
  35. 469 265
      app/service/change_audit.js
  36. 1 0
      app/service/change_plan_audit.js
  37. 1 1
      app/service/project_col_set.js
  38. 2 2
      app/service/project_spread.js
  39. 1 1
      app/service/revise_audit.js
  40. 2 2
      app/service/shenpi_audit.js
  41. 36 4
      app/service/stage.js
  42. 7 1
      app/service/stage_audit.js
  43. 22 1
      app/service/stage_change.js
  44. 33 14
      app/service/tender_cache.js
  45. 63 60
      app/service/tender_info.js
  46. 35 35
      app/view/change/index.ejs
  47. 65 54
      app/view/change/information.ejs
  48. 729 881
      app/view/change/information_modal.ejs
  49. 47 2
      app/view/change/modal.ejs
  50. 3 3
      app/view/dashboard/index.ejs
  51. 1 38
      app/view/setting/show.ejs
  52. 1 1
      app/view/stage/audit_modal.ejs
  53. 1 1
      app/view/tender/cert_modal.ejs
  54. 5 5
      app/view/tender/shenpi.ejs
  55. 45 49
      app/view/wap/shenpi_change.ejs
  56. 9 3
      app/view/wap/tender.ejs
  57. 3 0
      db_script/baseUtils.js
  58. 5 5
      db_script/project_spread.js
  59. 61 16
      sql/update.sql

+ 122 - 0
app/const/audit.js

@@ -601,6 +601,127 @@ const advance = (function() {
     return { type, status, statusString, statusClass, auditString, auditStringClass };
 })();
 
+// 变更 审批流程(新的,旧的也要保留,防止报表或其他地方调用旧的出问题)
+const change = (function() {
+    const status = {
+        uncheck: 1, // 待审批
+        checking: 2, // 审批中或者原报人待上报或者原报上报修订中
+        checked: 3, // 审批通过或者原报人上报完成
+        // checkNo: 4,     // 审批终止
+        checkNo: 5, // 退回到原报人重新上报
+        checkNoPre: 6, // 退回到上一个审批人
+        checkAgain: 7, // 重新审批
+        checkSkip: 8, // 跳过
+        revise: 9, // 修订变更
+        cancelRevise: 10, // 撤销修订
+        checkCancel: 11, // 撤回 // 该状态为上一审批人可发起,回到它到审批阶段,并同时新增一条新的审批中记录
+    };
+    const statusString = [];
+    statusString[status.uncheck] = '待上报';
+    statusString[status.checking] = '审批中';
+    statusString[status.checked] = '审批通过';
+    statusString[status.checkNo] = '审批退回';
+    statusString[status.checkNoPre] = '审批退回';
+    statusString[status.checkAgain] = '重新审批';
+    statusString[status.revise] = '修订';
+    statusString[status.cancelRevise] = '撤销修订';
+    statusString[status.checkCancel] = '撤回';
+
+    const statusClass = [];
+    statusClass[status.uncheck] = '';
+    statusClass[status.checking] = 'text-warning';
+    statusClass[status.checked] = 'text-success';
+    statusClass[status.checkNo] = 'text-warning';
+    statusClass[status.checkNoPre] = 'text-warning';
+    statusClass[status.checkAgain] = 'text-warning';
+    statusClass[status.revise] = 'text-warning';
+    statusClass[status.cancelRevise] = 'text-success';
+    statusClass[status.checkCancel] = 'text-warning';
+
+    // 标段概况页
+    // 描述文本
+    const auditString = [];
+    auditString[status.uncheck] = '';
+    auditString[status.checking] = '审批中';
+    auditString[status.checked] = '审批通过';
+    auditString[status.checkNo] = '审批退回';
+    auditString[status.checkNoPre] = '审批退回';
+    auditString[status.checkAgain] = '重新审批';
+    auditString[status.revise] = '修订';
+    auditString[status.cancelRevise] = '撤销修订';
+    auditString[status.checkCancel] = '撤回';
+    auditString[status.checkSkip] = '审批通过';
+    // 文字样式
+    const auditStringClass = [];
+    auditStringClass[status.uncheck] = '';
+    auditStringClass[status.checking] = 'text-warning';
+    auditStringClass[status.checked] = 'text-success';
+    auditStringClass[status.checkNo] = 'text-warning';
+    auditStringClass[status.checkNoPre] = 'text-warning';
+    auditStringClass[status.checkAgain] = 'text-warning';
+    auditStringClass[status.revise] = 'text-warning';
+    auditStringClass[status.cancelRevise] = 'text-success';
+    auditStringClass[status.checkCancel] = 'text-warning';
+    auditStringClass[status.checkSkip] = 'text-success';
+    // 描述文本
+    const auditProgress = [];
+    auditProgress[status.uncheck] = '待上报';
+    auditProgress[status.checking] = '审批中';
+    auditProgress[status.checked] = '审批通过';
+    auditProgress[status.checkNo] = '审批退回';
+    auditProgress[status.checkNoPre] = '审批退回';
+    auditProgress[status.checkAgain] = '重新审批';
+    auditProgress[status.revise] = '修订中';
+    auditProgress[status.cancelRevise] = '撤销修订';
+    auditProgress[status.checkCancel] = '撤回';
+    auditProgress[status.checkSkip] = '审批通过';
+    // 样式
+    const auditProgressClass = [];
+    auditProgressClass[status.uncheck] = '';
+    auditProgressClass[status.checking] = 'text-warning';
+    auditProgressClass[status.checked] = 'text-success';
+    auditProgressClass[status.checkNo] = 'text-warning';
+    auditProgressClass[status.checkNoPre] = 'text-warning';
+    auditProgressClass[status.checkAgain] = 'text-warning';
+    auditProgressClass[status.revise] = 'text-warning';
+    auditProgressClass[status.cancelRevise] = 'text-success';
+    auditProgressClass[status.checkCancel] = 'text-warning';
+    auditProgressClass[status.checkSkip] = 'text-success';
+
+    const filter = {
+        status: {
+            pending: 1,
+            uncheck: 5,
+            checking: 2,
+            checked: 3,
+            // checkNo: 4,
+        },
+        statusString: [],
+    };
+    filter.statusString[filter.status.pending] = '待处理';
+    filter.statusString[filter.status.uncheck] = '待上报';
+    filter.statusString[filter.status.checking] = '进行中';
+    filter.statusString[filter.status.checked] = '已通过';
+    // filter.statusString[filter.status.checkNo] = '终止';
+
+    // 按钮
+    const statusButton = [];
+    statusButton[status.uncheck] = '上报';
+    statusButton[status.checking] = '审批';
+    statusButton[status.checked] = '';
+    statusButton[status.checkNo] = '重新上报';
+    statusButton[status.revise] = '修订';
+
+    // 按钮样式
+    const statusButtonClass = [];
+    statusButtonClass[status.uncheck] = 'btn-primary';
+    statusButtonClass[status.checking] = 'btn-success';
+    statusButtonClass[status.checked] = '';
+    statusButtonClass[status.checkNo] = 'btn-warning';
+    statusButtonClass[status.revise] = 'btn-warning';
+    return { status, statusString, statusClass, auditString, auditStringClass, auditProgress, auditProgressClass, filter, statusButton, statusButtonClass };
+})();
+
 // 变更立项 审批流程
 const changeProject = (function() {
     const status = {
@@ -968,6 +1089,7 @@ module.exports = {
     filter,
     pushType,
     advance,
+    change,
     changeProject,
     changeApply,
     changePlan,

+ 1 - 1
app/const/project_setting.js

@@ -40,7 +40,7 @@ const colSet = {
         { field: 'end_yf_tp', name: '截止本期应付', fixed: [] },
         { field: 'sf_tp', name: '本期实付', fixed: [] },
         { field: 'end_sf_tp', name: '截止本期实付', fixed: [] },
-        { field: 'wf_tp', name: '未付金额', fixed: [], hint:'截止本期完成-截止本期实付' },
+        { field: 'wf_tp', name: '未付金额', fixed: [], hint:'截止本期应付-截止本期实付' },
     ]
 };
 const defaultColSet = {

+ 182 - 6
app/const/spread.js

@@ -113,7 +113,7 @@ const EmptySpreadSetting = {
 };
 // 可设置列集合
 const BaseSetCol = {
-    Ledger: [
+    tz_ledger_set: [
         { key: 'code', name: '项目节编号', fixed: ['move', 'valid', 'alias'], bills: 1, pos: 0, },
         { key: 'b_code', name: '清单编号', fixed: ['alias'], bills: 1, pos: 0, },
         { key: 'ex_memo1', name: '备注1', fixed: [], bills: 1, pos: 1, },
@@ -132,7 +132,7 @@ const BaseSetCol = {
         { key: 'ex_memo2', name: '备注2', fixed: [], bills: 1, pos: 1, },
         { key: 'ex_memo3', name: '备注3', fixed: [], bills: 1, pos: 1, },
     ],
-    Stage: [
+    tz_stage_set: [
         { key: 'code', name: '项目节编号', fixed: ['move', 'valid', 'alias'], bills: 1, pos: 0 },
         { key: 'b_code', name: '清单编号', fixed: ['alias'], bills: 1, pos: 0 },
         { key: 'ex_memo1', name: '备注1', fixed: [], bills: 1, pos: 1, },
@@ -160,6 +160,53 @@ const BaseSetCol = {
         { key: 'gxby', name: '工序报验', fixed: ['valid', 'alias'], bills: 1, pos: 1, },
         { key: 'dagl', name: '档案管理', fixed: ['valid', 'alias'], bills: 1, pos: 1, },
     ],
+    gcl_ledger_set: [
+        { key: 'code', name: '项目节编号', fixed: ['move', 'valid', 'alias'], bills: 1, pos: 0, },
+        { key: 'b_code', name: '清单编号', fixed: ['alias'], bills: 1, pos: 0, },
+        { key: 'ex_memo1', name: '备注1', fixed: [], bills: 1, pos: 1, },
+        { key: 'name', name: '名称/计量单元', fixed: ['alias'], bills: 1, pos: 1 },
+        { key: 'features', name: '项目特征', fixed: ['valid', 'alias'], bills: 1, pos: 0 },
+        { key: 'position', name: '位置', fixed: [], bills: 0, pos: 1 },
+        { key: 'unit', name: '单位', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'unit_price', name: '单价', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'dgn_qty', name: '项目节数量', fixed: [], bills: 1, pos: 0, },
+        { key: 'dgn_price', name: '经济指标', fixed: ['alias'], bills: 1, pos: 0},
+        { key: 'deal_calc', name: '签约', fixed: [], bills: 1, pos: 1, },
+        { key: 'tz_calc', name: '台账', fixed: ['alias'], bills: 1, pos: 1, },
+        { key: 'drawing_code', name: '图册号', fixed: ['alias'], bills: 1, pos: 1 },
+        { key: 'node_type', name: '费用类别', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'memo', name: '备注', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'ex_memo2', name: '备注2', fixed: [], bills: 1, pos: 1, },
+        { key: 'ex_memo3', name: '备注3', fixed: [], bills: 1, pos: 1, },
+    ],
+    gcl_stage_set: [
+        { key: 'code', name: '项目节编号', fixed: ['move', 'valid', 'alias'], bills: 1, pos: 0 },
+        { key: 'b_code', name: '清单编号', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'ex_memo1', name: '备注1', fixed: [], bills: 1, pos: 1, },
+        { key: 'name', name: '名称/计量单元', fixed: ['alias'], bills: 1, pos: 1 },
+        { key: 'features', name: '项目特征', fixed: ['valid', 'alias'], bills: 1, pos: 0 },
+        { key: 'position', name: '位置', fixed: [], bills: 0, pos: 1},
+        { key: 'unit', name: '单位', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'unit_price', name: '单价', fixed: ['alias'], bills: 1, pos: 0 },
+        { key: 'deal_calc', name: '签约', fixed: [], bills: 1, pos: 0 },
+        { key: 'tz_calc', name: '台账', fixed: [], bills: 1, pos: 0},
+        { key: 'real_qty', name: '现场实际数量', fixed: ['valid', 'alias'], bills: 0, pos: 1},
+        { key: 'estimate_qty', name: '预计变更数量', fixed: ['valid', 'alias'], bills: 0, pos: 1},
+        { key: 'cur_calc', name: '本期计量', fixed: ['alias'], bills: 1, pos: 1, },
+        { key: 'end_calc', name: '截止本期计量', fixed: ['alias'], bills: 1, pos: 1, },
+        { key: 'deal_dgn_qty', name: '合同-项目节数量', fixed: ['alias'], bills: 1, pos: 0, },
+        { key: 'c_dgn_qty', name: '变更-项目节数量', fixed: ['alias'], bills: 1, pos: 0, },
+        { key: 'final_dgn_price', name: '经济指标', fixed: [], bills: 1, pos: 0 },
+        { key: 'postil', name: '本期批注', fixed: [], bills: 1, pos: 1 },
+        { key: 'drawing_code', name: '图册号', fixed: [], bills: 1, pos: 1 },
+        { key: 'memo', name: '备注', fixed: [], bills: 1, pos: 0 },
+        { key: 'ex_memo2', name: '备注2', fixed: [], bills: 1, pos: 1, },
+        { key: 'ex_memo3', name: '备注3', fixed: [], bills: 1, pos: 1, },
+        { key: 'add_stage_order', name: '添加期数', fixed: [], bills: 1, pos: 1, },
+        { key: 'is_tp', name: '总额计量', fixed: [], bills: 1, pos: 0 },
+        { key: 'gxby', name: '工序报验', fixed: ['valid', 'alias'], bills: 1, pos: 1, },
+        { key: 'dagl', name: '档案管理', fixed: ['valid', 'alias'], bills: 1, pos: 1, },
+    ],
 };
 // 默认的列设置
 const glSpreadTemplate = {
@@ -454,7 +501,7 @@ const ProjectSpreadTemplate = [
     { code: 'xxby', name: '小修保养', template: glSpreadTemplate },
 ];
 const BaseSpreadColSetting = {
-    Ledger: {
+    tz_ledger_set: {
         bills: {
             code: [{title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', cellType: 'tree'}],
             b_code: [{title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@',}],
@@ -503,7 +550,7 @@ const BaseSpreadColSetting = {
             ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}]
         }
     },
-    Stage: {
+    tz_stage_set: {
         bills: {
             code: [{title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'}],
             b_code: [{title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@', readOnly: true}],
@@ -583,7 +630,136 @@ const BaseSpreadColSetting = {
             gxby: [{title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
             dagl: [{title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
         }
-    }
+    },
+    gcl_ledger_set: {
+        bills: {
+            code: [{title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', cellType: 'tree'}],
+            b_code: [{title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@',}],
+            name: [{title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', }],
+            unit: [{title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'}],
+            unit_price: [{title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number',}],
+            dgn_qty: [
+                {title: '项目节数量|数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 60, type: 'Number', aliasFormat: '{%s}|数量1'},
+                {title: '|数量2',  colSpan: '|1', rowSpan: '|1', field: 'dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
+            ],
+            dgn_price: [{title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true}],
+            deal_calc: [
+                {title: '签约|数量', colSpan: '2|1', rowSpan: '1|1', field: 'deal_qty', hAlign: 2, width: 60, type: 'Number', aliasFormat: '{%s}|数量'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'deal_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            ],
+            tz_calc: [
+                {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: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            ],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            node_type: [{title: '费用类别', colSpan: '1', rowSpan: '2', field: 'node_type', hAlign: 0, width: 100, cellType: 'customizeCombo'}],
+            memo: [{title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}, ],
+            ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}, ],
+            ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}]
+        },
+        pos: {
+            name: [{title: '计量单元', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, formatter: '@'}],
+            position: [{title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'}],
+            tz_calc: [
+                {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},
+            ],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            node_type: [{title: '费用类别', colSpan: '1', rowSpan: '2', field: 'node_type', hAlign: 0, width: 100, cellType: 'customizeCombo'}],
+            ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}]
+        }
+    },
+    gcl_stage_set: {
+        bills: {
+            code: [{title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'}],
+            b_code: [{title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@', readOnly: true}],
+            name: [{title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true}],
+            unit: [{title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true, cellType: 'unit'}],
+            unit_price: [{title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'}],
+            tz_calc: [
+                {title: '台账|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, readOnly: true, type: 'Number', aliasFormat: '{%s}|数量'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            ],
+            deal_calc: [
+                {title: '签约|数量', colSpan: '2|1', rowSpan: '1|1', field: 'deal_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number', aliasFormat: '{%s}|数量'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'deal_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            ],
+            cur_calc: [
+                {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'},
+                {title: '本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+                {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
+                {title: '本期补差|原单价', colSpan: '2|1', rowSpan: '1|1', field: 'org_price', hAlign: 2, width: 60, type: 'Number', readOnly: true },
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'pc_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true },
+                {title: '本期完成计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            ],
+            end_calc: [
+                {title: '截止本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+                {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            ],
+            deal_dgn_qty: [
+                {title: '合同|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'deal_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
+                {title: '|项目节数量2',  colSpan: '|1', rowSpan: '|1', field: 'deal_dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
+            ],
+            c_dgn_qty: [
+                {title: '变更|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'c_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
+                {title: '|项目节数量2',  colSpan: '|1', rowSpan: '|1', field: 'c_dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
+            ],
+            final_dgn_price: [{title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'final_dgn_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},],
+            is_tp: [{title: '总额计量', colSpan: '1', rowSpan: '2', field: 'is_tp', hAlign: 1, width: 60, cellType: 'checkbox'}],
+            gxby: [{title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
+            dagl: [{title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            memo: [{title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            postil: [{title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'autoTip'},],
+            ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+        },
+        pos: {
+            name: [{title: '计量单元', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@'}],
+            position: [{title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'}],
+            real_qty: [{title: '现场实际数量', colSpan: '1', rowSpan: '2', field: 'real_qty', hAlign: 2, width: 60, type: 'Number'}],
+            estimate_qty: [{title: '预计变更数量', colSpan: '1', rowSpan: '2', field: 'estimate_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true}],
+            cur_calc: [
+                {title: '本期计量|合同', colSpan: '4|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: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
+                {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            ],
+            end_calc: [
+                {title: '截止本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+                {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
+                {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            ],
+            postil: [{title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 80, formatter: '@', cellType: 'autoTip'},],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
+            add_stage_order: [{title: '添加期数', colSpan: '1', rowSpan: '2', field: 'add_stage_order', hAlign:1, width: 80, readOnly: true}],
+            gxby: [{title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
+            dagl: [{title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
+        }
+    },
 };
 const withoutClReplace = {
     indexField: 'sgfh_qty',
@@ -600,7 +776,7 @@ const SpreadSpec = {
     gcl_stage_set: {
         pos: [
             { condition: { key: 'field', value: ['name', 'position'] }, update: { readOnly: false } },
-        ]
+        ],
     }
 };
 

+ 112 - 505
app/controller/change_controller.js

@@ -19,6 +19,7 @@ const path = require('path');
 const audit = require('../const/audit');
 const codeRuleConst = require('../const/code_rule');
 const changeConst = require('../const/change');
+const auditType = require('../const/audit').auditType;
 const accountGroup = require('../const/account_group').group;
 const shenpiConst = require('../const/shenpi');
 const tenderMenu = require('../../config/menu').tenderMenu;
@@ -59,50 +60,17 @@ module.exports = app => {
             let page_total = 0;
             const tp = await ctx.service.change.getTp(tender.id, status);
             if (changes !== null) {
-                let i = 0;
                 for (const c of changes) {
-                    page_total = ctx.helper.add(page_total, c.total_price);
-                    const status = c.status === audit.flow.status.uncheck ? 0 : 1;
-                    // 根据审批人对当前变更令的状态取不同的展示方式。
-                    let changeAudit = '';
-                    let auditStatus = 0;
-                    switch (c.status) {
-                        case 1:
-                            auditStatus = 1;
-                            break;
-                        case 2:
-                            changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
-                            auditStatus = changeAudit.uid === ctx.session.sessionUser.accountId ? 1 : 0;
-                            break;
-                        case 3:
-                        case 4:
-                            auditStatus = 0;
-                            changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
-                            break;
-                        case 5:
-                            changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times - 1, status);
-                            auditStatus = c.uid === ctx.session.sessionUser.accountId ? 1 : 0;
-                            const back_changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, c.cid);
-                            c.stageChangeNum = this.ctx.helper.sum(back_changeUsedData.map(x => { return Math.abs(x.qty); }));
-                            c.isSettle = await ctx.service.changeSettleList.isSettle(c.cid);
-                            break;
-                        case 6:
-                            changeAudit = await ctx.service.changeAudit.getLastBackUser(c.cid, c.times);
-                            const checkingAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
-                            auditStatus = checkingAudit.uid === ctx.session.sessionUser.accountId ? 1 : 0;
-                            break;
-                        case 9:
-                            auditStatus = c.uid === ctx.session.sessionUser.accountId ? 9 : 0;
-                            const changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, c.cid);
-                            c.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.qty); }));
-                            c.isSettle = await ctx.service.changeSettleList.isSettle(c.cid);
-                            break;
-                        default:
-                            break;
+                    c.curAuditors = await ctx.service.changeAudit.getAuditorsByStatus(c.cid, c.status, c.times);
+                    if (c.status === audit.change.status.checkNoPre) {
+                        c.curAuditors2 = await ctx.service.stageAudit.getAuditorsByStatus(c.cid, audit.change.status.checking, c.times);
+                    }
+                    if (c.status === audit.change.status.checkNo || c.status === audit.change.status.revise) {
+                        const changeUsedData = await ctx.service.stageChange.getAllFinalUsedData(ctx.tender.id, c.cid);
+                        c.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.qty); }));
+                        c.isSettle = await ctx.service.changeSettleList.isSettle(c.cid);
                     }
-                    changes[i].changeAudit = changeAudit;
-                    changes[i].auditStatus = auditStatus;
-                    i++;
+                    page_total = ctx.helper.add(page_total, c.total_price);
                 }
             }
 
@@ -157,7 +125,6 @@ module.exports = app => {
             const apLists = allPlanCodes.length > 0 ? ctx.app._.uniq(ctx.app._.map(allPlanCodes, 'plan_code')) : [];
 
             const renderData = {
-                uid: ctx.session.sessionUser.accountId,
                 moment,
                 tender,
                 // tenderList,
@@ -169,7 +136,7 @@ module.exports = app => {
                 status,
                 codeRule,
                 dealCode: ctx.tender.info.deal_info.dealCode,
-                auditConst: audit.flow,
+                auditConst: audit.change,
                 changeConst,
                 state,
                 ruleType: codeRuleConst.ruleType.change,
@@ -179,6 +146,7 @@ module.exports = app => {
                 tpUnit: ctx.tender.info.decimal.tp,
                 changePlanList,
                 apLists,
+                auditType,
             };
 
             if (ctx.session.sessionProject.page_show.openChangeState) {
@@ -210,6 +178,25 @@ module.exports = app => {
         }
 
         /**
+         * 审批流程(Get)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async changeAuditors(ctx) {
+            try {
+                const cid = JSON.parse(ctx.request.body.data).cid;
+                const tenderId = ctx.params.id;
+                const changeInfo = await ctx.service.change.getDataByCondition({ cid });
+                await ctx.service.change.loadChangeUser(changeInfo);
+                await ctx.service.change.loadChangeAuditViewData(changeInfo);
+                ctx.body = { err: 0, msg: '', data: changeInfo };
+            } catch (error) {
+                this.log(error);
+                ctx.body = { err: 1, msg: error.toString(), data: null };
+            }
+        }
+
+        /**
          *
          * @param {Object} ctx - egg全局变量
          * @return {void}
@@ -327,277 +314,14 @@ module.exports = app => {
         }
 
         /**
-         * 变更信息 页面 (Get)
-         *
-         * @param {Object} ctx - egg全局变量
-         * @return {void}
+         * 获取审批界面所需的 原报、审批人数据等
+         * @param ctx
+         * @return {Promise<void>}
+         * @private
          */
-        async info(ctx) {
-            try {
-                const whiteList = this.ctx.app.config.multipart.whitelist;
-                const tenderid = ctx.params.id !== undefined ? ctx.params.id : ctx.session.sessionUser.tenderId;
-                ctx.session.sessionUser.tenderId = tenderid;
-                const tender = await ctx.service.tender.getDataById(tenderid);
-                const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid });
-
-                // 后台判断当前人查看info状态
-                const auditStatus = await ctx.service.changeAudit.getStatusByChange(change);
-
-                // 获取附件列表
-                const attList = await ctx.service.changeAtt.getChangeAttachment(ctx.params.cid);
-
-                // 获取其他变更令数据
-                const othersChange = await ctx.service.change.getOthersChange(ctx.params.id, ctx.params.cid);
-
-                // 根据auditStatus获取审批人列表
-                const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
-                // 获取已选清单
-                let changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.params.cid } });
-
-                // 获取用户人验证手机号
-                const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
-                const auth_mobile = pa.auth_mobile;
-                const renderData = {
-                    uid: ctx.session.sessionUser.accountId,
-                    tender,
-                    change,
-                    othersChange,
-                    changeConst,
-                    auditStatus,
-                    auditConst: audit.flow,
-                    ledgerConsts: audit.ledger.status,
-                    attList,
-                    whiteList,
-                    auditList,
-                    changeList,
-                    tpUnit: change.tp_decimal !== null ? change.tp_decimal : ctx.tender.info.decimal.tp,
-                    upUnit: change.up_decimal !== null ? change.up_decimal : ctx.tender.info.decimal.up,
-                    authMobile: auth_mobile,
-                    shenpiConst,
-                };
-                // 根据auditStatus状态获取的不同的数据
-                if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) {
-                    renderData.changeUnits = changeConst.units;
-                    renderData.precision = ctx.tender.info.precision;
-                    // renderData.accountGroup = accountGroup;
-                    // 获取所有项目参与者
-                    const accountList = await ctx.service.projectAccount.getAllDataByCondition({
-                        where: { project_id: ctx.session.sessionProject.id, enable: 1 },
-                        columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group'],
-                    });
-                    renderData.accountList = accountList;
-                    const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
-                    renderData.accountGroup = unitList.map(item => {
-                        const groupList = accountList.filter(item1 => item1.company === item.name);
-                        return { groupName: item.name, groupList };
-                    });
-                    // 重新上报获取审批流程
-                    if (auditStatus === 2 || auditStatus === 9) {
-                        const auditList2 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
-                        // 展示页右侧审批流程列表
-                        const auditList3 = [];
-                        for (let time = 1; time <= change.times - 1; time++) {
-                            const auditTimeList = [];
-                            let max_sort = 1;
-                            for (const al of auditList2) {
-                                if (al.times === time) {
-                                    auditTimeList.push(al);
-                                    if (al.usite > max_sort) {
-                                        max_sort = al.usite;
-                                    }
-                                }
-                            }
-                            for (const i in auditTimeList) {
-                                auditTimeList[i].max_sort = max_sort;
-                            }
-                            auditList3.push(auditTimeList);
-                        }
-                        renderData.auditList3 = auditList3;
-                    }
-
-                    // 根据清单获取提交数据和计算总金额
-                    const changeListData = [];
-                    const changeWhiteListData = [];
-                    let ototalCost = 0;
-                    let ctotalCost = 0;
-                    for (const cl of changeList) {
-                        const cLArray = [
-                            cl.code,
-                            cl.name,
-                            cl.bwmx,
-                            cl.unit,
-                            cl.unit_price,
-                            cl.oamount,
-                            cl.camount,
-                            cl.detail,
-                            cl.lid,
-                            cl.xmj_code,
-                            cl.xmj_jldy,
-                            cl.gcl_id,
-                        ];
-                        ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, ctx.tender.info.decimal.tp);
-                        ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, ctx.tender.info.decimal.tp);
-                        if (cl.lid !== '0') {
-                            changeListData.push(cLArray.join('*;*'));
-                        } else {
-                            changeWhiteListData.push(cLArray.join('*;*'));
-                        }
-                    }
-                    renderData.changeListData = changeListData.join('^_^');
-                    renderData.changeWhiteListData = changeWhiteListData.join('^_^');
-                    renderData.ototalCost = ototalCost;
-                    renderData.ctotalCost = ctotalCost;
-
-                    // 获取公司列表
-                    const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: tenderid } });
-                    renderData.companyList = companyList;
-                } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) {
-                    // 展示页左侧审批流程列表和清单审批列表数据
-                    const times = change.status === audit.flow.status.back ?
-                        change.times - 1 : change.times;
-                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times);
-
-                    // 展示页右侧审批流程列表
-                    const auditList3 = [];
-                    for (let time = 1; time <= times; time++) {
-                        const auditTimeList = [];
-                        let max_sort = 1;
-                        for (const al of auditList) {
-                            if (al.times === time) {
-                                auditTimeList.push(al);
-                                if (al.usite > max_sort) {
-                                    max_sort = al.usite;
-                                }
-                            }
-                        }
-                        for (const i in auditTimeList) {
-                            auditTimeList[i].max_sort = max_sort;
-                        }
-                        auditList3.push(auditTimeList);
-                    }
-                    renderData.auditList3 = auditList3;
-
-                    changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort();
-                    renderData.changeList = changeList;
-                    let ototalCost = 0;
-                    let ctotalCost = 0;
-                    let stotalCost = 0;
-                    const auditTotalCost = [];
-                    for (const cl of changeList) {
-                        // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit));
-                        ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit);
-                        // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit));
-                        ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit);
-                        // stotalCost += cl.samount !== '' && cl.unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.samount), renderData.tpUnit)) : 0;
-                        stotalCost += cl.samount !== '' && cl.unit_price !== null ? ctx.helper.mul(cl.unit_price, cl.samount, renderData.tpUnit) : 0;
-                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
-                        auditTotalCost.push(audit_amount);
-                    }
-                    renderData.ototalCost = ototalCost;
-                    renderData.ctotalCost = ctotalCost;
-                    renderData.stotalCost = stotalCost;
-
-                    // 清单表页赋值
-                    for (const [index, au] of auditList2.entries()) {
-                        if (au.usite !== 0) {
-                            au.list_amount = [];
-                            au.totalCost = 0;
-                            for (const [auindex, at] of auditTotalCost.entries()) {
-                                au.list_amount.push(at[index - 1]);
-                                // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0;
-                                au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0;
-                            }
-                        }
-                    }
-                    renderData.auditList2 = auditList2;
-                } else if (auditStatus === 6) {
-                    // 展示页左侧审批流程列表和清单审批列表数据
-                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, change.times);
-                    renderData.auditList2 = auditList2;
-                    const auditList3 = await ctx.service.changeAudit.getListOrderByTimes(change.cid, change.times);
-                    for (const i in auditList3) {
-                        auditList3[i].max_sort = auditList2.length - 1;
-                    }
-                    renderData.auditList3 = auditList3;
-
-                    // 展示页右侧审批流程列表
-                    const auditList5 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
-                    const auditList4 = [];
-                    for (let time = 1; time <= change.times; time++) {
-                        const auditTimeList = [];
-                        let max_sort = 1;
-                        for (const al of auditList5) {
-                            if (al.times === time) {
-                                auditTimeList.push(al);
-                                if (al.usite > max_sort) {
-                                    max_sort = al.usite;
-                                }
-                            }
-                        }
-                        for (const i in auditTimeList) {
-                            auditTimeList[i].max_sort = max_sort;
-                        }
-                        if (auditTimeList.length > 0) {
-                            auditList4.push(auditTimeList);
-                        }
-                    }
-                    renderData.auditList4 = auditList4;
-
-                    changeList = JSON.parse(JSON.stringify(changeList.sort())).sort().sort();
-                    renderData.changeList = changeList;
-                    let ototalCost = 0;
-                    let ctotalCost = 0;
-                    const auditTotalCost = [];
-                    const auditUnit = [];
-                    for (const cl of changeList) {
-                        // ototalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.oamount), renderData.tpUnit));
-                        ototalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.oamount, renderData.tpUnit);
-                        // ctotalCost += cl.unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(cl.unit_price, cl.camount), renderData.tpUnit));
-                        ctotalCost += cl.unit_price === null ? 0 : ctx.helper.mul(cl.unit_price, cl.camount, renderData.tpUnit);
-                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
-                        auditTotalCost.push(audit_amount);
-                    }
-                    renderData.ototalCost = ototalCost;
-                    renderData.ctotalCost = ctotalCost;
-
-                    // 清单表页赋值
-                    for (const [index, au] of auditList.entries()) {
-                        if (au.usite !== 0) {
-                            au.list_amount = [];
-                            au.totalCost = 0;
-                            if (au.uid === renderData.uid) {
-                                for (const [auindex, at] of auditTotalCost.entries()) {
-                                    // if (at[index - 2] !== undefined) {
-                                    //     au.list_amount.push(at[index - 2]);
-                                    //     au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 2]), renderData.tpUnit));
-                                    // } else if (at[index - 2] === undefined) {
-                                    //     au.list_amount.push(changeList[auindex].camount);
-                                    //     au.totalCost += parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].camount), renderData.tpUnit));
-                                    // }
-                                    au.list_amount.push(changeList[auindex].spamount);
-                                    // au.totalCost += changeList[auindex].unit_price === null ? 0 : parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, changeList[auindex].spamount), renderData.tpUnit));
-                                    au.totalCost += changeList[auindex].unit_price === null ? 0 : ctx.helper.mul(changeList[auindex].unit_price, changeList[auindex].spamount, renderData.tpUnit);
-                                }
-                            } else {
-                                for (const [auindex, at] of auditTotalCost.entries()) {
-                                    au.list_amount.push(at[index - 1]);
-                                    // au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? parseFloat(ctx.helper.roundNum(ctx.helper.accMul(changeList[auindex].unit_price, at[index - 1]), renderData.tpUnit)) : 0;
-                                    au.totalCost += at[index - 1] !== undefined && changeList[auindex].unit_price !== null ? ctx.helper.mul(changeList[auindex].unit_price, at[index - 1], renderData.tpUnit) : 0;
-                                }
-                            }
-                        }
-                    }
-                }
-                renderData.auditList = auditList;
-
-                // 获取是否已存在调用变更令
-                const changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, change.cid);
-                renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.qty); }));
-                await this.layout('change/info.ejs', renderData, 'change/info_modal.ejs');
-            } catch (err) {
-                this.log(err);
-                ctx.redirect('/tender/' + ctx.params.id + '/change');
-            }
+        async _getChangeAuditViewData(ctx) {
+            await ctx.service.change.loadChangeAuditViewData(ctx.change);
+            // await this._checkStageStart(ctx);
         }
 
         /**
@@ -609,10 +333,9 @@ module.exports = app => {
         async information(ctx) {
             try {
                 const whiteList = this.ctx.app.config.multipart.whitelist;
-                const tender = await ctx.service.tender.getDataById(ctx.tender.id);
+                await this._getChangeAuditViewData(ctx);
+                const tender = ctx.tender;
                 const change = ctx.change;
-                // 后台判断当前人查看info状态
-                const auditStatus = await ctx.service.changeAudit.getStatusByChange(change);
 
                 // 获取附件列表
                 const attList = await ctx.service.changeAtt.getChangeAttachment(change.cid, 'desc');
@@ -620,20 +343,38 @@ module.exports = app => {
                 // 获取其他变更令数据
                 const othersChange = await ctx.service.change.getOthersChange(ctx.tender.id, change.cid);
 
-                // 根据auditStatus获取审批人列表
-                const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
-
                 // 获取变更方案的清单
                 let planList = [];
                 let showPlanBtn = false;
                 if (ctx.session.sessionProject.page_show.openChangePlan) {
-                    const planInfo = change.plan_code ? await ctx.service.changePlan.getDataByCondition({ tid: ctx.tender.id, code: change.plan_code }) : null;
+                    const planInfo = change.plan_code ? await ctx.service.changePlan.getDataByCondition({ tid: tender.id, code: change.plan_code }) : null;
                     showPlanBtn = change.plan_code !== null && change.plan_code !== '';
                     if (planInfo && planInfo.id) {
                         planList = await ctx.service.changePlanList.getAllDataByCondition({ where: { cpid: planInfo.id } });
                     }
                 }
 
+                // 获取清单
+                const changeList = await ctx.service.changeAuditList.getList(change.cid);
+                if (change.status === audit.change.status.checked || change.status === audit.change.status.checking || change.status === audit.change.status.checkNoPre) {
+                    for (const cl of changeList) {
+                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
+                        // 清单表页赋值
+                        for (const au in change.userGroups) {
+                            if (change.userGroups[au][0].audit_order !== 0) {
+                                cl['audit_amount_' + change.userGroups[au][0].audit_order] =
+                                    (change.userGroups[au][0].audit_type === auditType.key.and &&
+                                        ctx.helper._.findIndex(change.userGroups[au], { uid: ctx.session.sessionUser.accountId, status: audit.change.status.checked }) !== -1) ||
+                                    (change.shenpiPower && ctx.helper._.findIndex(change.userGroups[au], { uid: ctx.session.sessionUser.accountId }) !== -1) ?
+                                        cl.spamount : (audit_amount[au - 1] !== undefined ? parseFloat(audit_amount[au - 1]) : null);
+                            }
+                        }
+                        if (change.readOnly && !change.shenpiPower) {
+                            cl.checked_amount = audit_amount.length > 0 ? parseFloat(audit_amount[audit_amount.length - 1]) : 0;
+                        }
+                    }
+                }
+
                 // 工程变更类别读取
                 const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
                 const fun_set = await ctx.service.project.getFunSet(projectData.fun_set);
@@ -642,18 +383,13 @@ module.exports = app => {
                 const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
                 const auth_mobile = pa.auth_mobile;
                 const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
-
-                if (change && change.status !== audit.flow.status.checked && ctx.session.sessionUser.is_admin) {
-                    change.auditors2 = await ctx.service.changeAudit.getListGroupByWithoutYB(change.cid, change.times);
-                }
                 const settleBills = ctx.change.readySettle ? await ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: ctx.change.readySettle.id } }) : [];
                 const settlePos = ctx.change.readySettle ? await ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: ctx.change.readySettle.id } }) : [];
                 // 判断并是否更新结算清单数据
                 await ctx.service.change.checkSettleUpdate(ctx.tender.id, ctx.change.readySettle);
-                // 获取清单
-                const changeList = await ctx.service.changeAuditList.getList(change.cid);
+
                 // 处理清单数据
-                const removeSettleNum = change.status !== audit.flow.status.checked ? await ctx.service.changeSettleList.updateChangeList(change.cid, settleBills, settlePos, changeList) : 0;
+                const removeSettleNum = change.status !== audit.change.status.checked ? await ctx.service.changeSettleList.updateChangeList(change.cid, settleBills, settlePos, changeList) : 0;
                 const renderData = {
                     tender,
                     change,
@@ -661,12 +397,12 @@ module.exports = app => {
                     changeConst,
                     changeClass: fun_set.change_class,
                     changeState: fun_set.change_state,
-                    auditStatus,
-                    auditConst: audit.flow,
+                    auditConst: audit.change,
                     ledgerConsts: audit.ledger.status,
+                    auditType,
+                    auditorGroups: change.userGroups,
                     attList,
                     whiteList,
-                    auditList,
                     showPlanBtn,
                     planList,
                     tpUnit: change.tp_decimal ? change.tp_decimal : ctx.tender.info.decimal.tp,
@@ -683,66 +419,35 @@ module.exports = app => {
                     removeSettleNum,
                 };
                 // 获取是否已存在调用变更令
-                let changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, change.cid);
+                let changeUsedData = await ctx.service.stageChange.getAllFinalUsedData(ctx.tender.id, change.cid);
                 changeUsedData = ctx.helper._.orderBy(ctx.helper._.filter(changeUsedData, function(item) {
                     return item.qty !== null;
                 }), ['sorder'], ['desc']);
                 const useChangeUsedData = [];
                 if (changeUsedData.length > 0) { // 防止未创建期时调用
-                    // const stage = await this.ctx.service.stage.getLastestStage(ctx.tender.id, true);
                     for (const cu of changeUsedData) {
-                        // if (cu.sorder !== 0 ||
-                        //     (cu.sorder === 0 && !(stage.status === audit.stage.status.uncheck || stage.status === audit.stage.status.checkNo))) {
                         const index = ctx.helper._.findIndex(useChangeUsedData, { cbid: cu.cbid });
                         if (index !== -1) {
                             useChangeUsedData[index].qty = ctx.helper.add(useChangeUsedData[index].qty, cu.qty);
                         } else {
                             useChangeUsedData.push(cu);
                         }
-                        // }
                     }
                 }
                 renderData.changeUsedData = useChangeUsedData;
                 renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.qty); }));
-                if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9 || ctx.session.sessionUser.is_admin) {
+                if (!change.readOnly || ctx.session.sessionUser.is_admin) {
                     // 获取所有项目参与者
                     const accountList = await ctx.service.projectAccount.getAllDataByCondition({
                         where: { project_id: ctx.session.sessionProject.id, enable: 1 },
-                        columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group'],
+                        columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile'],
                     });
                     renderData.accountList = accountList;
                     renderData.accountGroup = unitList.map(item => {
                         const groupList = accountList.filter(item1 => item1.company === item.name);
                         return { groupName: item.name, groupList };
                     });
-                }
-                // 根据auditStatus状态获取的不同的数据
-                if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) {
                     renderData.changeUnits = changeConst.units;
-                    // 重新上报获取审批流程
-                    if (auditStatus === 2 || auditStatus === 9) {
-                        const auditList2 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
-                        // 展示页右侧审批流程列表
-                        const auditList3 = [];
-                        for (let time = 1; time <= change.times - 1; time++) {
-                            const auditTimeList = [];
-                            let max_sort = 1;
-                            for (const al of auditList2) {
-                                if (al.times === time) {
-                                    auditTimeList.push(al);
-                                    if (al.usite > max_sort) {
-                                        max_sort = al.usite;
-                                    }
-                                }
-                            }
-                            for (const i in auditTimeList) {
-                                auditTimeList[i].max_sort = max_sort;
-                            }
-                            auditList3.push(auditTimeList);
-                        }
-                        renderData.auditList3 = auditList3;
-                    }
-
                     // 获取公司列表
                     const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                     renderData.companyList = companyList;
@@ -780,95 +485,11 @@ module.exports = app => {
                         renderData.change.class = ctx.helper._.find(fun_set.change_class, { checked: true }).value;
                         await ctx.service.change.saveInfo({ class: ctx.helper._.find(fun_set.change_class, { checked: true }).value });
                     }
-                } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7 || auditStatus === 8) {
-                    // 展示页左侧审批流程列表和清单审批列表数据
-                    const times = change.status === audit.flow.status.back ?
-                        change.times - 1 : change.times;
-                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times);
-
-                    // 展示页右侧审批流程列表
-                    const auditList3 = [];
-                    for (let time = 1; time <= times; time++) {
-                        const auditTimeList = [];
-                        let max_sort = 1;
-                        for (const al of auditList) {
-                            if (al.times === time) {
-                                auditTimeList.push(al);
-                                if (al.usite > max_sort) {
-                                    max_sort = al.usite;
-                                }
-                            }
-                        }
-                        for (const i in auditTimeList) {
-                            auditTimeList[i].max_sort = max_sort;
-                        }
-                        auditList3.push(auditTimeList);
-                    }
-                    renderData.auditList3 = auditList3;
-                    for (const cl of changeList) {
-                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
-                        // 清单表页赋值
-                        for (const [index, au] of auditList2.entries()) {
-                            if (au.usite !== 0) {
-                                cl['audit_amount_' + au.uid] = audit_amount[index - 1] !== undefined ? audit_amount[index - 1] : null;
-                            }
-                        }
-                        cl.changed_amount = ctx.helper._.indexOf([audit.flow.status.backnew, audit.flow.status.checking, audit.flow.status.checked], change.status) !== -1 ?
-                            (audit_amount !== '' ? audit_amount[audit_amount.length - 1] :
-                                (ctx.helper._.indexOf([audit.flow.status.backnew, audit.flow.status.checking], change.status) !== -1 ? cl.camount : 0)) : cl.camount;
-                        // cl.changed_amount = ctx.helper.add(cl.oamount ? parseFloat(cl.oamount) : 0, changed_amount ? parseFloat(changed_amount) : 0);
-                    }
-                    renderData.auditList2 = auditList2;
-                } else if (auditStatus === 6) {
-                    // 展示页左侧审批流程列表和清单审批列表数据
-                    const auditList2 = await ctx.service.changeAudit.getListGroupByTimes(change.cid, change.times);
-                    renderData.auditList2 = auditList2;
-                    const auditList3 = await ctx.service.changeAudit.getListOrderByTimes(change.cid, change.times);
-                    for (const i in auditList3) {
-                        auditList3[i].max_sort = auditList2.length - 1;
-                    }
-                    renderData.auditList3 = auditList3;
-
-                    // 展示页右侧审批流程列表
-                    const auditList5 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
-                    const auditList4 = [];
-                    for (let time = 1; time <= change.times; time++) {
-                        const auditTimeList = [];
-                        let max_sort = 1;
-                        for (const al of auditList5) {
-                            if (al.times === time) {
-                                auditTimeList.push(al);
-                                if (al.usite > max_sort) {
-                                    max_sort = al.usite;
-                                }
-                            }
-                        }
-                        for (const i in auditTimeList) {
-                            auditTimeList[i].max_sort = max_sort;
-                        }
-                        if (auditTimeList.length > 0) {
-                            auditList4.push(auditTimeList);
-                        }
-                    }
-                    renderData.auditList4 = auditList4;
-                    for (const cl of changeList) {
-                        const audit_amount = cl.audit_amount !== null && cl.audit_amount !== '' ? cl.audit_amount.split(',') : '';
-                        // 清单表页赋值
-                        for (const [index, au] of auditList2.entries()) {
-                            if (au.usite !== 0) {
-                                cl['audit_amount_' + au.uid] = au.uid === ctx.session.sessionUser.accountId ? cl.spamount : (audit_amount[index - 1] !== undefined ? audit_amount[index - 1] : null);
-                            }
-                        }
-                        cl.changed_amount = ctx.helper._.indexOf([audit.flow.status.backnew, audit.flow.status.checking, audit.flow.status.checked], change.status) !== -1 ?
-                            (audit_amount !== '' ? audit_amount[audit_amount.length - 1] :
-                                (ctx.helper._.indexOf([audit.flow.status.backnew, audit.flow.status.checking], change.status) !== -1 ? cl.camount : 0)) : cl.camount;
-                        // cl.changed_amount = ctx.helper.add(cl.oamount ? parseFloat(cl.oamount) : 0, changed_amount ? parseFloat(changed_amount) : 0);
-                    }
+                } else if (change.readOnly && change.shenpiPower) {
                     renderData.changeLedgerList = await ctx.service.changeLedger.getAllDataByCondition({ where: { tender_id: ctx.tender.id } });
                     renderData.changePosList = await ctx.service.changePos.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                 }
                 renderData.changeList = changeList;
-                renderData.auditList = auditList;
                 await this.layout('change/information.ejs', renderData, 'change/information_modal.ejs');
             } catch (err) {
                 this.log(err);
@@ -919,7 +540,7 @@ module.exports = app => {
                         await ctx.service.changeAuditList.saveLedgerListDatas(data.updateData, data.postData);
                         // 取所有工料表
                         responseData.data = { changeList: await ctx.service.changeAuditList.getList(ctx.change.cid),
-                            usedList: await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, ctx.change.cid) };
+                            usedList: await ctx.service.stageChange.getAllFinalUsedData(ctx.tender.id, ctx.change.cid) };
                         break;
                     case 'remove_list':
                         await ctx.service.changeAuditList.removeLedgerListDatas(data.updateData);
@@ -999,20 +620,20 @@ module.exports = app => {
                 if (ctx.change.uid !== ctx.session.sessionUser.accountId) {
                     throw '您无权上报该变更令数据';
                 }
-                if (!(ctx.change.status === audit.flow.status.uncheck || ctx.change.status === audit.flow.status.back || ctx.change.status === audit.flow.status.revise)) {
+                if (!(ctx.change.status === audit.change.status.uncheck || ctx.change.status === audit.change.status.checkNo || ctx.change.status === audit.change.status.revise)) {
                     throw '该变更令当前无法上报';
                 }
                 // 判断是否是修订,判断有无审批人员作弊
-                if ((ctx.change.status === audit.flow.status.revise || ctx.change.is_revise) && ctx.tender.info.shenpi.change === shenpiConst.sp_status.sqspr) {
+                if ((ctx.change.status === audit.change.status.revise || ctx.change.is_revise) && ctx.tender.info.shenpi.change === shenpiConst.sp_status.sqspr) {
                     // 获取上一次的审批人流程
-                    const lastUserList = await ctx.service.changeAudit.getListGroupByTimes(ctx.change.cid, ctx.change.times - 1);
+                    const lastUserList = await ctx.service.changeAudit.getUniqAuditor(ctx.change.cid, ctx.change.times - 1);
                     const lastUidList = ctx.helper._.map(lastUserList, 'uid');
                     // 判断上一次审批是否为非原报为审批人
                     const nowUidList = ctx.helper._.map(ctx.change.auditors, 'uid');
                     // 判断条件修订可上报条件
                     // 1.有原报,不管有无其他人   可以添加原报作为审核人,但是不能只原报上报
                     // 2.无原报,有其他人   不可以添加原报
-                    // const noYBUidList = ctx.change.status === audit.flow.status.revise ? ctx.helper._.initial(ctx.helper._.tail(lastUidList)) : ctx.helper._.tail(lastUidList);
+                    // const noYBUidList = ctx.change.status === audit.change.status.revise ? ctx.helper._.initial(ctx.helper._.tail(lastUidList)) : ctx.helper._.tail(lastUidList);
                     const noYBUidList = ctx.helper._.tail(lastUidList);
                     // if (!ctx.helper._.isEqual(lastUidList, nowUidList) && ctx.helper._.includes(noYBUidList, lastUidList[0]) && nowUidList.length === 2 && nowUidList[0] === nowUidList[1]) {
                     if (nowUidList.length === 2 && nowUidList[0] === nowUidList[1]) {
@@ -1048,7 +669,7 @@ module.exports = app => {
                 if (ctx.change.uid !== ctx.session.sessionUser.accountId) {
                     throw '您无权添加审核人';
                 }
-                if (ctx.change.status === audit.flow.status.checking || ctx.change.status === audit.flow.status.checked) {
+                if (ctx.change.status === audit.change.status.checking || ctx.change.status === audit.change.status.checked) {
                     throw '当前不允许添加审核人';
                 }
 
@@ -1065,8 +686,7 @@ module.exports = app => {
                     throw '添加审核人失败';
                 }
 
-                // const auditors = await ctx.service.changeAudit.getAuditorsWithOwner(ctx.change.id, ctx.change.times);
-                const auditors = null;
+                const auditors = await ctx.service.changeAudit.getUserGroup(ctx.change.cid, ctx.change.times);
                 ctx.body = { err: 0, msg: '', data: auditors };
             } catch (err) {
                 this.log(err);
@@ -1184,8 +804,8 @@ module.exports = app => {
                 }
                 const status = parseInt(ctx.request.body.status);
                 // 判断是否到你审批,如果不是则无法审批
-                const curAuditor = await ctx.service.changeAudit.getCurAuditor(changeData.cid, changeData.times);
-                if (!curAuditor || (curAuditor && curAuditor.uid !== ctx.session.sessionUser.accountId)) {
+                const curAuditor = await ctx.service.changeAudit.getCurAuditors(changeData.cid, changeData.times);
+                if (!curAuditor || (curAuditor && ctx.helper._.findIndex(curAuditor, { uid: ctx.session.sessionUser.accountId }) === -1)) {
                     throw '该变更令当前您无权操作';
                 }
                 const readySettle = await ctx.service.settle.getReadySettle(changeData.tid);
@@ -1198,14 +818,14 @@ module.exports = app => {
                     case 3:// 审批通过
                         result = await ctx.service.change.approvalSuccess(pid, ctx.request.body, changeData);
                         break;
-                    case 4:// 审批终止
-                        result = await ctx.service.change.approvalStop(ctx.request.body);
-                        break;
+                    // case 4:// 审批终止
+                    //     result = await ctx.service.change.approvalStop(ctx.request.body);
+                    //     break;
                     case 5:// 审批退回到原报人
-                        result = await ctx.service.change.approvalBack(pid, ctx.request.body, changeData);
+                        result = await ctx.service.change.approvalCheckNo(pid, ctx.request.body, changeData);
                         break;
                     case 6:// 审批退回到上一个审批人
-                        result = await ctx.service.change.approvalBackNew(pid, ctx.request.body, changeData);
+                        result = await ctx.service.change.approvalCheckNoPre(pid, ctx.request.body, changeData);
                         break;
                     default:break;
                 }
@@ -1283,7 +903,7 @@ module.exports = app => {
                 const files = [];
                 let index = 0;
                 const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid });
-                const extra_upload = change.status === audit.flow.status.checked;
+                const extra_upload = change.status === audit.change.status.checked;
                 while ((stream = await parts()) !== undefined) {
                     // 判断用户是否选择上传文件
                     if (!stream.filename) {
@@ -1467,7 +1087,7 @@ module.exports = app => {
                 if (!fileInfo || !Object.keys(fileInfo).length) {
                     throw '该文件不存在';
                 }
-                if (!fileInfo.extra_upload && change.status === audit.flow.status.checked) {
+                if (!fileInfo.extra_upload && change.status === audit.change.status.checked) {
                     throw '无权限删除';
                 }
                 if (fileInfo !== undefined && fileInfo !== '') {
@@ -1549,16 +1169,7 @@ module.exports = app => {
          */
         async checkAgain(ctx) {
             try {
-                const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.cid });
-                if (!changeData) {
-                    throw '变更令数据错误';
-                }
-                // 获取终审
-                const auditInfo = await ctx.service.changeAudit.getAuditorByStatus(changeData.cid, changeData.times, audit.flow.status.checked);
-                if (changeData.status !== audit.flow.status.checked || ctx.session.sessionUser.accountId !== auditInfo.uid) {
-                    throw '您无权进行该操作';
-                }
-                const readySettle = await ctx.service.settle.getReadySettle(changeData.tid);
+                const readySettle = await ctx.service.settle.getReadySettle(ctx.change.tid);
                 if (readySettle && readySettle.settle_order !== ctx.tender.data.settle_order) {
                     throw '结算数据发生变化,请刷新页面再提交';
                 }
@@ -1576,16 +1187,20 @@ module.exports = app => {
                     }
                 }
                 // 重新审批
-                const result = await ctx.service.change.checkAgain(changeData.cid);
-                if (!result) {
-                    throw '重新审批失败';
+                if ((ctx.change.finalAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) && ctx.change.status === audit.change.status.checked) {
+                    const result = await ctx.service.change.checkAgain(ctx.change);
+                    if (!result) {
+                        throw '重新审批失败';
+                    }
+                    // ctx.redirect('/tender/' + changeData.tid + '/change/' + changeData.cid + '/info');
+                    ctx.body = {
+                        err: 0,
+                        url: ctx.request.header.referer,
+                        msg: '',
+                    };
+                } else {
+                    throw '您无权进行该操作';
                 }
-                // ctx.redirect('/tender/' + changeData.tid + '/change/' + changeData.cid + '/info');
-                ctx.body = {
-                    err: 0,
-                    url: ctx.request.header.referer,
-                    msg: '',
-                };
             } catch (err) {
                 console.log(err);
                 // ctx.redirect(ctx.request.header.referer);
@@ -1604,14 +1219,10 @@ module.exports = app => {
          */
         async checkRevise(ctx) {
             try {
-                const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.cid });
-                if (!changeData) {
-                    throw '变更令数据错误';
-                }
-                if (changeData.status !== audit.flow.status.checked || ctx.session.sessionUser.accountId !== changeData.uid) {
+                if (ctx.change.status !== audit.change.status.checked || ctx.session.sessionUser.accountId !== ctx.change.uid) {
                     throw '您无权进行该操作';
                 }
-                const readySettle = await ctx.service.settle.getReadySettle(changeData.tid);
+                const readySettle = await ctx.service.settle.getReadySettle(ctx.change.tid);
                 if (readySettle && readySettle.settle_order !== ctx.tender.data.settle_order) {
                     throw '结算数据发生变化,请刷新页面再提交';
                 }
@@ -1630,13 +1241,13 @@ module.exports = app => {
                 }
 
                 // 获取是否已存在调用变更令
-                // const changeUsedData = await ctx.service.stageChange.getFinalUsedData(ctx.tender.id, changeData.cid);
+                // const changeUsedData = await ctx.service.stageChange.getAllFinalUsedData(ctx.tender.id, changeData.cid);
                 // const stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.qty); }));
                 // if (stageChangeNum !== 0) {
                 //     throw '该变更令已被调用,无法重新审批';
                 // }
                 // 重新审批
-                const result = await ctx.service.change.checkRevise(changeData.cid);
+                const result = await ctx.service.change.checkRevise(ctx.change);
                 if (!result) {
                     throw '修订发起失败';
                 }
@@ -1664,19 +1275,15 @@ module.exports = app => {
          */
         async cancelRevise(ctx) {
             try {
-                const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.cid });
-                if (!changeData) {
-                    throw '变更令数据错误';
-                }
-                if (!(changeData.status === audit.flow.status.revise && (ctx.session.sessionUser.accountId === changeData.uid || ctx.session.sessionUser.accountId === ctx.session.sessionUser.is_admin))) {
+                if (!(ctx.change.status === audit.change.status.revise && (ctx.session.sessionUser.accountId === ctx.change.uid || ctx.session.sessionUser.accountId === ctx.session.sessionUser.is_admin))) {
                     throw '您无权进行该操作';
                 }
-                const readySettle = await ctx.service.settle.getReadySettle(changeData.tid);
+                const readySettle = await ctx.service.settle.getReadySettle(ctx.change.tid);
                 if (readySettle && readySettle.settle_order !== ctx.tender.data.settle_order) {
                     throw '结算数据发生变化,请刷新页面再提交';
                 }
                 // 重新审批
-                const result = await ctx.service.change.cancelRevise(changeData.cid, changeData.times);
+                const result = await ctx.service.change.cancelRevise(ctx.change.cid, ctx.change.times);
                 if (!result) {
                     throw '撤销修订失败';
                 }
@@ -1700,9 +1307,9 @@ module.exports = app => {
                 //     throw '台账修订中,请勿修改提交期数据';
                 // }
                 const data = JSON.parse(ctx.request.body.data);
-                if (ctx.session.sessionUser.is_admin && ctx.change.status !== audit.flow.status.checked) {
+                if (ctx.session.sessionUser.is_admin && ctx.change.status !== audit.change.status.checked) {
                     await ctx.service.changeAudit.saveAudit(ctx.change.cid, ctx.change.times, data);
-                    const auditors = await ctx.service.changeAudit.getListGroupByTimes(ctx.change.cid, ctx.change.times);
+                    const auditors = await ctx.service.changeAudit.getUniqUserGroup(ctx.change.cid, ctx.change.times);
                     ctx.body = { err: 0, msg: '', data: auditors };
                 } else {
                     throw '您无权进行该操作';
@@ -1807,7 +1414,7 @@ module.exports = app => {
                 const change = ctx.change;
                 let edit = true;
                 let changing = false;
-                if (change.status !== audit.flow.status.uncheck && change.status !== audit.flow.status.back && change.status !== audit.flow.status.revise) {
+                if (change.status !== audit.change.status.uncheck && change.status !== audit.change.status.checkNo && change.status !== audit.change.status.revise) {
                     // throw '本条变更审批中或已完成,无法操作台账数据';
                     edit = false;
                     changing = true;
@@ -1861,7 +1468,7 @@ module.exports = app => {
                 if (!data.postType || !data.postData) throw '数据错误';
                 const responseData = { err: 0, msg: '', data: {} };
                 const change = ctx.change;
-                if (change.status !== audit.flow.status.uncheck && change.status !== audit.flow.status.back && change.status !== audit.flow.status.revise) {
+                if (change.status !== audit.change.status.uncheck && change.status !== audit.change.status.checkNo && change.status !== audit.change.status.revise) {
                     throw '该变更令正在审批中或已完成,无法操作新增部位数据';
                 }
                 // 判断是否在修订中,是则无法操作本页

+ 1 - 1
app/controller/dashboard_controller.js

@@ -96,7 +96,7 @@ module.exports = app => {
                 authMobile: pa.auth_mobile,
                 acLedger: auditConst.ledger,
                 acStage: auditConst.stage,
-                acChange: auditConst.flow,
+                acChange: auditConst.change,
                 acRevise: auditConst.revise,
                 acMaterial: auditConst.material,
                 acAdvance: auditConst.advance,

+ 1 - 1
app/controller/revise_controller.js

@@ -43,7 +43,7 @@ module.exports = app => {
          */
         async _getAddReviseValid(ctx) {
             const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
-            const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true);
+            const lastStage = await ctx.service.stage.getFlowLatestStage(ctx.tender.id, true);
             const addVisible = (ctx.tender.data.user_id === ctx.session.sessionUser.accountId) &&
                 (ctx.tender.data.ledger_status === audit.ledger.status.checked) &&
                 (!revise || !revise.valid || revise.status === audit.revise.status.checked);

+ 2 - 7
app/controller/schedule_controller.js

@@ -275,15 +275,10 @@ module.exports = app => {
                 tid: ctx.tender.id,
                 order: stageOrder,
             });
-            let preStageData;
+            await ctx.service.stage.loadPreCheckedStage(stageInfo);
             // 当前操作人查看最新数据,其他人查看历史数据
             const curStageData = await ctx.service.stageBills.getLastestStageData2(ctx.tender.id, stageInfo.id);
-            // 查询截止上期数据
-            if (stageInfo.order > 1) {
-                preStageData = await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, stageInfo.order - 1);
-            } else {
-                preStageData = [];
-            }
+            const preStageData = stageInfo.preCheckedStage ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, stageInfo.preCheckedStage.order) : [];
             const pcData = await ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stageInfo.id } });
             this.ctx.helper.assignRelaData(ledgerData, [
                 { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid' },

+ 1 - 1
app/controller/setting_controller.js

@@ -1388,7 +1388,7 @@ module.exports = app => {
                 const code = ctx.query.code;
                 const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectData.id, code);
                 const renderData = {
-                    BaseSetCol: sType.indexOf('stage') > 0 ? SpreadConst.BaseSetCol.Stage : SpreadConst.BaseSetCol.Ledger,
+                    BaseSetCol: SpreadConst.BaseSetCol[sType],
                     sType,
                     code,
                     colSet: projectSpread[sType],

+ 23 - 0
app/controller/stage_controller.js

@@ -399,6 +399,16 @@ module.exports = app => {
             }
         }
 
+        async _innerCheckChangeBillsOver(ctx, checkData) {
+            const change = await this.ctx.service.change.getAllDataByCondition({ where: { tid: ctx.tender.id }});
+            if (change.length > 0) {
+                const cid = change.map(x => { return x.cid; });
+                const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid } });
+                const endStageChange = await this.ctx.service.stageChange.getFinalUsedData(ctx.tender.id, cid);
+                checkData.checkChangeBillsOver(change, changeBills, endStageChange, ctx.stage.id);
+            }
+        }
+
         async check(ctx) {
             try {
                 const helper = this.ctx.helper;
@@ -437,6 +447,9 @@ module.exports = app => {
                     }
                 }
                 if (ctx.stage.readySettle) checkData.checkSettle();
+                if (ctx.stage.status === auditConst.status.uncheck || ctx.stage.status === auditConst.status.checkNo) {
+                    await this._innerCheckChangeBillsOver(ctx, checkData);
+                }
                 ctx.body = { err: 0, msg: '', data: checkData.checkResult };
             } catch (err) {
                 this.log(err);
@@ -457,6 +470,13 @@ module.exports = app => {
             return checkData.checkResult.error;
         }
 
+        async _checkChangeBillsOver(ctx) {
+            const checkDataModel = require('../lib/ledger').checkData;
+            const checkData = new checkDataModel(ctx, measureType);
+            await this._innerCheckChangeBillsOver(ctx, checkData);
+            return checkData.checkResult.error;
+        }
+
         async stageCheck(ctx) {
             try {
                 if (!ctx.query.type) throw '参数错误';
@@ -467,6 +487,9 @@ module.exports = app => {
                         case 'minus_cb':
                             result.minus_cb = await this._checkMinusChangeBills(ctx);
                             break;
+                        case 'change_over':
+                            result.change_over = await this._checkChangeBillsOver(ctx);
+                            break;
                     }
                 }
                 ctx.body = { err: 0, msg: '', data: result };

+ 6 - 3
app/controller/tender_controller.js

@@ -241,6 +241,8 @@ module.exports = app => {
 
         async listInfoFinish(ctx) {
             this.jsFiles = this.app.jsFiles.tender.info;
+            const projectColSet = await ctx.service.projectColSet.getProjectColSet(ctx.session.sessionProject.id);
+            this.colSet = ctx.service.projectColSet.analysisColSetWithDefine(projectSetting.colSet.info, projectColSet.info);
             await this._listDetailFinish('tender/info.ejs', 'tender/modal.ejs');
         }
 
@@ -1095,10 +1097,11 @@ module.exports = app => {
                     fujianOssPath: ctx.app.config.fujianOssPath,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tender.cert),
                 };
-                const accountList = await ctx.service.projectAccount.getAllDataByCondition({
-                    where: { project_id: ctx.session.sessionProject.id, enable: 1, id: ctx.helper._.uniq(ctx.helper._.map(allCertList, 'uid')) },
+                const uidList = ctx.helper._.uniq(ctx.helper._.map(allCertList, 'uid'));
+                const accountList = uidList.length > 0 ? await ctx.service.projectAccount.getAllDataByCondition({
+                    where: { project_id: ctx.session.sessionProject.id, enable: 1, id: uidList },
                     columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile'],
-                });
+                }) : [];
                 renderData.accountList = accountList;
                 const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
                 renderData.accountGroup = unitList.map(item => {

+ 39 - 23
app/controller/wap_controller.js

@@ -16,6 +16,7 @@ const fs = require('fs');
 const path = require('path');
 const sendToWormhole = require('stream-wormhole');
 const moment = require('moment');
+const auditType = require('../const/audit').auditType;
 
 module.exports = app => {
 
@@ -258,7 +259,24 @@ module.exports = app => {
                 const changes = await ctx.service.change.getListByStatus(tender.id, 0, 0);
 
                 for (const c of changes) {
-                    c.curAuditor = await ctx.service.changeAudit.getLastUser(c.cid, c.times);
+                    c.showApprovalBtn = false;
+                    c.curAuditors = await ctx.service.changeAudit.getAuditorsByStatus(c.cid, c.status, c.times);
+                    if (c.status === auditConst.change.status.checkNoPre) {
+                        c.curAuditors2 = await ctx.service.stageAudit.getAuditorsByStatus(c.cid, auditConst.change.status.checking, c.times);
+                        const curAudit = c.curAuditors2.find(function(x) {
+                            return x.uid === ctx.session.sessionUser.accountId;
+                        });
+                        if (curAudit && curAudit.status === auditConst.change.status.checking) {
+                            c.showApprovalBtn = true;
+                        }
+                    } else {
+                        const curAudit = c.curAuditors.find(function(x) {
+                            return x.uid === ctx.session.sessionUser.accountId;
+                        });
+                        if (curAudit && curAudit.status === auditConst.change.status.checking) {
+                            c.showApprovalBtn = true;
+                        }
+                    }
                 }
 
                 // 变更令列表
@@ -293,7 +311,7 @@ module.exports = app => {
                     revises,
                     advanceList,
                     auditConst: auditConst.stage,
-                    auditChangeConst: auditConst.flow,
+                    auditChangeConst: auditConst.change,
                     auditChangePlanConst: auditConst.changePlan,
                     auditReviseConst: auditConst.revise,
                     changeConst,
@@ -368,18 +386,21 @@ module.exports = app => {
         async change(ctx) {
             try {
                 const tender = ctx.tender.data;
-                const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid });
-                const times = change.status !== auditConst.flow.status.back ? change.times : change.times - 1;
+                const change = ctx.change;
+                const times = change.status !== auditConst.change.status.checkNo && change.status !== auditConst.change.status.revise ? change.times : change.times - 1;
                 const auditList = await ctx.service.changeAudit.getListOrderByTimes(change.cid, times);
                 const auditGroupList = await ctx.service.changeAudit.getListGroupByTimes(change.cid, times);
+                await ctx.service.change.loadChangeAuditViewData(ctx.change);
                 const renderData = {
+                    moment,
                     tender,
                     change,
                     auditList,
                     auditGroupList,
-                    auditConst: auditConst.flow,
+                    auditConst: auditConst.change,
                     changeConst,
                     tpUnit: ctx.tender.info.decimal.tp,
+                    auditType,
                 };
                 await ctx.render('wap/shenpi_change.ejs', renderData);
             } catch (err) {
@@ -516,40 +537,35 @@ module.exports = app => {
          */
         async changeApproval(ctx) {
             try {
-                const changeData = await ctx.service.change.getDataByCondition({ cid: ctx.request.body.change_id });
+                const cid = ctx.request.body.change_id;
+                const changeData = await ctx.service.change.getDataByCondition({ cid });
                 if (!changeData) {
                     throw '变更令数据错误';
                 }
                 // 判断是否到你审批,如果不是则无法审批
-                const curAuditor = await ctx.service.changeAudit.getCurAuditor(changeData.cid, changeData.times);
-                if (!curAuditor || (curAuditor && curAuditor.uid !== ctx.session.sessionUser.accountId)) {
+                const curAuditor = await ctx.service.changeAudit.getCurAuditors(changeData.cid, changeData.times);
+                if (!curAuditor || (curAuditor && ctx.helper._.findIndex(curAuditor, { uid: ctx.session.sessionUser.accountId }) === -1)) {
                     throw '该变更令当前您无权操作';
                 }
+                const readySettle = await ctx.service.settle.getReadySettle(changeData.tid);
+                if (readySettle && readySettle.settle_order !== ctx.tender.data.settle_order) {
+                    throw '结算数据发生变化,请刷新页面再提交';
+                }
                 const status = parseInt(ctx.request.body.status);
                 const pid = this.ctx.session.sessionProject.id;
                 let result = false;
                 switch (status) {
                     case 3:// 审批通过
-                        // 获取前一个人的list,生成bills_list
-                        // 获取已选清单
-                        const changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.request.body.change_id } });
-                        const bills_array = [];
-                        for (const cl of changeList) {
-                            const bill = cl.id + '_' + cl.spamount;
-                            bills_array.push(bill);
-                        }
-                        const postData = ctx.request.body;
-                        postData.bills_list = bills_array.join(',');
                         result = await ctx.service.change.approvalSuccess(pid, ctx.request.body, changeData);
                         break;
-                    case 4:// 审批终止
-                        result = await ctx.service.change.approvalStop(ctx.request.body);
-                        break;
+                    // case 4:// 审批终止
+                    //     result = await ctx.service.change.approvalStop(ctx.request.body);
+                    //     break;
                     case 5:// 审批退回到原报人
-                        result = await ctx.service.change.approvalBack(pid, ctx.request.body, changeData);
+                        result = await ctx.service.change.approvalCheckNo(pid, ctx.request.body, changeData);
                         break;
                     case 6:// 审批退回到上一个审批人
-                        result = await ctx.service.change.approvalBackNew(pid, ctx.request.body, changeData);
+                        result = await ctx.service.change.approvalCheckNoPre(pid, ctx.request.body, changeData);
                         break;
                     default:break;
                 }

+ 43 - 0
app/lib/ledger.js

@@ -1079,6 +1079,49 @@ class checkData {
             });
         });
     }
+    checkChangeBillsOver(change, changeBills, finalStageChange, curStageId) {
+        const error = this.checkResult.error;
+        const helper = this.ctx.helper;
+        const changeIndex = {};
+        change.forEach(c => {
+            changeIndex[c.cid] = c;
+            c.bills = [];
+            c.billsIndex = {};
+            c.stageChange = [];
+        });
+        changeBills.forEach(cb => {
+            const c = changeIndex[cb.cid];
+            if (c) c.bills.push(cb);
+            c.billsIndex[cb.id] = cb;
+            cb.used_qty = 0;
+            cb.qty = parseFloat(cb.samount);
+        });
+        finalStageChange.forEach(sc => {
+            if (!sc.qty) return;
+            const c = changeIndex[sc.cid];
+            if (c) {
+                c.used = true;
+                const cb = c.billsIndex[sc.cbid];
+                if (cb) {
+                    cb.used_qty = helper.add(cb.used_qty, sc.qty);
+                    if (sc.sid === curStageId) {
+                        cb.cur_used = true;
+                        cb.lid = sc.lid;
+                    }
+                }
+            }
+        });
+        change.forEach(c => {
+            if (!c.used) return;
+            c.bills.forEach(b => {
+                if (!b.cur_used) return;
+                const qtyDecimal = helper.findDecimal(b.unit);
+                const limitQty = helper.mul(b.qty, helper.div(b.delimit, 100, 2), qtyDecimal);
+                if (Math.abs(b.used_qty) > Math.abs(limitQty)) error.push({ b_code: b.code, name: b.name, errorType: 'change_over', memo: c.code, lid: b.lid, used_qty: b.used_qty, limit_qty: limitQty });
+
+            });
+        });
+    }
 
     checkSettle() {
         const settleStatus = this.ctx.service.settle.settleStatus;

+ 76 - 0
app/lib/revise_price.js

@@ -53,6 +53,14 @@ class revisePriceCalc {
         });
     }
 
+    findCommonChangeBillsPrice(b_code, name, unit, unit_price) {
+        const helper = this.ctx.helper;
+        const p = this.price.find(x => {
+            return b_code === x.b_code && name === x.name && unit === x.unit && helper.numEqual(unit_price, x.org_price);
+        });
+        return p;
+    }
+
     /**
      * 新增一期计量,检查单价调整
      * @param {Object} newStage - 新计量期
@@ -250,6 +258,72 @@ class revisePriceCalc {
         }
         if (revisePriceUpdate.length > 0) await transaction.updateRows(this.ctx.service.revisePrice.tableName, revisePriceUpdate);
     }
+    /**
+     * 重算变更方案(调整单价)
+     * @param {Object} change - 工程变更
+     * @param {Object} transaction - 事务 (无则非事务提交)
+     */
+    async calcChangePlan(changePlan, transaction) {
+        const decimal = changePlan.decimal ? JSON.parse(changePlan.decimal) : this.ctx.tender.info.decimal;
+        const changeBills = await this.ctx.service.changePlanList.getAllDataByCondition({ where: { cpid: changePlan.id } });
+        const updateBills = [];
+        let total_price = 0;
+        for (const b of changeBills) {
+            const p = this.findCommonChangeBillsPrice(b.code, b.name, b.unit, b.unit_price);
+            let bills_tp;
+            if (p) {
+                bills_tp = this.ctx.helper.mul(p.new_price, b.spamount, decimal.tp);
+                updateBills.push({ id: b.id, unit_price: p.new_price });
+            } else {
+                bills_tp = this.ctx.helper.mul(b.unit_price, b.spamount, decimal.tp);
+            }
+            total_price = this.ctx.helper.add(total_price, bills_tp);
+        }
+        if (updateBills.length > 0) {
+            await transaction.updateRows(this.ctx.service.changePlanList.tableName, updateBills);
+            await transaction.update(this.ctx.service.changePlan.tableName, { id: changePlan.id, total_price});
+        }
+    }
+    async calcAllChangePlan(tid, transaction) {
+        const changePlan = await this.ctx.service.changePlan.getAllDataByCondition({ where: { tid } });
+        if (changePlan.length === 0) return;
+        for (const c of changePlan) {
+            await this.calcChangePlan(c, transaction);
+        }
+    }
+    /**
+     * 重算变更申请(调整单价)
+     * @param {Object} change - 工程变更
+     * @param {Object} transaction - 事务 (无则非事务提交)
+     */
+    async calcChangeApply(changeApply, transaction) {
+        const decimal = changeApply.decimal ? JSON.parse(changeApply.decimal) : this.ctx.tender.info.decimal;
+        const changeBills = await this.ctx.service.changeApplyList.getAllDataByCondition({ where: { caid: changeApply.id } });
+        const updateBills = [];
+        let total_price = 0;
+        for (const b of changeBills) {
+            const p = this.findCommonChangeBillsPrice(b.code, b.name, b.unit, b.unit_price);
+            let bills_tp;
+            if (p) {
+                bills_tp = this.ctx.helper.mul(p.new_price, b.camount, decimal.tp);
+                updateBills.push({ id: b.id, unit_price: p.new_price });
+            } else {
+                bills_tp = this.ctx.helper.mul(b.unit_price, b.camount, decimal.tp);
+            }
+            total_price = this.ctx.helper.add(total_price, bills_tp);
+        }
+        if (updateBills.length > 0) {
+            await transaction.updateRows(this.ctx.service.changeApplyList.tableName, updateBills);
+            await transaction.update(this.ctx.service.changeApply.tableName, { id: changeApply.id, total_price});
+        }
+    }
+    async calcAllChangeApply(tid, transaction) {
+        const changeApply = await this.ctx.service.changeApply.getAllDataByCondition({ where: { tid } });
+        if (changeApply.length === 0) return;
+        for (const c of changeApply) {
+            await this.calcChangeApply(c, transaction);
+        }
+    }
     async _calcStage(stage, bills, transaction) {
         const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 };
         // 无单价变更不执行
@@ -454,6 +528,8 @@ class revisePriceCalc {
         const pcTp = await this.calcReviseLedger(revise, transaction);
         // 引用到所有工程变更
         await this.calcAllChanges(revise.tid, transaction);
+        await this.calcAllChangePlan(revise.tid, transaction);
+        await this.calcAllChangeApply(revise.tid, transaction);
         return pcTp;
     }
 }

+ 30 - 9
app/middleware/change_audit_check.js

@@ -8,7 +8,7 @@
  * @version
  */
 
-const status = require('../const/audit').flow.status;
+const status = require('../const/audit').change.status;
 const shenpiConst = require('../const/shenpi');
 const _ = require('lodash');
 
@@ -28,26 +28,47 @@ module.exports = options => {
             if (!cid) {
                 throw '您访问的变更令不存在';
             }
-            const change = yield this.service.change.getDataByCondition({ cid });
-            if (!change) throw '变更令数据有误';
-            if ((change.status === status.uncheck || change.status === status.back || change.status === status.revise) && this.tender.info.shenpi.change !== shenpiConst.sp_status.sqspr) {
+            // const change = yield this.service.change.getDataByCondition({ cid });
+            if (!this.change) {
+                const change = yield this.service.change.getDataByCondition({ cid });
+                if (!change) throw '变更令数据有误';
+                yield this.service.change.loadChangeUser(change);
+                this.change = change;
+            }
+            const change = this.change;
+            if ((change.status === status.uncheck || change.status === status.checkNo || change.status === status.revise) && this.tender.info.shenpi.change !== shenpiConst.sp_status.sqspr) {
                 const shenpi_status = this.tender.info.shenpi.change;
                 // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
-                const auditList = yield this.service.changeAudit.getAllDataByCondition({ where: { cid: change.cid, times: change.times }, orders: [['usort', 'asc']] });
+                const auditList = yield this.service.changeAudit.getAllDataByCondition({ where: { cid: change.cid, times: change.times }, orders: [['usite', 'asc']] });
                 auditList.shift();
                 const auditIdList = _.map(auditList, 'uid');
                 if (shenpi_status === shenpiConst.sp_status.gdspl) {
                     const shenpiList = yield this.service.shenpiAudit.getAllDataByCondition({ where: { tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status } });
-                    const shenpiIdList = _.map(shenpiList, 'audit_id');
+                    // const shenpiIdList = _.map(shenpiList, 'audit_id');
                     // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
-                    if (!_.isEqual(auditIdList, shenpiIdList)) {
-                        yield this.service.changeAudit.updateNewAuditList(change, shenpiIdList);
+                    let sameAudit = auditList.length === shenpiList.length;
+                    if (sameAudit) {
+                        for (const audit of auditList) {
+                            const shenpi = shenpiList.find(x => { return x.audit_id === audit.uid; });
+                            if (!shenpi || shenpi.audit_order !== audit.audit_order || shenpi.audit_type !== audit.audit_type) {
+                                sameAudit = false;
+                                break;
+                            }
+                        }
+                    }
+                    if (!sameAudit) {
+                        yield this.service.changeAudit.updateNewAuditList(change, shenpiList);
+                        yield this.service.change.loadChangeUser(change);
+                        yield this.service.change.doCheckChangeCanCancel(change);
                     }
                 } else if (shenpi_status === shenpiConst.sp_status.gdzs) {
                     const shenpiInfo = yield this.service.shenpiAudit.getDataByCondition({ tid: this.tender.id, sp_type: shenpiConst.sp_type.change, sp_status: shenpi_status });
                     // 判断最后一个id是否与固定终审id相同,不同则删除原审批流中如果存在的id和添加终审
-                    if (shenpiInfo && shenpiInfo.audit_id !== _.last(auditIdList)) {
+                    const lastAuditors = auditList.filter(x => { return x.usite === auditList.length - 1; });
+                    if (shenpiInfo && (lastAuditors.length === 0 || (lastAuditors.length > 1 || shenpiInfo.audit_id !== lastAuditors[0].uid))) {
                         yield this.service.changeAudit.updateLastAudit(change, auditList, shenpiInfo.audit_id);
+                        yield this.service.change.loadChangeUser(change);
+                        yield this.service.change.doCheckChangeCanCancel(change);
                     } else if (!shenpiInfo) {
                         // 不存在终审人的状态下这里恢复为授权审批人
                         this.tender.info.shenpi.change = shenpiConst.sp_status.sqspr;

+ 29 - 15
app/middleware/change_check.js

@@ -8,7 +8,7 @@
  * @version
  */
 
-const status = require('../const/audit').flow.status;
+const status = require('../const/audit').change.status;
 const shenpiConst = require('../const/shenpi');
 const _ = require('lodash');
 
@@ -30,47 +30,61 @@ module.exports = options => {
             }
             const change = yield this.service.change.getDataByCondition({ cid });
             // 读取原报、审核人数据
-            change.auditors = yield this.service.changeAudit.getListGroupByTimes(change.cid, change.times);
-            change.curAuditor = yield this.service.changeAudit.getCurAuditor(change.cid, change.times);
+            // 读取原报、审核人数据
+            yield this.service.change.loadChangeUser(change);
+            // change.auditors = yield this.service.changeAudit.getListGroupByTimes(change.cid, change.times);
+            // change.curAuditor = yield this.service.changeAudit.getCurAuditor(change.cid, change.times);
 
             if (!change) throw '变更令数据有误';
             // 权限相关
             // todo 校验权限 (变更参与人)
             const accountId = this.session.sessionUser.accountId,
-                auditorIds = _.map(change.auditors, 'uid'),
                 shareIds = [];
             const permission = this.session.sessionUser.permission;
+            // if (change.status === status.uncheck || change.status === status.checkNo) {
+            //     change.readOnly = accountId !== change.uid;
+            // } else if (change.status === status.checked) {
+            //     change.readOnly = true;
+            // } else {
+            //     change.readOnly = change.flowAuditors.indexOf(accountId) < 0;
+            //     if (!change.readOnly) {
+            //         change.readOnly = !_.isEqual(change.flowAuditorIds, change.curAuditorIds);
+            //         change.canCheck = true;
+            //     }
+            // }
             if (accountId === change.uid) { // 原报
-                if (change.curAuditor) {
-                    change.readOnly = change.curAuditor.uid !== accountId;
-                } else {
-                    change.readOnly = change.status !== status.uncheck && change.status !== status.back && change.status !== status.revise;
-                }
+                change.curTimes = change.times;
+                change.filePermission = true;
             } else if (this.tender.isTourist) {
-                change.readOnly = true;
-            } else if (auditorIds.indexOf(accountId) !== -1) { // 审批人
+                change.curTimes = change.times;
+                change.filePermission = this.tender.touristPermission.file || change.auditorIds.indexOf(accountId) !== -1;
+            } else if (change.auditorIds.indexOf(accountId) !== -1) { // 审批人
                 if (change.status === status.uncheck) {
                     throw '您无权查看该数据';
                 }
-                change.readOnly = true;
+                change.curTimes = change.status === status.checkNo || change.status === status.revise ? change.times - 1 : change.times;
+                change.filePermission = true;
             } else if (shareIds.indexOf(accountId) !== -1 || (permission !== null && permission.tender !== undefined && permission.tender.indexOf('2') !== -1)) { // 分享人
                 if (change.status === status.uncheck) {
                     throw '您无权查看该数据';
                 }
                 change.readOnly = true;
-            } else if (change.status === status.back && change.uid !== accountId) {
+            } else if ((change.status === status.checkNo || change.status === status.revise) && change.uid !== accountId) {
                 const preAuditors = yield this.service.changeAudit.getListGroupByTimes(change.cid, change.times - 1);
                 const preAuditorIds = _.map(preAuditors, 'uid');
                 if (preAuditorIds.indexOf(accountId) === -1) {
                     throw '您无权查看该数据';
                 }
-                change.readOnly = true;
+                change.filePermission = true;
             } else { // 其他不可见
                 throw '您无权查看该数据';
             }
             change.readySettle = yield this.service.settle.getReadySettle(change.tid);
+            // 调差的readOnly 指表格和页面只能看不能改,和审批无关
+            change.readOnly = !((change.status === status.uncheck || change.status === status.checkNo || change.status === status.revise) && accountId === change.uid);
+            change.shenpiPower = (change.status === status.checking || change.status === status.checkNoPre) && change.curAuditorIds.indexOf(accountId) !== -1;
             this.change = change;
-            if ((change.status === status.uncheck || change.status === status.back || change.status === status.revise) && change.tp_decimal !== this.tender.info.decimal.tp) {
+            if ((change.status === status.uncheck || change.status === status.checkNo || change.status === status.revise) && change.tp_decimal !== this.tender.info.decimal.tp) {
                 this.change.tp_decimal = this.tender.info.decimal.tp;
                 yield this.service.change.updateDecimalAndTp();
             }

+ 3 - 0
app/public/css/main.css

@@ -48,6 +48,9 @@ font-size: .875rem;
   font-weight: normal;
   color:#000;
 }
+.table td{
+    vertical-align: middle;
+}
 .table.table-dark th {
   background:none;
   font-weight: normal;

+ 133 - 1
app/public/js/change.js

@@ -134,9 +134,141 @@ class codeRuleSet {
         });
     }
 }
+/**
+ * 期计量 - 期列表页面 js
+ *
+ * @author Mai
+ * @date 2018/12/7
+ * @version
+ */
+const getGroupAuditHtml = function (group) {
+    return group.map(u => { return `<small class="d-inline-block text-dark mx-1" title="${u.role}" data-auditorId="${u.aid}">${u.name}</small>`; }).join('');
+};
+
+const getAuditTypeHtml = function (type) {
+    if (type === auditType.key.common) return '';
+    return `<div class="li-subscript"><span class="badge badge-pill badge-${auditType.info[type].class} p-1 badge-bg-small"><small>${auditType.info[type].short}</small></span></div>`;
+};
 
+const getAuditTypeText = function (type) {
+    if (type === auditType.key.common) return '';
+    return `<span class="text-${auditType.info[type].class}">${auditType.info[type].long}</span>`;
+};
 $(document).ready(() => {
 
+    // 获取审批流程
+    $('a[data-target="#sp-list" ]').on('click', function () {
+        const data = {
+            cid: $(this).attr('c-id'),
+        };
+        postData('/tender/' + tenderId + '/change/auditors', data, function (result) {
+            const { auditHistory, auditors2, user } = result;
+            let auditorsHTML = [];
+            auditors2.forEach((group, idx) => {
+                if (idx === 0) {
+                    auditorsHTML.push(`<li class="list-group-item d-flex justify-content-between align-items-center">
+                    <span class="mr-1"><i class="fa fa fa-play-circle fa-rotate-90"></i></span>
+                <span class="text-muted">${getGroupAuditHtml(group)}</span>
+                <span class="badge badge-light badge-pill ml-auto"><small>原报</small></span>
+                </li>`);
+                } else if(idx === auditors2.length -1 && idx !== 0) {
+                    auditorsHTML.push(`<li class="list-group-item d-flex justify-content-between align-items-center">
+                    <span class="mr-1"><i class="fa fa fa-stop-circle fa-rotate-90"></i></span>
+                <span class="text-muted">${getGroupAuditHtml(group)}</span>
+                <div class="d-flex ml-auto">
+                ${getAuditTypeHtml(group[0].audit_type)}
+                <span class="badge badge-light badge-pill ml-auto"><small>终审</small></span>
+                </div>
+                </li>`);
+                } else {
+                    auditorsHTML.push(`<li class="list-group-item d-flex justify-content-between align-items-center">
+                    <span class="mr-1"><i class="fa fa fa-chevron-circle-down"></i></span>
+                <span class="text-muted">${getGroupAuditHtml(group)}</span>
+                <div class="d-flex ml-auto">
+                ${getAuditTypeHtml(group[0].audit_type)}
+                <span class="badge badge-light badge-pill"><small>${transFormToChinese(idx)}审</small></span>
+                </div>
+                </li>`);
+                }
+            });
+            $('#auditor-list').empty();
+            $('#auditor-list').append(auditorsHTML.join(''));
+
+            let historyHTML = [];
+            auditHistory.forEach((his, idx) => {
+                if (idx === auditHistory.length - 1 && auditHistory.length !== 1) {
+                    historyHTML.push(`<div class="text-right"><a href="javascript: void(0);" id="fold-btn" data-target="show">展开历史审批流程</a></div>`);
+                }
+                historyHTML.push(`<div class="${idx < auditHistory.length - 1 ? 'fold-card' : ''}">`);
+                historyHTML.push(`<div class="text-center text-muted">${idx+1}#</div>`);
+                historyHTML.push(`<ul class="timeline-list list-unstyled mt-2 ${ idx === auditHistory.length - 1 && auditHistory.length !== 1 ? 'last-auditor-list' : '' }">`);
+                his.forEach((group, index) => {
+                    historyHTML.push(`<li class="timeline-list-item pb-2 ${ group.status === auditConst.status.uncheck && idx === auditHistory.length - 1 && auditHistory.length !== 1 ? 'is_uncheck' : ''}">`);
+                    if (group.endYear) {
+                        historyHTML.push(`<div class="timeline-item-date">${group.endYear}<span>${group.endDate}</span><span>${group.endTime}</span></div>`);
+                    }
+                    if (index < his.length - 1) {
+                        historyHTML.push('<div class="timeline-item-tail"></div>');
+                    }
+                    if (group.status === auditConst.status.checked || group.status === auditConst.status.cancelRevise) {
+                        historyHTML.push('<div class="timeline-item-icon bg-success text-light"><i class="fa fa-check"></i></div>');
+                    } else if (group.status === auditConst.status.checkNo || group.status === auditConst.status.checkNoPre || group.status === auditConst.status.revise || group.status === auditConst.status.checkCancel) {
+                        historyHTML.push('<div class="timeline-item-icon bg-warning text-light"><i class="fa fa-level-up"></i></div>');
+                    } else if (group.status === auditConst.status.checking) {
+                        historyHTML.push('<div class="timeline-item-icon bg-warning text-light"><i class="fa fa-ellipsis-h"></i></div>');
+                    } else if(group.status === auditConst.status.checkAgain) {
+                        historyHTML.push('<div class="timeline-item-icon bg-warning text-light"><i class="fa fa-check"></i></div>');
+                    } else {
+                        historyHTML.push('<div class="timeline-item-icon bg-secondary text-light"></div>');
+                    }
+
+                    historyHTML.push('<div class="timeline-item-content">');
+                    historyHTML.push('<div class="py-1">');
+                    if (index === 0) {
+                        historyHTML.push('<span class="text-black-50">原报</span>');
+                        historyHTML.push(`<span class="pull-right text-success">${idx !== 0 ? '重新' : ''}上报审批</span>`);
+                    } else {
+                        const statuStr = group.status !== auditConst.status.uncheck ?
+                            `<span class="pull-right ${auditConst.statusClass[group.status]}">${auditConst.statusString[group.status]}</span>` : '';
+                        historyHTML.push(`
+                        <span class="text-black-50">
+                        ${ group.audit_order === 0 ? '原报' : !group.is_final ? group.audit_order + '审' : '终审' } ${getAuditTypeText(group.audit_type)}
+                        </span>
+                        ${statuStr}`);
+                    }
+                    historyHTML.push('</div>');
+                    historyHTML.push('<div class="card"><div class="card-body px-3 py-0">');
+                    for (const [i, auditor] of group.auditors.entries()) {
+                        historyHTML.push(`<div class="card-text p-2 py-3 row ${ ( i > 0 ? 'border-top' : '') }">`);
+                        historyHTML.push(`<div class="col"><span class="h6">${auditor.name}</span><span class="text-muted ml-1">${auditor.role}</span></div>`);
+                        historyHTML.push('<div class="col">');
+                        if (auditor.status === auditConst.status.checked || group.status === auditConst.status.cancelRevise) {
+                            historyHTML.push('<span class="pull-right text-success"><i class="fa fa-check-circle"></i></span>');
+                        } else if (auditor.status === auditConst.status.checkNo || auditor.status === auditConst.status.checkNoPre || group.status === auditConst.status.revise || auditor.status === auditConst.status.checkCancel) {
+                            historyHTML.push('<span class="pull-right text-warning"><i class="fa fa-share-square fa-rotate-270"></i></span>');
+                        } else if (auditor.status === auditConst.status.checking) {
+                            historyHTML.push('<span class="pull-right text-warning"><i class="fa fa-commenting"></i></span>');
+                        } else if (auditor.status === auditConst.status.checkAgain) {
+                            historyHTML.push('<span class="pull-right text-warning"><i class="fa fa-check"></i></span>');
+                        }
+                        historyHTML.push('</div>');
+                        if (auditor.sdesc) {
+                            historyHTML.push(`<div class="col-12 py-1 bg-light"><i class="fa fa-commenting-o mr-1"></i>${auditor.sdesc}</div>`);
+                        }
+                        historyHTML.push('</div>');
+                    }
+                    historyHTML.push('</div></div>');
+                    historyHTML.push('</div>');
+                    historyHTML.push('</li>');
+                });
+                historyHTML.push('</div>');
+                historyHTML.push('</ul>');
+            });
+            $('#audit-list').empty();
+            $('#audit-list').append(historyHTML.join(''));
+        });
+    });
+
     $("#change-table").colResizable({
         liveDrag:true,
         gripInnerHtml:"<div class='grip'></div>",
@@ -374,5 +506,5 @@ $(document).ready(() => {
             link += '&pageSize=' + getLocalCache('account-pageSize');
         }
         window.location.href = link;
-    })
+    });
 });

+ 58 - 62
app/public/js/change_audit.js

@@ -84,66 +84,62 @@ $(document).ready(function () {
     // 添加到审批流程中
     $('dl').on('click', 'dd', function () {
         const id = parseInt($(this).data('id'));
-        if (id) {
-            const auditListIdData = [];
-            $('#auditList li').each(function () {
-                const aid = $(this).data('auditid');
-                auditListIdData.push(aid);
-            });
-            if (!in_array(auditListIdData, id)) {
-                postData(getUrlPre() + '/audit/add', { auditorId: id }, (datas) => {
-                    if (shenpi_status === shenpiConst.sp_status.gdzs) {
-                        auditListIdData.splice(-1,0,id);
-                    } else {
-                        auditListIdData.push(id);
-                    }
-                    const html = [];
-                    const auditorshtml = [];
-                    auditListIdData.unshift(changesUid);
-                    for (const [index,ids] of auditListIdData.entries()) {
-                        const accountInfo = _.find(accountList, { 'id': ids });
-                        if (index !== 0) {
-                            const user = accountInfo.id + '/%/' + accountInfo.name + '/%/' + accountInfo.role + '/%/' + accountInfo.company;
-                            html.push('<li class="list-group-item" data-auditmsg="' + user + '" data-auditid="'+ ids +'">');
-                            if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== auditListIdData.length)) {
-                                html.push('<a href="javascript:void(0);" class="text-danger pull-right remove_audit_btn">移除</a>');
-                            }
-                            html.push('<span>');
-                            html.push(index + ' ');
-                            html.push('</span> ');
-                            html.push(accountInfo.name + ' ');
-                            html.push('<small class="text-muted">');
-                            html.push(accountInfo.role);
-                            html.push('</small>');
-                            html.push('<p class="m-0 ml-2"><small class="text-muted">' + accountInfo.company + '</small></p>');
-                            html.push('</li>');
+        if (id !== 0) {
+            postData(getUrlPre() + '/audit/add', { auditorId: id }, (datas) => {
+                const html = [];
+                // 如果是重新上报,添加到重新上报列表中
+                const auditorshtml = [];
+                for (const [index,data] of datas.entries()) {
+                    if (index !== 0) {
+                        html.push('<li class="list-group-item d-flex" data-auditid="'+ data[0].uid +'">');
+                        html.push(`<div class="col-auto">${index}</div>`);
+                        html.push('<div class="col">');
+                        for (const auditor of data) {
+                            html.push(`<div class="d-inline-block mx-1" auditorId="${auditor.uid}"><i class="fa fa-user text-muted"></i> ${auditor.name} <small class="text-muted">${auditor.role}</small></div>`);
                         }
-                        // 添加新审批人流程修改
-                        auditorshtml.push('<li class="list-group-item" ' + (index !== 0 ? 'data-auditid="' + accountInfo.id + '"' : '') + '>');
-                        auditorshtml.push('<i class="fa ' + (index+1 === auditListIdData.length ? 'fa-stop-circle' : 'fa-chevron-circle-down') + '"></i> ');
-                        auditorshtml.push(accountInfo.name + ' <small class="text-muted">' + accountInfo.role + '</small>');
-                        if (index === 0) {
-                            auditorshtml.push('<span class="pull-right">原报</span>');
-                        } else if (index+1 === auditListIdData.length) {
-                            auditorshtml.push('<span class="pull-right">终审</span>');
-                        } else {
-                            auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+                        html.push('</div>');
+                        html.push('<div class="col-auto">');
+                        // todo 添加会签或签时
+                        if (data[0].audit_type !== auditType.key.common) {
+                            html.push(`<span class="badge badge-pill badge-${auditType.info[data[0].audit_type].class} badge-bg-small"><small>${auditType.info[data[0].audit_type].long}</small></span>`);
                         }
-                        auditorshtml.push('</li>');
+                        if (shenpi_status === shenpiConst.sp_status.sqspr || (shenpi_status === shenpiConst.sp_status.gdzs && index+1 !== datas.length)) {
+                            html.push('<a href="javascript: void(0)" class="text-danger pull-right">移除</a>');
+                        }
+                        html.push('</div>');
+                        html.push('</li>');
                     }
-                    $('#auditList').html(html.join(''));
-                    $('#shenpi-audit-list').html(auditorshtml.join(''));
-                });
-            } else {
-                toastr.error('审批流程中已存在该用户!');
-            }
+                    auditorshtml.push(`<li class="list-group-item d-flex justify-content-between align-items-center" data-auditid="${index !== 0 ? data[0].uid : ''}">`);
+                    auditorshtml.push('<span class="mr-1"><i class="fa ' + (index === 0 ? 'fa-play-circle fa-rotate-90' : index+1 === datas.length ? 'fa-stop-circle' : 'fa-chevron-circle-down') + '"></i></span>');
+                    auditorshtml.push('<span class="text-muted">');
+                    for (const auditor of data) {
+                        auditorshtml.push(`<small class="d-inline-block text-dark mx-1" title="${auditor.role}" data-auditorId="${auditor.uid}">${auditor.name}</small>`);
+                    }
+                    auditorshtml.push('</span>');
+                    auditorshtml.push('<div class="d-flex ml-auto">');
+                    if (data[0].audit_type !== auditType.key.common) {
+                        auditorshtml.push(`<span class="badge badge-pill badge-${auditType.info[data[0].audit_type].class} p-1"><small>${auditType.info[data[0].audit_type].short}</small></span>`);
+                    }
+                    if (index === 0) {
+                        auditorshtml.push('<span class="badge badge-light badge-pill ml-auto"><small>原报</small></span>');
+                    } else if (index+1 === datas.length) {
+                        auditorshtml.push('<span class="badge badge-light badge-pill"><small>终审</small></span>');
+                    } else {
+                        auditorshtml.push('<span class="badge badge-light badge-pill"><small>'+ transFormToChinese(index) +'审</small></span>');
+                    }
+                    auditorshtml.push('</div>');
+                    auditorshtml.push('</li>');
+                }
+                $('#auditList').html(html.join(''));
+                $('#auditors-list').html(auditorshtml.join(''));
+            });
         }
     });
 
     // 移除审批流程的审批人
-    $('body').on('click', '.remove_audit_btn', function () {
+    $('body').on('click', '#auditList li a', function () {
         const uid = $(this).parents('li').attr('data-auditid');
-        const li = $(this).parent();
+        const li = $(this).parents('li');
         const data = {
             auditorId: uid,
         };
@@ -151,24 +147,24 @@ $(document).ready(function () {
             li.remove();
             let index = 1;
             $('#auditList li').each(function () {
-                $(this).children('span').text(index);
+                $(this).children('.col-auto').eq(0).text(index);
                 index++;
             });
-            if (index === 1) {
-                $('#account_list').val(0);
-            }
+            // if (index === 1) {
+            //     $('#account_list').val(0);
+            // }
 
             // 重新上报时。移除审批流程
             // 令最后一个图标转换
-            $('#shenpi-audit-list li[data-auditid="' + uid + '"]').remove();
-            if ($('#shenpi-audit-list li').length !== 0 && !$('#shenpi-audit-list li i').hasClass('fa-stop-circle')) {
-                $('#shenpi-audit-list li').eq($('#shenpi-audit-list li').length-1).children('i')
+            $('#auditors-list li[data-auditid="' + uid + '"]').remove();
+            if ($('#auditors-list li').length !== 0 && !$('#auditors-list li').find('i').hasClass('fa-stop-circle')) {
+                $('#auditors-list li').eq($('#auditors-list li').length-1).find('i')
                     .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
             }
-            for (let i = 0; i < $('#shenpi-audit-list li').length; i++) {
-                $('#shenpi-audit-list li').eq(i).find('.pull-right').text(i === 0 ? '原报' : (i+1 === $('#shenpi-audit-list li').length ? '终' : transFormToChinese(i)) + '审');
+            for (let i = 0; i < $('#auditors-list li').length; i++) {
+                $('#auditors-list li').eq(i).find('.badge-pill').children('small').text(i === 0 ? '原报' : (i+1 === $('#auditors-list li').length ? '终' : transFormToChinese(i)) + '审');
             }
-            $('#shenpi-audit-list li i').eq(0).removeClass('fa-chevron-circle-down').addClass('fa-play-circle');
+            // $('#auditors-list li').eq(0).find('i').removeClass('fa-chevron-circle-down').addClass('fa-play-circle fa-rotate-90');
         });
     });
 

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

@@ -431,12 +431,12 @@ $(document).ready(() => {
             {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.unit_price'},
             {title: '申报变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'camount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.camount'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'ca_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.ca_tp'},
-            {title: '审批变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'amount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.amount', visible: auditStatus === 7},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'a_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.a_tp', visible: auditStatus === 7},
-            {title: '审批变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'spamount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.spamount', visible: [3,4,5,6,8].indexOf(auditStatus) !== -1},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'spa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.spa_tp', visible: [3,4,5,6,8].indexOf(auditStatus) !== -1},
-            {title: '审批变更|数量', colSpan: '2|1', rowSpan: '1|1', hAlign: 2, width: 60, type: 'Number', getValue: '', visible: [1,2,9].indexOf(auditStatus) !== -1},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', hAlign: 2, width: 80, type: 'Number', getValue: '', visible: [1,2,9].indexOf(auditStatus) !== -1},
+            {title: '审批变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'amount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.amount', visible: !readOnly && shenpiPower},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'a_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.a_tp', visible: !readOnly && shenpiPower},
+            {title: '审批变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'spamount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.spamount', visible: !readOnly && !shenpiPower},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'spa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.spa_tp', visible: !readOnly && !shenpiPower},
+            {title: '审批变更|数量', colSpan: '2|1', rowSpan: '1|1', hAlign: 2, width: 60, type: 'Number', getValue: '', visible: readOnly},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', hAlign: 2, width: 80, type: 'Number', getValue: '', visible: readOnly},
         ],
         emptyRows: 0,
         headRows: 2,
@@ -479,11 +479,11 @@ $(document).ready(() => {
         makeBackColor: function () {
             const rowCount = hzSpread.getActiveSheet().getRowCount();
             for (let i = 0; i < rowCount; i++) {
-                if ([3,4,5,6,8].indexOf(auditStatus) !== -1 && hzSpread.getActiveSheet().zh_data[i].camount != hzSpread.getActiveSheet().zh_data[i].spamount) {
+                if (!readOnly && !shenpiPower && hzSpread.getActiveSheet().zh_data[i].camount != hzSpread.getActiveSheet().zh_data[i].spamount) {
                     hzSpread.getActiveSheet().getRange(i, -1, 1, -1).backColor('#ffeeba');
-                } else if (auditStatus === 7 && hzSpread.getActiveSheet().zh_data[i].camount != hzSpread.getActiveSheet().zh_data[i].amount) {
+                } else if (!readOnly && shenpiPower && hzSpread.getActiveSheet().zh_data[i].camount != hzSpread.getActiveSheet().zh_data[i].amount) {
                     hzSpread.getActiveSheet().getRange(i, -1, 1, -1).backColor('#ffeeba');
-                } else if ([1,2,9].indexOf(auditStatus) !== -1 && !(hzSpread.getActiveSheet().zh_data[i].camount === '' || hzSpread.getActiveSheet().zh_data[i].camount === 0 || hzSpread.getActiveSheet().zh_data[i].camount === null)) {
+                } else if (readOnly && !(hzSpread.getActiveSheet().zh_data[i].camount === '' || hzSpread.getActiveSheet().zh_data[i].camount === 0 || hzSpread.getActiveSheet().zh_data[i].camount === null)) {
                     hzSpread.getActiveSheet().getRange(i, -1, 1, -1).backColor('#ffeeba');
                 }
             }
@@ -706,7 +706,7 @@ function getAllList(currPageNum = 1) {
         <td>${moment(att.in_time * 1000).format('YYYY-MM-DD')}<br>${bytesToSize(att.filesize)}</td>
         <td>
             <a href="/change/download/file/${att.id}" class="mr-2" title="下载"><span class="fa fa-download text-primary"></span></a>`
-        html += (att.uid === accountId && (auditStatus === 4 ? Boolean(att.extra_upload) : true)) ?
+        html += (att.uid === accountId && (changeStatus === auditConst.status.checked ? Boolean(att.extra_upload) : true)) ?
             `<a href="javascript:void(0)" class="mr-2 delete-file" data-attid="${att.id}" title="删除附件"><span class="fa fa-trash text-danger"></span></a>` : '';
         html += `</td>`;
     }

+ 4 - 15
app/public/js/change_information_approval.js

@@ -62,12 +62,12 @@ $(document).ready(() => {
         }
     };
     for (const aid of aidList) {
-        const userinfo = _.find(auditList2, { 'uid': aid });
+        // const userinfo = _.find(auditList2, { 'uid': aid });
         const newColcount = {
-            title: userinfo.name + ' 审批|数量',
+            title: (auditors2[aid - 1] && auditors2[aid - 1].length > 1 ? (aid + '审') : auditors2[aid - 1][0].name) + ' 审批|数量',
             colSpan: '2|1', rowSpan: '1|1',
             field: 'audit_amount_' + aid,
-            hAlign: 2, width: 60, type: 'Number', readOnly: aid !== parseInt(accountId) ? true : 'readOnly.isSettle' ,
+            hAlign: 2, width: 60, type: 'Number', readOnly: _.findIndex(auditors2[aid - 1], { uid: parseInt(accountId) }) === -1 ? true : 'readOnly.isSettle' ,
         };
         const newColTp = {
             title: '|金额',
@@ -414,17 +414,6 @@ $(document).ready(() => {
                     returnflag = false;
                 });
             }
-            // 判断并提交变更清单表格数据到表单中
-            const clist = [];
-            for(const [i,cl] of changeList.entries()) {
-                // if (cl['audit_amount_' + accountId] === null || cl['audit_amount_' + accountId] === '') {
-                //     toastr.error('清单第' + (i+1) + '行审批变更数量不能为空');
-                //     returnflag = false;
-                // } else {
-                clist.push(cl.id + '_' + cl['audit_amount_' + accountId]);
-                // }
-            }
-            $('#change-list-approval').val(clist.join(','));
 
             if(returnflag) {
                 $('input[name="w_code"]').val($.trim($('#w_code').val()));
@@ -443,7 +432,7 @@ $(document).ready(() => {
             if (type === undefined) {
                 // toastr.error('请选择退回类型!');
                 if (!$('#warning-text').length) {
-                    $('#change-back-content').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+                    $('#change-back-content').append('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
                 }
                 returnflag = false;
             }

+ 8 - 4
app/public/js/change_information_show.js

@@ -52,9 +52,9 @@ $(document).ready(() => {
         }
     };
     for (const aid of aidList) {
-        const userinfo = _.find(auditList2, { 'uid': aid });
+        // const userinfo = _.find(auditList2, { 'uid': aid });
         const newColcount = {
-            title: userinfo.name + ' 审批|数量',
+            title: (auditors2[aid - 1] && auditors2[aid - 1].length > 1 ? (aid + '审') : auditors2[aid - 1][0].name) + ' 审批|数量',
             colSpan: '2|1', rowSpan: '1|1',
             field: 'audit_amount_' + aid,
             hAlign: 2, width: 60, type: 'Number',
@@ -98,11 +98,15 @@ $(document).ready(() => {
                 return ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.samount, findDecimal(data.unit))), totalPriceUnit);
             },
             changed_amount: function (data) {
-                return ZhCalc.add(ZhCalc.round(data.oamount, findDecimal(data.unit)), ZhCalc.round(data.changed_amount, findDecimal(data.unit)));
+                console.log(data.checked_amount);
+                // return ZhCalc.round(ZhCalc.add(data.oamount, data.spamount), findDecimal(data.unit));
+                return ZhCalc.round(ZhCalc.add(data.oamount, data.checked_amount), findDecimal(data.unit));
             },
             changed_tp: function (data) {
+                // return ZhCalc.add(ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.oamount, findDecimal(data.unit))), totalPriceUnit),
+                //     ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.spamount, findDecimal(data.unit))), totalPriceUnit));
                 return ZhCalc.add(ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.oamount, findDecimal(data.unit))), totalPriceUnit),
-                    ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.changed_amount, findDecimal(data.unit))), totalPriceUnit));
+                    ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.checked_amount, findDecimal(data.unit))), totalPriceUnit));
             },
         },
     };

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

@@ -28,6 +28,7 @@ const ledgerCheckType = {
         ]
     },
     minus_cb: { value: 12, text: '负变更清单漏计', url: window.location.pathname + '/stageCheck?type=minus_cb' },
+    change_over: { value: 13, text: '变更令超计', url: window.location.pathname + '/stageCheck?type=change_over'},
 };
 const ledgerCheckUtil = {
     checkSibling: function (ledgerTree, ledgerPos, decimal, option) {
@@ -344,14 +345,14 @@ const ledgerCheck2 = async function (setting) {
             }
         } else if (checkInfo.url) {
             const errors = await postDataAsync(checkInfo.url, {}, false);
-            if (errors && errors.minus_cb) {
-                errors.minus_cb.forEach(mcb => {
+            if (errors && errors[prop]) {
+                errors[prop].forEach(mcb => {
                     checkData.warning_data.push({
-                        type: checkInfo.value, code: mcb.memo, b_code: mcb.b_code, name: mcb.name,
+                        type: checkInfo.value, code: mcb.memo, b_code: mcb.b_code, name: mcb.name, lid: mcb.lid
                     });
                 });
             }
-            progressData.push({key: prop, caption: checkInfo.text, error: errors && errors.minus_cb ? errors.minus_cb.length : 0});
+            progressData.push({key: prop, caption: checkInfo.text, error: errors && errors[prop] ? errors[prop].length : 0});
         } else {
             const errors = ledgerCheckUtil[checkInfo.fun](ledger, ledgerPos, decimal, checkOption[prop]) || [];
             assignWarningData(errors, checkInfo.value, checkData.warning_data);

+ 18 - 3
app/public/js/profile_cert.js

@@ -42,12 +42,17 @@ $(document).ready(function() {
                                     if (oldVal === '') {
                                         res.clear();
                                     } else {
+                                        const showDate = [];
+                                        for (const v of oldVal.split(' ~ ')) {
+                                            showDate.push(new Date(v));
+                                        }
                                         res.selectDate(new Date(oldVal));
                                     }
                                     return;
                                 }
                             }
-                        } else if(val !== oldVal) {
+                        }
+                        if(val !== oldVal) {
                             const data = {
                                 id: res.$el.parents('.one-cert').data('cid'),
                                 jxid: res.$el.parents('.one-jx').data('jxid'),
@@ -133,7 +138,11 @@ $(document).ready(function() {
         const defaultValue = $(this).val(); // 获取当前元素的 value 属性作为默认值
         if (defaultValue) {
             // 初始化日期选择器,并设置默认值
-            $(this).datepicker().data('datepicker').selectDate(new Date(defaultValue));
+            const showDate = [];
+            for (const v of defaultValue.split(' ~ ')) {
+                showDate.push(new Date(v));
+            }
+            $(this).datepicker().data('datepicker').selectDate(showDate);
         }
     });
     $('body .jx-date').datepicker({
@@ -145,6 +154,7 @@ $(document).ready(function() {
                 res.$el.attr('readOnly', false);
                 const val = res.$el.val();
                 const oldVal = res.$el.attr('data-old-date') || '';
+                console.log(val, oldVal);
                 // 日期格式判断
                 if (val !== '') {
                     const valArr = val.split(' ~ ');
@@ -155,12 +165,17 @@ $(document).ready(function() {
                             if (oldVal === '') {
                                 res.clear();
                             } else {
+                                const showDate = [];
+                                for (const v of oldVal.split(' ~ ')) {
+                                    showDate.push(new Date(v));
+                                }
                                 res.selectDate(new Date(oldVal));
                             }
                             return;
                         }
                     }
-                } else if(val !== oldVal) {
+                }
+                if(val !== oldVal) {
                     const data = {
                         id: res.$el.parents('.one-cert').data('cid'),
                         jxid: res.$el.parents('.one-jx').data('jxid'),

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

@@ -2022,7 +2022,8 @@ $(document).ready(() => {
                         if (posSheet.zh_data) {
                             const selection = posSheet.getSelections();
                             let settleFinish = false;
-                            for (let i = row; i < row + rowCount; i++) {
+                            const rowCount = posSheet.zh_data.count;
+                            for (let i = 0; i < rowCount; i++) {
                                 if (!posSheet.zh_data[i]) continue;
                                 settleFinish = settleFinish || posSheet.zh_data[i].settle_status === settleStatus.finish;
                             }

+ 6 - 3
app/public/js/schedule_stage_tp.js

@@ -104,7 +104,10 @@ $(function () {
                 fullPath: 'full_path',
                 calcFields: calcList,
             };
-            baseLedgerTreeSetting.updateFields = ['year_contract_qty', 'year_gather_tp', 'contract_qty', 'end_gather_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'final_contract_tp', 'final_qc_tp', 'final_pc_tp', 'postil', 'used', 'contract_expr'];
+            baseLedgerTreeSetting.updateFields = ['year_contract_qty', 'year_gather_tp', 'contract_qty', 'end_gather_qty',
+                'contract_tp', 'gather_tp', 'qc_qty', 'contract_pc_tp', 'qc_pc_tp', 'qc_tp', 'pc_tp', 'final_contract_tp',
+                'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp',
+                'final_qc_tp', 'final_pc_tp', 'postil', 'used', 'contract_expr'];
             baseLedgerTreeSetting.calcFun = function (node) {
                 if (!node.children || node.children.length === 0) {
                     node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
@@ -115,8 +118,8 @@ $(function () {
                 }
                 node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
                 node.gather_tp = ZhCalc.sum([node.contract_tp, node.qc_tp, node.pc_tp]);
-                node.end_contract_tp = ZhCalc.add(node.pre_contract_tp, node.contract_tp);
-                node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
+                node.end_contract_tp = ZhCalc.sum([node.pre_contract_tp, node.contract_tp, node.contract_pc_tp]);
+                node.end_qc_tp = ZhCalc.sum([node.pre_qc_tp, node.qc_tp, node.qc_pc_tp]);
                 node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
                 node.end_final_tp = ZhCalc.add(node.end_qc_tp, node.total_price);
                 if (!node.children || node.children.length === 0) {

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

@@ -213,8 +213,8 @@ $(document).ready(() => {
             // <li class="list-group-item">
             //     计量进度<a href="#" class="btn btn-primary btn-sm pull-right">设为默认</a>
             // </li>
-            $('.list-group').empty()
-            $('.list-group').append(html)
+            $('#tenderList').empty()
+            $('#tenderList').append(html)
             const item = result.find((i, idx) => idx=== attid)
             $('#nav_tender').attr('href', item.path)
         });

+ 19 - 2
app/public/js/shares/cs_tools.js

@@ -84,6 +84,7 @@ const showSelectTab = function(select, spread, afterShow) {
                                 case 's2b_lost_gxby': return '遗漏计量(工序报验)';
                                 case 's2b_lost_dagl': return '遗漏计量(档案管理)';
                                 case 'minus_cb': return '负变更清单漏计';
+                                case 'change_over': return '变更令超计';
                                 case 'settle': return '结算清单';
                                 default: return '';
                             }
@@ -146,7 +147,15 @@ const showSelectTab = function(select, spread, afterShow) {
                 if (!sourceTree) return;
 
                 for (const d of data) {
-                    d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
+                    if (d.ledger_id) {
+                        d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
+                    } else if (d.lid) {
+                        const nodeIndex = sourceTree.nodes.findIndex(x => { return x.id === d.lid });
+                        if (nodeIndex >= 0) {
+                            d.serialNo = nodeIndex + 1;
+                            d.ledger_id = sourceTree.nodes[nodeIndex].ledger_id;
+                        }
+                    }
                 }
                 data.sort(function (a, b) {
                     return a.serialNo ? (b.serialNo ? a.serialNo - b.serialNo : 1) : 1;
@@ -327,7 +336,15 @@ const showSelectTab = function(select, spread, afterShow) {
                 if (!sourceTree) return;
 
                 for (const d of data.warning_data) {
-                    d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
+                    if (d.ledger_id) {
+                        d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
+                    } else if (d.lid) {
+                        const nodeIndex = sourceTree.nodes.findIndex(x => { return x.id === d.lid });
+                        if (nodeIndex >= 0) {
+                            d.serialNo = nodeIndex + 1;
+                            d.ledger_id = sourceTree.nodes[nodeIndex].ledger_id;
+                        }
+                    }
                 }
 
                 $('#' + setting.id + '-time').html('检查时间:' + moment(data.check_time).format('YYYY-MM-DD HH:mm:ss'));

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

@@ -249,7 +249,7 @@ $(document).ready(function () {
         },
         getAuditTypeHtml: function(code, type) {
             const html = [];
-            const hide = code !== 'stage' ? 'style="display: none;"' : '';
+            const hide = ['stage', 'change'].indexOf(code) === -1 ? 'style="display: none;"' : '';
             html.push(`<span class="d-inline-block"><select class="form-control form-control-sm" ${hide} data-type="${type}">`);
             for (const t of auditType.types) {
                 html.push(`<option value="${t.value}" ${t.value === type ? 'selected' : ''}>${t.name}</option>`);
@@ -641,7 +641,7 @@ $(document).ready(function () {
     $('body').on('click', '.set-otherShenpi', function () {
         let canSetOther = true;
         const this_code = $(this).data('code');
-        if (this_code === 'stage') {
+        if (['stage', 'change'].indexOf(this_code) !== -1) {
             const select = $(this).siblings('.lc-show').find('select');
             select.each((i, s) => {
                 if (s.value !== '1') canSetOther = false;

+ 1 - 1
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -2413,7 +2413,7 @@ const SpreadJsObj = {
          */
         getUnitCellType: function (comboEdit, items = ['m', 'km', 'm2', 'm3', 'dm3', 'kg', 't', 'm3·km',
             '总额', '月' ,'项', '处' ,'个', '根', '棵', '块', '台', '系统', '延米', '每一试桩',
-            '桥长米', '公路公里', '株', '组', '座', '元', '工日', '套', '台班', '艘班', '亩', '片',
+            '桥长米', '公路公里', '株', '组', '座', '元', '工日', '套', '台班', '辆', '艘班', '亩', '片',
             'm/处', 'm/道', 'm/座', 'm2/m', 'm3/m', 'm3/处', '根/米', 'm3/m2']) {
             let combo = this.getActiveComboCellType();
             combo.editable(comboEdit);

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

@@ -242,6 +242,7 @@ $(document).ready(() => {
         over: { enable: 1, isTz: checkTzMeasureType(), },
         limit3f: { enable: 1, checkType: [], status: thirdParty, },
         minus_cb: { enable: hintMinusCb },
+        // change_over: { enable: 1 },
     };
     if (tender.s2b_gxby_check) checkOption.limit3f.checkType.push('gxby');
     if (tender.s2b_dagl_check) checkOption.limit3f.checkType.push('dagl');

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

@@ -318,7 +318,7 @@ $(document).ready(function () {
                             makeSelectAudit(auditor.aid+'_add', auditor.aid, 'add'),'</div>', '</span>');
                         if (auditor.audit_type !== auditType.key.common) {
                             html.push('<span class="dropdown mr-2">',
-                                '<a href="javascript: void(0)" class="add-audit" id="<%- auditor.aid %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">平级</a>',
+                                `<a href="javascript: void(0)" class="add-audit" id="${auditor.aid}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">平级</a>`,
                                 makeSelectAudit(auditor.aid+'_add-sibling', auditor.aid, 'add-sibling'),'</div>', '</span>');
                         }
                     }
@@ -401,7 +401,7 @@ $(document).ready(function () {
             }
             auditorshtml.push('<span class="text-muted">');
             for (const u of data) {
-                auditorshtml.push(`<small class="d-inline-block text-dark mx-1" title="${u.role}" data-auditorId="<%- u.aid %>">${u.name}</small>`);
+                auditorshtml.push(`<small class="d-inline-block text-dark mx-1" title="${u.role}" data-auditorId="${u.aid}">${u.name}</small>`);
             }
             auditorshtml.push('</span>');
             auditorshtml.push('<div class="d-flex ml-auto">');

+ 6 - 6
app/router.js

@@ -517,6 +517,7 @@ module.exports = app => {
     // 变更管理
     app.get('/tender/:id/change', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.index');
     app.get('/tender/:id/change/status/:status', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.status');
+    app.post('/tender/:id/change/auditors', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.changeAuditors');
     app.post('/tender/:id/change/newCode', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.newCode');
     app.post('/tender/:id/change/add', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'changeController.add');
     app.post('/tender/:id/change/defaultBills', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.defaultBills');
@@ -531,9 +532,9 @@ module.exports = app => {
     app.post('/tender/:id/change/save', sessionAuth, tenderCheck, uncheckTenderCheck, changeAuditCheck, 'changeController.save');
 
     app.post('/tender/:id/change/approval', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'changeController.approval');
-    app.post('/tender/:id/change/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'changeController.checkAgain');
-    app.post('/tender/:id/change/check/revise', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'changeController.checkRevise');
-    app.post('/tender/:id/change/cancel/revise', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'changeController.cancelRevise');
+    app.post('/tender/:id/change/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, changeCheck, changeAuditCheck, 'changeController.checkAgain');
+    app.post('/tender/:id/change/check/revise', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, changeCheck, changeAuditCheck, 'changeController.checkRevise');
+    app.post('/tender/:id/change/cancel/revise', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, changeCheck, changeAuditCheck, 'changeController.cancelRevise');
 
     app.post('/tender/:id/change/:cid/check/codeRepeat', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.checkCodeRepeat');
     app.post('/tender/:id/change/:cid/info/copy', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.copyChange');
@@ -541,7 +542,6 @@ module.exports = app => {
     app.post('/change/update/company', sessionAuth, 'changeController.updateCompany');
 
     // 变更令 - 新版本
-    app.get('/tender/:id/change/:cid/info', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, changeAuditCheck, 'changeController.information');// 针对旧数据wap端跳转web问题
     app.get('/tender/:id/change/:cid/information', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, changeAuditCheck, 'changeController.information');
     app.post('/tender/:id/change/:cid/information/save', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, 'changeController.saveListsData');
     app.post('/tender/:id/change/:cid/information/audit/start', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, changeAuditCheck, 'changeController.startAudit');
@@ -709,7 +709,7 @@ module.exports = app => {
     app.get('/wap/list', sessionAuth, 'wapController.list');
     app.get('/wap/tender/:id', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.tender');
     app.get('/wap/tender/:id/stage/:order', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.stage');
-    app.get('/wap/tender/:id/change/:cid/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.change');
+    app.get('/wap/tender/:id/change/:cid/info', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, changeAuditCheck, 'wapController.change');
     app.get('/wap/tender/:id/change/plan/:cpid/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.changePlan');
     app.post('/wap/tender/:id/change/approval', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'wapController.changeApproval');
     app.get('/wap/tender/:id/revise/:rid/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.revise');
@@ -717,7 +717,7 @@ module.exports = app => {
     app.get('/wap/tender/:id/advance/:order/detail', sessionAuth, tenderCheck, advanceCheck, 'wapController.advanceDetail');
     // 针对企业微信访问判断去掉wap就能直达web端
     app.get('/wap/tender/:id/measure/stage/:order', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.stage');
-    app.get('/wap/tender/:id/change/:cid/information', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.change');
+    app.get('/wap/tender/:id/change/:cid/information', sessionAuth, tenderCheck, uncheckTenderCheck, changeCheck, changeAuditCheck, 'wapController.change');
     app.get('/wap/tender/:id/change/plan/:cpid/information', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.changePlan');
 
     // 微信

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 481 - 476
app/service/change.js


+ 1 - 0
app/service/change_apply_audit.js

@@ -97,6 +97,7 @@ module.exports = app => {
                 case auditConst.status.checking :
                 case auditConst.status.checked :
                 case auditConst.status.revise :
+                case auditConst.status.cancelRevise :
                     sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`caid`, la.`aid`, la.`order` ' +
                         '  FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id` ' +
                         '  WHERE la.`caid` = ? and la.`status` = ? ' +

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 469 - 265
app/service/change_audit.js


+ 1 - 0
app/service/change_plan_audit.js

@@ -97,6 +97,7 @@ module.exports = app => {
                 case auditConst.status.checking :
                 case auditConst.status.checked :
                 case auditConst.status.revise :
+                case auditConst.status.cancelRevise :
                     sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`cpid`, la.`aid`, la.`order`, la.`status` ' +
                         '  FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id` ' +
                         '  WHERE la.`cpid` = ? and la.`status` = ? ' +

+ 1 - 1
app/service/project_col_set.js

@@ -38,7 +38,7 @@ module.exports = app => {
         }
 
         async initProjectColSet(id) {
-            const data = ProjectSetting.defaultColSet;
+            const data = JSON.parse(JSON.stringify(ProjectSetting.defaultColSet));
             JsonFields.forEach(jf => { if(data[jf]) data[jf] = JSON.stringify(data[jf]); });
             data.id = id;
             await this.db.insert(this.tableName, data);

+ 2 - 2
app/service/project_spread.js

@@ -86,8 +86,8 @@ module.exports = app => {
         }
 
         generateRelaSpread(colSetType, colSet) {
-            const baseSetCol = colSetType.indexOf('stage') > 0 ? SpreadConst.BaseSetCol.Stage : SpreadConst.BaseSetCol.Ledger;
-            const baseSpreadColSetting = colSetType.indexOf('stage') > 0 ? SpreadConst.BaseSpreadColSetting.Stage : SpreadConst.BaseSpreadColSetting.Ledger;
+            const baseSetCol = SpreadConst.BaseSetCol[colSetType];
+            const baseSpreadColSetting = SpreadConst.BaseSpreadColSetting[colSetType];
             const billsSpread = this.generateSpreadSetting(colSet, SpreadConst.EmptySpreadSetting[colSetType].bills, baseSetCol, baseSpreadColSetting.bills);
             const posSpread = this.generateSpreadSetting(colSet, SpreadConst.EmptySpreadSetting[colSetType].pos, baseSetCol, baseSpreadColSetting.pos, 'pos');
             const spreadSpec = SpreadConst.SpreadSpec[colSetType];

+ 1 - 1
app/service/revise_audit.js

@@ -463,7 +463,7 @@ module.exports = app => {
                         });
                         await this.ctx.service.tenderTag.saveTenderTag(revise.tid, {revise_time: new Date()}, transaction);
                         // 最新一期跟台账相关的缓存数据应过期
-                        const lastStage = await this.ctx.service.stage.getLastestStage(revise.tid, true);
+                        const lastStage = await this.ctx.service.stage.getFlowLatestStage(revise.tid, true);
                         const cacheTime = new Date();
                         if (lastStage) {
                             await transaction.update(this.ctx.service.stage.tableName, {

+ 2 - 2
app/service/shenpi_audit.js

@@ -358,9 +358,9 @@ module.exports = app => {
                     tid: tenderId,
                     sp_type,
                     sp_status,
-                    audit_id: a.aid,
+                    audit_id: a.aid || a.uid,
                     audit_order: a.audit_order,
-                    audit_type: a.audit_type
+                    audit_type: a.audit_type,
                 });
             }
             await transaction.insert(this.tableName, insertDatas);

+ 36 - 4
app/service/stage.js

@@ -305,6 +305,35 @@ module.exports = app => {
         }
 
         /**
+         * 获取 最新一期 期计量
+         * @param tenderId
+         * @param includeUnCheck
+         * @return {Promise<*>}
+         */
+        async getFlowLatestStage(tenderId, includeUnCheck = false) {
+            const stages = await this.getAllDataByCondition({ where: {tid: tenderId}, orders: [['order', 'desc']] });
+            const flowStages = [];
+            for (const s of stages) {
+                if (s.status !== auditConst.stage.status.checked) flowStages.push(s);
+            }
+            let stage;
+            if (flowStages.length === 0) {
+                stage = stages[0];
+            } else {
+                const firstFlowStage = flowStages[flowStages.length - 1];
+                if (includeUnCheck) {
+                    stage = firstFlowStage;
+                } else {
+                    stage = firstFlowStage.status === auditConst.stage.status.uncheck ? stages[flowStages.length] : firstFlowStage;
+                }
+            }
+            return stage;
+        }
+        async getUnCompleteStages(tenderId) {
+            return this.db.query(`SELECT * From ${this.tableName} WHERE tid = ? and status <> ?`, [tenderId, auditConst.stage.status.checked]);
+        }
+
+        /**
          * 获取 最新一期 审批完成的 期计量
          * @param tenderId
          * @return {Promise<*>}
@@ -892,14 +921,17 @@ module.exports = app => {
         }
 
         async getStageByDataCollect(tenderId, stage_tp) {
-            const stages = await this.db.select(this.tableName, {
+            const allStages = await this.db.select(this.tableName, {
                 columns: ['id', 'user_id', 'times', 'status', 's_time', 'contract_tp', 'qc_tp', 'pc_tp', 'pre_contract_tp', 'pre_qc_tp', 'tp_history'],
                 where: { tid: tenderId },
                 orders: [['order', 'desc']],
             });
-            if (stages.length > 0 && stages[0].status === auditConst.stage.status.uncheck) {
-                stages.splice(0, 1);
-            }
+            const stages = this._.filter(allStages, function(s) {
+                return s.status !== auditConst.stage.status.uncheck;
+            });
+            // if (stages.length > 0 && stages[0].status === auditConst.stage.status.uncheck) {
+            //     stages.splice(0, 1);
+            // }
             // 最新一期计量(未审批完成),取上一个人的期详细数据,应实时计算
             const stage = stages[0];
             if (stages.length === 0) return stages;

+ 7 - 1
app/service/stage_audit.js

@@ -343,7 +343,13 @@ module.exports = app => {
                     sf_tp: sfPay.tp,
                 };
                 this.ctx.stage.tp_history.push({ times: this.ctx.stage.curTimes, order: 0, ...stageTp });
-                await this.ctx.service.tenderCache.updateStageCache4Start(transaction, this.ctx.stage, auditConst.status.checking, audits, ledgerTp, stageTp);
+                const completeStageTp = {
+                    ...stageTp,
+                    pre_contract_tp: this.ctx.stage.pre_contract_tp || 0, pre_qc_tp: this.ctx.stage.pre_qc_tp || 0,
+                    pre_positive_qc_tp: this.ctx.stage.pre_positive_qc_tp || 0, pre_negative_qc_tp: this.ctx.stage.pre_negative_qc_tp || 0,
+                    pre_yf_tp: this.ctx.stage.pre_yf_tp || 0, pre_sf_tp: this.ctx.stage.pre_sf_tp || 0,
+                };
+                await this.ctx.service.tenderCache.updateStageCache4Start(transaction, this.ctx.stage, auditConst.status.checking, audits, ledgerTp, completeStageTp);
                 await transaction.update(this.ctx.service.stage.tableName, {
                     id: stageId,
                     status: auditConst.status.checking,

+ 22 - 1
app/service/stage_change.js

@@ -559,7 +559,7 @@ module.exports = app => {
         }
 
         async getFinalUsedData(tid, cid) {
-            const stage = await this.ctx.service.stage.getLastestStage(tid, true);
+            const stage = await this.ctx.service.stage.getFlowLatestStage(tid, true);
             if (!stage) { // 防止未创建期时调用
                 return [];
             }
@@ -583,6 +583,27 @@ module.exports = app => {
             }
         }
 
+        async getAllFinalUsedData(tid, cid) {
+            const result = [];
+            const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: tid }, orders: [['order', 'desc']] });
+            for (const stage of stages) {
+                if (stage.status === audit.stage.status.checked) {
+                    const sql = 'SELECT scf.* ' +
+                        '  FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' +
+                        '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' +
+                        this.ctx.helper.whereSql({ tid, cid }, 'scf') + ' And s.order = ?';
+                    const pre = await this.db.query(sql, [stage.order]);
+                    result.push(...pre);
+                } else {
+                    const sql = 'SELECT * FROM ' + this.tableName + this.ctx.helper.whereSql({ sid: stage.id, cid });
+                    const curAll = await this.db.query(sql);
+                    const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
+                    result.push(...cur);
+                }
+            }
+            return result;
+        }
+
         /**
          * 获取 变更令 - 变更清单 当期使用情况
          * @param {Number} sid - 查询期id

+ 33 - 14
app/service/tender_cache.js

@@ -56,11 +56,20 @@ module.exports = app => {
                     : JSON.parse(cache.stage_flow_cur_info || cache.stage_flow_pre_info);
                 tender.pre_flow = cache.stage_flow_pre_info ? JSON.parse(cache.stage_flow_pre_info) : null;
                 tender.stage_tp = JSON.parse(cache.stage_flow_cur_tp || cache.stage_flow_pre_tp);
-                tender.progress = {
-                    title: `第${cache.stage_count}期`,
-                    status: auditConst.stage.tiStatusString[cache.stage_status],
-                    status_class: auditConst.stage.tiStatusStringClass[cache.stage_status],
-                };
+                try {
+                    tender.progress = {
+                        title: `第${tender.cur_flow.order === undefined ? tender.cur_flow[0].order : tender.cur_flow.order}期`,
+                        status: auditConst.stage.tiStatusString[cache.stage_status],
+                        status_class: auditConst.stage.tiStatusStringClass[cache.stage_status],
+                    };
+                } catch (err) {
+                    console.log(tender.id);
+                    tender.progress = {
+                        title: `第${tender.stage_count}期`,
+                        status: auditConst.stage.tiStatusString[cache.stage_status],
+                        status_class: auditConst.stage.tiStatusStringClass[cache.stage_status],
+                    };
+                }
             } else {
                 tender.stage_status = auditConst.stage.status.checked;
                 tender.stage_count = tender.stage_complete_count;
@@ -69,11 +78,20 @@ module.exports = app => {
                     ? JSON.parse(cache.stage_flow_pre_info) : JSON.parse(cache.stage_flow_cur_info || cache.stage_flow_pre_info);
                 tender.pre_flow = cache.stage_flow_pre_info ? JSON.parse(cache.stage_flow_pre_info) : null;
                 tender.stage_tp = cache.stage_flow_pre_tp ? JSON.parse(cache.stage_flow_pre_tp) : {};
-                tender.progress = {
-                    title: `第${cache.stage_complete_count}期`,
-                    status: auditConst.stage.tiStatusString[auditConst.stage.status.checked],
-                    status_class: auditConst.stage.tiStatusStringClass[auditConst.stage.status.checked],
-                };
+                try {
+                    tender.progress = {
+                        title: `第${tender.pre_flow.order === undefined ? tender.pre_flow[0].order : tender.pre_flow.order}期`,
+                        status: auditConst.stage.tiStatusString[auditConst.stage.status.checked],
+                        status_class: auditConst.stage.tiStatusStringClass[auditConst.stage.status.checked],
+                    };
+                } catch(err) {
+                    console.log(tender.id);
+                    tender.progress = {
+                        title: `第${tender.stage_count}期`,
+                        status: auditConst.stage.tiStatusString[auditConst.stage.status.checked],
+                        status_class: auditConst.stage.tiStatusStringClass[auditConst.stage.status.checked],
+                    };
+                }
             }
             tender.contract_price = cache.contract_price;
             tender.advance_tp = cache.advance_tp;
@@ -390,10 +408,11 @@ module.exports = app => {
 
         async _refreshStageRela(tender, data) {
             if (tender.ledger_status === auditConst.ledger.status.checked) {
-                const lastStage = await this.ctx.service.stage.getLastestStage(tender.id, true);
-                if (!lastStage) return;
+                const endLastStage = await this.ctx.service.stage.getLastestStage(tender.id, true);
+                const lastStage = await this.ctx.service.stage.getFlowLatestStage(tender.id, true);
+                if (!lastStage || !endLastStage) return;
 
-                data.stage_count = lastStage.order;
+                data.stage_count = endLastStage.order;
                 data.stage_complete_count = lastStage.status === auditConst.stage.status.checked ? lastStage.order : lastStage.order - 1;
                 data.stage_status = lastStage.status;
                 const tp = {
@@ -411,7 +430,7 @@ module.exports = app => {
                         const preAuditorIds = preAuditors.map(x => { return x.aid; });
                         data.stage_flow_pre_uid = preAuditorIds.join(',');
                         data.stage_flow_pre_info = preAuditors.length > 0 ? JSON.stringify(preAuditors.map(preAuditor => { return {
-                            order: preAuditor.order, audit_type: preAuditor.audit_type, audit_order: preAuditor.order, status: preAuditor.status, time: preAuditor.end_time,
+                            order: preStage.order, audit_type: preAuditor.audit_type, audit_order: preAuditor.order, status: preAuditor.status, time: preAuditor.end_time,
                             name: preAuditor.name, company: preAuditor.company, role: preAuditor.role, mobile: preAuditor.mobile, telephone: preAuditor.telephone,
                         }})) : '';
                         data.stage_flow_pre_tp = JSON.stringify({

+ 63 - 60
app/service/tender_info.js

@@ -249,78 +249,81 @@ module.exports = app => {
         }
 
         async _reCalcStageBills(tenderId, newDecimal, oldDecimal) {
-            let updateStageBills = [], insertStageBills = [];
-            const stage = await this.ctx.service.stage.getLastestStage(tenderId, true);
-            if (!stage || stage.status === auditConst.stage.status.checking ||
-                stage.status === auditConst.stage.status.checked || newDecimal.tp === oldDecimal.tp)
-                return [updateStageBills, insertStageBills];
-
-            const stageBills = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id);
-            const bills = await this.ctx.service.ledger.getAllDataByCondition({
-                columns: ['id', 'unit_price'],
-                where: { tender_id: tenderId, is_leaf: true },
-            });
-            for (const sb of stageBills) {
-                const b = bills.find(x => {return x.id === sb.lid});
-                const contract_tp = this.ctx.helper.mul(b.unit_price, sb.contract_qty, newDecimal.tp);
-                const qc_tp = this.ctx.helper.mul(b.unit_price, sb.qc_qty, newDecimal.tp);
-                if (contract_tp == sb.contract_tp && qc_tp === sb.qc_tp) continue;
-
-                //if (sb.)
-                if (sb.times === stage.times && sb.order === 0) {
-                    updateStageBills.push({
-                        id: sb.id, contract_tp, qc_tp
-                    });
-                } else {
-                    insertStageBills.push({
-                        tid: stage.tid, lid: sb.lid, sid: stage.id, said: this.ctx.session.sessionUser.accountId,
-                        times: stage.times, order: 0,
-                        contract_qty: sb.contract_qty, contract_expr: sb.contract_expr, contract_tp,
-                        qc_qty: sb.qc_qty, qc_tp,
-                        postil: sb.postil,
-                    });
+            const updateStageBills = [], insertStageBills = [];
+            const stages = await this.ctx.service.stage.getUnCompleteStages(tenderId);
+            if (stages.length === 0 || newDecimal.tp === oldDecimal.tp) return [updateStageBills, insertStageBills];
+
+            for (const stage of stages) {
+                const stageBills = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id);
+                const bills = await this.ctx.service.ledger.getAllDataByCondition({
+                    columns: ['id', 'unit_price'],
+                    where: { tender_id: tenderId, is_leaf: true },
+                });
+                for (const sb of stageBills) {
+                    const b = bills.find(x => {return x.id === sb.lid});
+                    const contract_tp = this.ctx.helper.mul(b.unit_price, sb.contract_qty, newDecimal.tp);
+                    const qc_tp = this.ctx.helper.mul(b.unit_price, sb.qc_qty, newDecimal.tp);
+                    if (contract_tp == sb.contract_tp && qc_tp === sb.qc_tp) continue;
+
+                    if (sb.times === stage.times && sb.order === 0) {
+                        updateStageBills.push({
+                            id: sb.id, contract_tp, qc_tp
+                        });
+                    } else {
+                        insertStageBills.push({
+                            tid: stage.tid, lid: sb.lid, sid: stage.id, said: this.ctx.session.sessionUser.accountId,
+                            times: stage.times, order: 0,
+                            contract_qty: sb.contract_qty, contract_expr: sb.contract_expr, contract_tp,
+                            qc_qty: sb.qc_qty, qc_tp,
+                            postil: sb.postil,
+                        });
+                    }
                 }
             }
             return [updateStageBills, insertStageBills];
         }
 
         async _reCalcStageExtra(tenderId, newDecimal, oldDecimal) {
-            let changeSj = [], changeSb = [], changeSo = [];
-            const stage = await this.ctx.service.stage.getLastestStage(tenderId, true);
-            if (!stage) return [changeSj, changeSb, changeSo];
+            const changeSj = [], changeSb = [], changeSo = [];
+            const stages = await this.ctx.service.stage.getUnCompleteStages(tenderId);
+            if (stages.length === 0) return [changeSj, changeSb, changeSo];
 
             const upDecimal = newDecimal.up, tpDecimal = newDecimal.extra ? newDecimal.extraTp : newDecimal.tp;
             const calcUp = upDecimal < oldDecimal.up,
                 calcTp = tpDecimal < (oldDecimal.extra ? oldDecimal.extraTp : oldDecimal.tp);
 
-            if (calcUp || calcTp) {
-                const stageJgcl = await this.ctx.service.stageJgcl.getAllDataByCondition({
-                    columns: ['id', 'unit_price', 'arrive_qty', 'deduct_qty'],
-                    where: { sid: stage.id }
-                });
-                for (const sj of stageJgcl) {
-                    const cj = { id: sj.id };
-                    cj.unit_price = calcUp ? this.ctx.helper.round(sj.unit_price, upDecimal) : sj.unit_price;
-                    cj.arrive_tp = this.ctx.helper.mul(sj.arrive_qty, sj.unit_price, tpDecimal);
-                    cj.deduct_tp = this.ctx.helper.mul(sj.deduct_qty, sj.unit_price, tpDecimal);
-                    changeSj.push(cj);
-                }
-            }
-            if (calcTp) {
-                changeSb = await this.ctx.service.stageBonus.getAllDataByCondition({
-                    columns: ['id', 'tp'],
-                    where: { sid: stage.id }
-                });
-                for (const cb of changeSb) {
-                    cb.tp = this.ctx.helper.round(cb.tp, tpDecimal);
+            for (const stage of stages) {
+                if (calcUp || calcTp) {
+                    const stageJgcl = await this.ctx.service.stageJgcl.getAllDataByCondition({
+                        columns: ['id', 'unit_price', 'arrive_qty', 'deduct_qty'],
+                        where: { sid: stage.id }
+                    });
+                    for (const sj of stageJgcl) {
+                        const cj = { id: sj.id };
+                        cj.unit_price = calcUp ? this.ctx.helper.round(sj.unit_price, upDecimal) : sj.unit_price;
+                        cj.arrive_tp = this.ctx.helper.mul(sj.arrive_qty, sj.unit_price, tpDecimal);
+                        cj.deduct_tp = this.ctx.helper.mul(sj.deduct_qty, sj.unit_price, tpDecimal);
+                        changeSj.push(cj);
+                    }
                 }
-                changeSo = await this.ctx.service.stageOther.getAllDataByCondition({
-                    columns: ['id', 'total_price', 'tp'],
-                    where: { sid: stage.id }
-                });
-                for (const co of changeSo) {
-                    if (stage.order === 1) co.total_price = this.ctx.helper.round(co.total_price, tpDecimal);
-                    co.tp = this.ctx.helper.round(co.tp, tpDecimal);
+                if (calcTp) {
+                    const stageChangeSb = await this.ctx.service.stageBonus.getAllDataByCondition({
+                        columns: ['id', 'tp'],
+                        where: { sid: stage.id }
+                    });
+                    for (const cb of stageChangeSb) {
+                        cb.tp = this.ctx.helper.round(cb.tp, tpDecimal);
+                    }
+                    changeSb.push(...stageChangeSb);
+                    const stageChangeSo = await this.ctx.service.stageOther.getAllDataByCondition({
+                        columns: ['id', 'total_price', 'tp'],
+                        where: { sid: stage.id }
+                    });
+                    for (const co of stageChangeSo) {
+                        if (stage.order === 1) co.total_price = this.ctx.helper.round(co.total_price, tpDecimal);
+                        co.tp = this.ctx.helper.round(co.tp, tpDecimal);
+                    }
+                    changeSo.push(...stageChangeSo);
                 }
             }
             return [changeSj, changeSb, changeSo];

+ 35 - 35
app/view/change/index.ejs

@@ -68,7 +68,7 @@
                     <span class="ml-3">本页小计:<%- page_total %>元</span><span class="ml-3">合计:<%- tp %>元</span>
                 </div>
             </div>
-            <% if (tender.user_id === uid) { %>
+            <% if (tender.user_id === ctx.session.sessionUser.accountId) { %>
             <div class="ml-auto">
                 <a href="#add-bj" data-toggle="modal" data-target="#add-bj" class="btn btn-sm btn-primary pull-right ml-1">新建变更令</a>
                 <a href="#setting" data-toggle="modal" data-target="#setting" class="btn btn-sm btn-outline-primary pull-right ml-1"><i class="fa fa-cog"></i></a>
@@ -83,13 +83,13 @@
             <input id="tenderId" value="<%= tender.id %>" type="hidden">
             <div class="sjs-height-0">
                 <table class="table table-bordered" id="change-table">
-                    <thead>
+                    <thead class="text-center">
                     <tr><th width="3%">序号</th>
                         <th width="18%" id="sort_change">申请编号/变更令号</th><th width="24%">变更工程名称</th>
                         <th width="7%">变更性质</th><% if (ctx.session.sessionProject.page_show.openChangeState) { %><th width="7%">变更令状态</th><% } %>
                         <th width="7%">变更金额</th><th width="7%">正变更金额</th>
                         <th width="7%">负变更金额</th><th width="7%">审批状态</th>
-                        <th width="14%">审批进度</th><th width="4%"></th>
+                        <th width="14%">审批进度</th><th width="4%">操作</th>
                     </tr>
                     </thead>
                     <tbody id="changeList">
@@ -111,40 +111,40 @@
                         <td style="text-align: right"><%= ctx.helper.roundNum(c.total_price, tpUnit) %></td>
                         <td style="text-align: right"><%= ctx.helper.roundNum(c.positive_tp, tpUnit) %></td>
                         <td style="text-align: right"><%= ctx.helper.roundNum(c.negative_tp, tpUnit) %></td>
-                        <% if (c.status === auditConst.status.uncheck && ctx.tender.isTourist) { %>
-                            <td>
-                                上报中
-                            </td>
-                        <% } else if (c.status === auditConst.status.revise && ctx.tender.isTourist) { %>
-                            <td>
-                                修订中
-                            </td>
-                        <% } else if (c.auditStatus) { %>
-                        <td>
-                            <a href="/tender/<%- tender.id %>/change/<%- c.cid %>/information" class="btn <%- auditConst.statusButtonClass[c.status] %> btn-sm">
-                                <%- auditConst.statusButton[c.status] %>
-                            </a>
-                        </td>
-                        <% } else {  %>
-                        <td>
-                            <span class="<%- auditConst.statusClass[c.status] %>"><%- auditConst.statusString[c.status] %></span>
-                        </td>
-                        <% } %>
-                        <% if (c.status === auditConst.status.uncheck) { %>
-                        <td>
-                            待上报
+                        <td class="text-center">
+                            <% if (c.status === auditConst.status.uncheck && c.uid === ctx.session.sessionUser.accountId) { %>
+                                <a href="<%- '/tender/' + ctx.tender.id + '/change/' + c.cid %>/information" class="btn <%- auditConst.statusButtonClass[c.status] %> btn-sm"><%- auditConst.statusButton[c.status] %></a>
+                            <% } else if ((c.status === auditConst.status.checkNo || c.status === auditConst.status.revise) && c.curAuditors && c.uid === ctx.session.sessionUser.accountId) { %>
+                                <a href="<%- '/tender/' + ctx.tender.id + '/change/' + c.cid %>/information" class="btn <%- auditConst.statusButtonClass[c.status] %> btn-sm"><%- auditConst.statusButton[c.status] %></a>
+                            <% } else if (c.status === auditConst.status.checking && c.curAuditors && c.curAuditors.findIndex(x => { return x.uid === ctx.session.sessionUser.accountId; }) >= 0) { %>
+                                <% const curAudit = c.curAuditors.find(x => { return x.uid === ctx.session.sessionUser.accountId; }); %>
+                                <% if (curAudit.status === auditConst.status.checking) { %>
+                                <a href="<%- '/tender/' + ctx.tender.id + '/change/' + c.cid %>/information" class="btn <%- auditConst.statusButtonClass[c.status] %> btn-sm"><%- auditConst.statusButton[c.status] %></a>
+                                <% } else { %>
+                                <span class="<%- auditConst.auditStringClass[curAudit.status] %>"><%- auditConst.auditString[curAudit.status] %></span>
+                                <% } %>
+                            <% } else if (c.status === auditConst.status.checkNoPre && c.curAuditor2 && c.curAuditor2.findIndex(x => { return x.uid === ctx.session.sessionUser.accountId; }) >= 0) { %>
+                                <% const curAudit = c.curAuditors2.find(x => { return x.uid === ctx.session.sessionUser.accountId; }); %>
+                                <% if (curAudit.status === auditConst.status.checking) { %>
+                                <a href="<%- '/tender/' + ctx.tender.id + '/change/' + c.cid %>/information" class="btn <%- auditConst.statusButtonClass[c.status] %> btn-sm"><%- auditConst.statusButton[c.status] %></a>
+                                <% } else { %>
+                                    <span class="<%- auditConst.auditStringClass[curAudit.status] %>"><%- auditConst.auditString[curAudit.status] %></span>
+                                <% } %>
+                            <% } else { %>
+                                <span class="<%- auditConst.auditStringClass[c.status] %>"><%- auditConst.auditString[c.status] %></span>
+                            <% } %>
                         </td>
-                        <% } else if (c.status === auditConst.status.revise) { %>
-                            <td>
-                                待修订
-                            </td>
-                        <% } else if (c.changeAudit) { %>
-                        <td>
-                            <%- c.changeAudit.name %>-<%- c.changeAudit.jobs %>
-                            <span class="<%- auditConst.auditStatusClass[c.changeAudit.status] %>"><%- auditConst.auditStatusString[c.changeAudit.status] %></span>
+                        <td class="<%- auditConst.auditProgressClass[c.status] %>">
+                            <% if (c.curAuditors.length > 0) { %>
+                                <% if (c.curAuditors[0].audit_type === auditType.key.common) { %>
+                                    <a href="#sp-list" data-toggle="modal" data-target="#sp-list" c-id="<%- c.cid %>"><%- c.curAuditors[0].name %><%if (c.curAuditors[0].role !== '' && c.curAuditors[0].role !== null) { %>-<%- c.curAuditors[0].role %><% } %></a>
+                                <% } else { %>
+                                    <a href="#sp-list" data-toggle="modal" data-target="#sp-list" c-id="<%- c.cid %>"><%- ctx.helper.transFormToChinese(c.curAuditors[0].audit_order) + '审' %></a>
+                                <% } %>
+                            <% } %>
+                            <%- auditConst.auditProgress[c.status] %>
                         </td>
-                        <% } else { %><td></td><% } %>
-                        <td><% if (c.uid === uid && (c.status === auditConst.status.uncheck || ((c.status === auditConst.status.back || c.status === auditConst.status.revise) && c.stageChangeNum === 0 && !c.isSettle))) { %><a href="#del-bg" cid="<%= c.cid %>" data-toggle="modal" data-target="#del-bg" class="btn btn-outline-danger btn-sm delete-cid-modal">删除</a><% } %></td>
+                        <td class="text-center"><% if (c.uid === ctx.session.sessionUser.accountId && (c.status === auditConst.status.uncheck || ((c.status === auditConst.status.checkNo || c.status === auditConst.status.revise) && c.stageChangeNum === 0 && !c.isSettle))) { %><a href="#del-bg" cid="<%= c.cid %>" data-toggle="modal" data-target="#del-bg" class="btn btn-outline-danger btn-sm delete-cid-modal">删除</a><% } %></td>
                     </tr>
                     <% } %>
                     <% } %>

+ 65 - 54
app/view/change/information.ejs

@@ -14,44 +14,49 @@
                 </div>
                 <div class="pull-right mr-3" id="sp-btn">
                     <% if (ctx.change.cancancel) { %>
-                        <a href="javascript: void(0);" data-toggle="modal" data-target="#sp-down-cancel" class="btn btn-danger btn-sm">撤回</a>
+                        <a href="javascript: void(0);" data-toggle="modal" data-target="#sp-down-cancel" class="btn btn-danger btn-sm mr-2">撤回</a>
                     <% } %>
-                    <!--info状态区分-->
-                    <% if (auditStatus === 1) { %>
-                        <a href="#sub-ap" data-category="up_change" data-toggle="modal" data-target="#sub-ap" class="btn btn-primary btn-sm">上报审批</a>
-                    <% } else if (auditStatus === 2 || auditStatus === 9) { %>
-                        <a href="#sub-sp2" data-category="up_change" data-toggle="modal" data-target="#sub-sp2" class="btn btn-primary btn-sm">重新上报</a>
-                        <% if (auditStatus === 9) { %>
-                            <a href="#sub-revoke" data-toggle="modal" data-target="#sub-revoke" class="btn btn-warning btn-sm">撤销修订</a>
+                    <% if (ctx.change.status === auditConst.status.uncheck) { %>
+                        <% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %>
+                            <a id="sub-sp-btn" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm">上报审批</a>
+                        <% } else { %>
+                            <a id="sub-sp-btn" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-outline-secondary btn-sm">上报中</a>
                         <% } %>
-                    <% } else if (auditStatus === 3) { %>
-                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted">审批退回</a>
-                    <% } else if (auditStatus === 4) { %>
+                    <% } else if (ctx.change.status === auditConst.status.checking) { %>
+                        <% if (ctx.change.curAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) { %>
+                            <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm">审批通过</a>
+                            <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm">审批退回</a>
+                        <% } else { %>
+                            <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm">审批中</a>
+                        <% } %>
+                    <% } else if (ctx.change.status === auditConst.status.checkNoPre) { %>
+                        <% if (ctx.change.curAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) { %>
+                            <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm">审批通过</a>
+                            <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm">审批退回</a>
+                        <% } else { %>
+                            <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted">审批退回</a>
+                        <% } %>
+                    <% } else if (ctx.change.status === auditConst.status.checked) { %>
                         <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-success btn-sm">审批完成</a>
-                    <% } else if (auditStatus === 5) { %>
-                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-danger btn-sm">审批终止</a>
-                    <% } else if (auditStatus === 6) { %>
-                        <a href="#sp-done" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm">审批通过</a>
-                        <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm">审批退回</a>
-                    <% } else if (auditStatus === 7) { %>
-                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm">审批中</a>
-                    <% } else if (auditStatus === 8) { %>
-                        <% if (change.status === auditConst.status.uncheck) { %>
-                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm">上报中</a>
-                        <% } else if (change.status === auditConst.status.checking) { %>
-                        <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm">审批中</a>
+                        <% if (ctx.change.auditors !== undefined && ctx.change.finalAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) { %>
+                            <!--重新审批-->
+                            <a href="#sp-down-back" data-toggle="modal" data-target="#sp-down-back" class="btn btn-warning btn-sm ml-2">重新审批</a>
+                        <% } %>
+                        <% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %>
+                            <a href="javascript: void(0);" data-toggle="modal" data-target="#sp-down-revise" class="btn btn-warning btn-sm ml-2">修订变更</a>
+                        <% } %>
+                    <% } else if (ctx.change.status === auditConst.status.checkNo || ctx.change.status === auditConst.status.revise) { %>
+                        <a href="#sp-list" data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted sp-list-btn">审批<% if (ctx.change.status === auditConst.status.checkNo) { %>退回<% } else { %>修订<% } %></a>
+                        <% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %>
+                            <a href="#sp-list" data-type="show" data-toggle="modal" data-target="#sp-list" class="btn btn-primary btn-sm sp-list-btn">重新上报</a>
+                        <% } %>
+                        <% if (ctx.change.status === auditConst.status.revise && (ctx.session.sessionUser.accountId === ctx.change.uid || ctx.session.sessionUser.is_admin)) { %>
+                            <a href="#sub-revoke" data-toggle="modal" data-target="#sub-revoke" class="btn btn-warning btn-sm ml-2">撤销修订</a>
                         <% } %>
-                    <% } %>
-                    <% if (auditStatus === 4 && ctx.session.sessionUser.accountId === auditList2[auditList2.length-1].uid) { %>
-                        <!--重新审批-->
-                        <a href="javascript: void(0);" data-toggle="modal" data-target="#sp-down-back" class="btn btn-warning btn-sm">重新审批</a>
-                    <% } %>
-                    <% if (auditStatus === 4 && ctx.session.sessionUser.accountId === change.uid) { %>
-                        <a href="javascript: void(0);" data-toggle="modal" data-target="#sp-down-revise" class="btn btn-warning btn-sm">修订变更</a>
                     <% } %>
                 </div>
                 <!--info状态区分-->
-                <% if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) { %>
+                <% if (!change.readOnly) { %>
                     <div class="pull-right px-3" id="show-save-btn" style="display: none">
 <!--                        <span>您修改了变更信息,记得保存修改。</span>-->
                         <button class="btn btn-sm btn-primary save_change_btn" id="save_change"><i class="fa fa-save"></i> 保存修改</button>
@@ -66,8 +71,8 @@
         <div class="w-100 sub-content row">
             <div class="c-body" id="left-view" style="width: 33.33%">
                 <div class="sjs-bar-1">
-                    <input type="hidden" id="tenderId" value="<%- ctx.tender.id %>">
-                    <input type="hidden" id="changeId" value="<%- ctx.change.cid %>">
+                    <input type="hidden" id="tenderId" value="<%- tender.id %>">
+                    <input type="hidden" id="changeId" value="<%- change.cid %>">
                     <ul class="nav nav-tabs">
                         <li class="nav-item">
                             <a class="nav-link active" data-toggle="tab" data-tab="bgxinxi" href="#bgxinxi" role="tab">变更信息</a>
@@ -76,7 +81,7 @@
                             <a class="nav-link" data-toggle="tab" data-tab="bgfujian" href="#bgfujian" role="tab">附件</a>
                         </li>
                         <li class="nav-item ml-auto pt-1 mr-3" id="copy_btn">
-                            <% if(auditStatus === 1 || auditStatus === 2 || auditStatus === 9) { %>
+                            <% if(!change.readOnly) { %>
                                 <a class="btn btn-sm btn-primary" href="#add-bj" data-toggle="modal" data-target="#add-bj">拷贝其他变更令数据</a>
                             <% } %>
                         </li>
@@ -85,7 +90,7 @@
                             <button  data-toggle="modal" class="btn btn-sm btn-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</button>
                             <!-- <a href="javascript: void(0);" data-toggle="modal" class="btn btn-sm btn-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</a> -->
                             <a href="javascript:void(0);" class="page-select ml-3" content="pre"><i class="fa fa-chevron-left"></i></a> <span id="currentPage">1</span>/<span id="totalPage">10</span> <a href="javascript:void(0);" class="page-select mr-3" content="next"><i class="fa fa-chevron-right"></i></a>
-                            <% if (auditStatus !== 8 || (auditStatus === 8 && ctx.tender.touristPermission.file)) { %>
+                            <% if (change.filePermission) { %>
                             <a href="#addfujian" data-toggle="modal" class="btn btn-sm btn-light text-primary" data-placement="bottom" title="" data-original-title="上传附件"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件</a>
                             <% } %>
                             <a href="javascript: void(0);" id="zipDown" download style="display: none;"></a>
@@ -95,7 +100,7 @@
                 <div class="tab-content">
                     <div class="tab-pane active" id="bgxinxi">
                         <div class="sjs-sh-1" style="overflow-y: auto;">
-                            <% if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) { %>
+                            <% if (!change.readOnly) { %>
                             <form class="p-2" action="/tender/<%- change.tid %>/change/<%- change.cid %>/information/save?_csrf_j=<%= ctx.csrf %>" method="post" id="change_form">
                                 <% if (ctx.session.sessionProject.page_show.openChangeState) { %>
                                 <div class="form-group">
@@ -233,7 +238,7 @@
                                     <label>申请编号</label>
                                     <input class="form-control form-control-sm" value="<%- change.code %>" type="text" readonly>
                                 </div>
-                                <% if (auditStatus === 4) { %>
+                                <% if (change.status === auditConst.status.checked) { %>
                                     <div class="form-group">
                                         <label>变更令号(批复编号)</label>
                                         <input class="form-control form-control-sm" value="<%- change.p_code %>" type="text" readonly>
@@ -335,7 +340,7 @@
                                 </div>
                                 <div class="form-group">
                                     <label>批复文号</label>
-                                    <input class="form-control form-control-sm" id="w_code" placeholder="" type="text" value="<%- change.w_code %>" <% if (auditStatus !== 6) { %>readonly<% } %>>
+                                    <input class="form-control form-control-sm" id="w_code" placeholder="" type="text" value="<%- change.w_code %>" <% if (!change.shenpiPower) { %>readonly<% } %>>
                                 </div>
                             </form>
                             <% } %>
@@ -364,7 +369,7 @@
                                                 <td><%- moment(att.in_time * 1000).format('YYYY-MM-DD') %><br><%- ctx.helper.bytesToSize(att.filesize) %></td>
                                                 <td>
                                                     <a href="/change/download/file/<%- att.id %>" class="mr-2" title="下载"><span class="fa fa-download text-primary"></span></a>
-                                                    <% if (att.uid === ctx.session.sessionUser.accountId && (auditStatus === 4 ? Boolean(att.extra_upload) : true )) { %>
+                                                    <% if (att.uid === ctx.session.sessionUser.accountId && (change.status === auditConst.status.checked ? Boolean(att.extra_upload) : true )) { %>
                                                         <a href="javascript:void(0)" class="mr-2 delete-file" data-attid="<%- att.id %>" title="删除附件"><span class="fa fa-trash text-danger"></span></a>
                                                     <% } %>
                                                 </td>
@@ -385,7 +390,7 @@
                 <div class="sjs-height-1 row w-100 sub-content">
                     <div class="c-body" style="width: 100%">
                         <div class="m-1" id="list-tab">
-                            <% if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) { %>
+                            <% if (!change.readOnly) { %>
                                 <div class="d-inline-block ml-1">
                                     <a href="#addlist" data-toggle="modal" class="btn btn-sm btn-light text-primary" id="open-list-modal" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="添加清单"><i class="fa fa-plus" aria-hidden="true"></i> <span class="order_text"><% if (change.order_by === 0) { %>添加<% } else { %>插入<% } %></span>台账清单</a>
                                 </div>
@@ -424,7 +429,7 @@
                                     <label class="custom-control-label" for="customCheck1">变更详情</label>
                                 </div>
                             </div>
-                            <% if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7 || auditStatus === 8) { %>
+                            <% if (change.readOnly && !change.shenpiPower) { %>
                                 <div class="d-inline-block mr-2">
                                     <div class="custom-control custom-checkbox">
                                         <input type="checkbox" class="custom-control-input" id="show-table-detail">
@@ -469,21 +474,19 @@
     </div>
 </div>
 <script>
-    const tenderName = JSON.parse(unescape('<%- escape(JSON.stringify(tender.name)) %>'));
+    const tenderName = JSON.parse(unescape('<%- escape(JSON.stringify(tender.data.name)) %>'));
     const tenderId = '<%- tender.id %>';
     const totalPriceUnit = '<%- tpUnit %>';
     const unitPriceUnit = '<%- upUnit %>';
     const accountId = parseInt('<%- ctx.session.sessionUser.accountId %>');
     const ledgeStatus = '<%- tender.ledger_status %>';
     const ledgerConsts = JSON.parse('<%- JSON.stringify(ledgerConsts) %>');
-    const auditStatus = parseInt('<%- auditStatus %>');
     const changeName = JSON.parse(unescape('<%- escape(JSON.stringify(change.name)) %>'));
     let changeTp = parseFloat('<%- change.total_price ? change.total_price : 0 %>');
     let changePp = parseFloat('<%- change.positive_tp ? change.positive_tp : 0 %>');
     let changeNp = parseFloat('<%- change.negative_tp ? change.negative_tp : 0 %>');
     const changeStatus = parseFloat('<%- change.status %>');
     const touristPermission = parseInt('<%- ctx.tender.touristPermission.file %>');
-    const auditList = JSON.parse(unescape('<%- escape(JSON.stringify(auditList)) %>'));
     const precision = JSON.parse('<%- JSON.stringify(precision) %>');
     const whiteList = JSON.parse('<%- JSON.stringify(whiteList) %>');
     const auditConst = JSON.parse('<%- JSON.stringify(auditConst) %>');
@@ -492,14 +495,16 @@
     const change_uid = parseInt('<%- change.uid %>');;
     const settleBills = JSON.parse(unescape('<%- escape(JSON.stringify(settleBills)) %>'));
     const settlePos = JSON.parse(unescape('<%- escape(JSON.stringify(settlePos)) %>'));
+    const auditType = JSON.parse('<%- JSON.stringify(auditType) %>');
     autoFlashHeight();
-    $('a[href="#sub-ap"').click(function() {
+    $('a[href="#sub-sp"').click(function() {
         if (parseInt(ledgeStatus) === ledgerConsts.uncheck) {
             $('#warning-ledger').modal('show');
             return false;
         }
     });
     const readOnly = <%- change.readOnly %>;
+    const shenpiPower = <%- change.shenpiPower %>;
     const changeSpread = SpreadJsObj.createNewSpread($('#change-spread')[0]);
     const changeSpreadSheet = changeSpread.getActiveSheet();
     const xmjSpread = SpreadJsObj.createNewSpread($('#xmj-spread')[0]);
@@ -527,7 +532,7 @@
         toastr.warning('结算发生变化,已移除 ' + removeSettleNum + ' 条已结算清单。');
     }
 </script>
-<% if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) { %>
+<% if (!change.readOnly) { %>
 <script>
     let changeUnits = JSON.parse('<%- JSON.stringify(changeUnits) %>');
     changeUnits = _.map(changeUnits, 'unit');
@@ -569,18 +574,24 @@
 </script>
 <script src="/public/js/change_information_set.js"></script>
 <script src="/public/js/change_audit.js"></script>
-<% } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7 || auditStatus === 8) { %>
+<% } else if (change.readOnly && !change.shenpiPower) { %>
 <script>
-    const auditList2 = JSON.parse(unescape('<%- escape(JSON.stringify(auditList2)) %>'));
-    const aidList = _.map(auditList2, 'uid');
-    aidList.splice(0, 1);
+    const auditors2 = JSON.parse(unescape('<%- escape(JSON.stringify(change.auditors2)) %>'));
+    auditors2.shift();
+    const aidList = [];
+    for (let i = 0; i < auditors2.length; i++) {
+        aidList.push(auditors2[i][0].audit_order);
+    }
 </script>
 <script src="/public/js/change_information_show.js?202206211"></script>
-<% } else if (auditStatus === 6) { %>
+<% } else if (change.shenpiPower) { %>
 <script>
-    const auditList2 = JSON.parse(unescape('<%- escape(JSON.stringify(auditList2)) %>'));
-    const aidList = _.map(auditList2, 'uid');
-    aidList.splice(0, 1);
+    const auditors2 = JSON.parse(unescape('<%- escape(JSON.stringify(change.auditors2)) %>'));
+    auditors2.shift();
+    const aidList = [];
+    for (let i = 0; i < auditors2.length; i++) {
+        aidList.push(auditors2[i][0].audit_order);
+    }
     let changeUsedData = JSON.parse(unescape('<%- escape(JSON.stringify(changeUsedData)) %>'));
     // console.log(changeUsedData);
     const changeLedgerList = JSON.parse(unescape('<%- escape(JSON.stringify(changeLedgerList)) %>'));

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 729 - 881
app/view/change/information_modal.ejs


+ 47 - 2
app/view/change/modal.ejs

@@ -17,8 +17,32 @@
         </div>
     </div>
 </div>
-
-<% if (tender.user_id === uid) { %>
+<!--审批流程/结果-->
+<div class="modal fade" id="sp-list" 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="row">
+                    <div class="col-4 modal-height-500" style="overflow: auto">
+                        <div class="card mt-3">
+                            <ul class="list-group list-group-flush" id="auditor-list">
+                            </ul>
+                        </div>
+                    </div>
+                    <div class="col-8 modal-height-500" style="overflow: auto" id="audit-list">
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+<% if (tender.user_id === ctx.session.sessionUser.accountId) { %>
 <!--弹出添加变更令-->
 <div class="modal fade" id="add-bj-modal" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -150,6 +174,27 @@
     let codeRule = JSON.parse('<%- JSON.stringify(codeRule) %>');
     let connectorRule = '<%- tender.c_connector %>';
     let cRuleFirst = '<%- tender.c_rule_first %>';
+    const tenderId = '<%- ctx.tender.id %>';
+    const auditConst = JSON.parse(unescape('<%- escape(JSON.stringify(auditConst)) %>'));
+    const auditType = JSON.parse('<%- JSON.stringify(auditType) %>');
+
+    $('#audit-list').on('click', 'a', function() {
+        const type = $(this).data('target')
+        const auditCard = $(this).parent().parent()
+        if (type === 'show') {
+            $(this).data('target', 'hide')
+            auditCard.find('.fold-card').slideDown('swing', () => {
+                auditCard.find('#end-target').text($(this).data('idx') + '#')
+                auditCard.find('#fold-btn').text('收起历史审核记录')
+            })
+        } else {
+            $(this).data('target', 'show')
+            auditCard.find('.fold-card').slideUp('swing', () => {
+                auditCard.find('#end-target').text('1#')
+                auditCard.find('#fold-btn').text('展开历史审核记录')
+            })
+        }
+    });
 </script>
 <script src="/public/js/moment/moment.min.js"></script>
 

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


+ 1 - 38
app/view/setting/show.ejs

@@ -13,7 +13,7 @@
                         <div class="form-group">
                             <h6>项目列表默认显示</h6>
                             <div class="card w-50">
-                                <ul class="list-group list-group-flush">
+                                <ul class="list-group list-group-flush" id="tenderList">
                                     <% showList.forEach(function(item, idx) { %>
                                         <li class="list-group-item">
                                             <%= item.label_name %>
@@ -69,43 +69,6 @@
                                 </ul>
                             </div>
                         </div>
-                        <!--<div class="form-group">-->
-                            <!--<label>台账列显示</label>-->
-                            <!--<table class="table table-hover table-bordered">-->
-                                <!--<thead><tr><th>名称</th><th>是否显示</th><th>别名</th><th>位置</th></tr></thead>-->
-                                <!--<tbody id="ledger_col_list">-->
-                                <!--<% for (const sl of sjsRela.ledgerCol) { %>-->
-                                <!--<tr>-->
-                                    <!--<td><%- sl.name %></td>-->
-                                    <!--<td>-->
-                                        <!--<div class="form-check form-check-inline">-->
-                                            <!--<input class="form-check-input" type="checkbox" id="inlineCheckbox-<%- sl.field %>" <% if (sl.show) { %>checked<% } %> onchange="updateColShow('ledgerCol', '<%- sl.field %>', this);">-->
-                                            <!--<label class="form-check-label" for="inlineCheckbox-<%- sl.field %>"></label>-->
-                                        <!--</div>-->
-                                    <!--</td>-->
-                                    <!--<td>-->
-                                        <!--<div class="input-group input-group-sm" style="width:90px">-->
-                                            <!--<input type="text" class="form-control" value="<%- sl.alias %>" onchange="updateColAlias('ledgerCol', '<%- sl.field%>', this);">-->
-                                        <!--</div>-->
-                                    <!--</td>-->
-                                    <!--<td>-->
-                                        <!--<% if (sl.pos) { %>-->
-                                        <!--<div class="input-group input-group-sm">-->
-                                            <!--<select class="form-control form-control-sm" onchange="updateColPos('ledgerCol', '<%- sl.field%>', this)" value="<%- sl.pos %>" org="<%- sl.pos %>">-->
-                                                <!--<% for (const r of settingConst.exMemoPosRange[sl.field]) { %>-->
-                                                <!--<option value="<%- r.key %>" <% if (sl.pos === r.key) {%>selected<% } %>><%- r.hint %></option>-->
-                                                <!--<% } %>-->
-                                            <!--</select>-->
-                                        <!--</div>-->
-                                        <!--<% } else { %>-->
-                                        <!--<span class="form-control-sm text-warning"><%- sl.hint || '' %></span>-->
-                                        <!--<% } %>-->
-                                    <!--</td>-->
-                                <!--</tr>-->
-                                <!--<% } %>-->
-                                <!--</tbody>-->
-                            <!--</table>-->
-                        <!--</div>-->
                     </div>
                 </div>
             </div>

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

@@ -611,7 +611,7 @@
                                                                     <input class="form-check-input" type="radio" name="checkType" id="inlineRadio2" value="<%- auditConst.status.checkNoPre %>">
                                                                     <label class="form-check-label" for="inlineRadio2">退回上一审批人
                                                                         <% const pre = his.find(x => { return x.audit_order === auditor.audit_order - 1}); %>
-                                                                        <% (pre.audit_type === auditType.key.common ? pre.auditors[0].name : `${pre.audit_order}审`)%>
+                                                                        <%- (pre.audit_type === auditType.key.common ? pre.auditors[0].name : `${pre.audit_order}审`)%>
                                                                     </label>
                                                                 </div>
                                                                 <% } %>

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

@@ -60,7 +60,7 @@
             <div class="modal-footer d-flex justify-content-between">
                 <div class="ml-auto">
                     <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                    <button type="button" class="btn btn-sm btn-primary" id="add_cert_btn">添加</button>
+                    <button type="button" class="btn btn-sm btn-primary" id="add_cert_btn">确认</button>
                 </div>
             </div>
         </div>

+ 5 - 5
app/view/tender/shenpi.ejs

@@ -41,7 +41,7 @@
                                             <span class="col-auto"><%- ctx.helper.transFormToChinese(i+1) %>审</span>
                                             <span class="col-7 spr-span">
                                                 <span class="d-inline-block">
-                                                    <select class="form-control form-control-sm" data-type="<%- auditGroup[0].audit_type %>" <% if (sp.code !== 'stage') { %> style="display: none;" <% } %>>
+                                                    <select class="form-control form-control-sm" data-type="<%- auditGroup[0].audit_type %>" <% if (['stage', 'change'].indexOf(sp.code) === -1 ) { %> style="display: none;" <% } %>>
                                                         <% for (const at of auditType.types) { %>
                                                         <option value="<%- at.value %>" <% if (auditGroup[0].audit_type === at.value) { %>selected<%} %>><%- at.name %></option>
                                                         <% } %>
@@ -94,11 +94,11 @@
                                         <% } %>
                                         <li class="pl-3"><a href="javascript:void(0);" class="add-audit" ><i class="fa fa-plus"></i> 添加流程</a></li>
                                         <% } else { %>
-                                        <li class="d-flex justify-content-start mb-3">
+                                        <li class="d-flex justify-content-start mb-3 align-items-center">
                                             <span class="col-auto">一审</span>
                                             <span class="col-7 spr-span">
                                                 <span class="d-inline-block">
-                                                    <select class="form-control form-control-sm" data-type="<%- auditType.key.common %>" <% if (sp.code !== 'stage') { %> style="display: none;" <% } %>>
+                                                    <select class="form-control form-control-sm" data-type="<%- auditType.key.common %>" <% if (['stage', 'change'].indexOf(sp.code) === -1) { %> style="display: none;" <% } %>>
                                                         <% for (const at of auditType.types) { %>
                                                         <option value="<%- at.value %>" <% if (auditType.key.common === at.value) { %>selected<%} %>><%- at.name %></option>
                                                         <% } %>
@@ -144,7 +144,7 @@
                                             </span>
                                         </li>
                                         <% if (sp.audit) { %>
-                                        <li class="d-flex justify-content-start mb-3">
+                                        <li class="d-flex justify-content-start mb-3 align-items-center">
                                             <span class="col-auto">终审</span>
                                             <span class="col-7 spr-span">
                                             <span class="d-inline-block"></span>
@@ -163,7 +163,7 @@
                                             </span></span></span>
                                         </li>
                                         <% } else { %>
-                                        <li class="d-flex justify-content-start mb-3">
+                                        <li class="d-flex justify-content-start mb-3 align-items-center">
                                             <span class="col-auto">终审</span>
                                             <span class="col-7 spr-span">
                                                 <span class="d-inline-block">

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 45 - 49
app/view/wap/shenpi_change.ejs


+ 9 - 3
app/view/wap/tender.ejs

@@ -270,12 +270,18 @@
                             </tr>
                             <tr>
                                 <td colspan="2">
-                                    <% if ((c.status === auditChangeConst.status.checking || c.status === auditChangeConst.status.backnew) && c.curAuditor.uid === ctx.session.sessionUser.accountId) { %>
-                                    <a href="/wap/tender/<%- tender.id %>/change/<%- c.cid %>/info#shenpi" class="btn btn-block btn-success">审批变更</a>
+                                    <% if (c.showApprovalBtn){ %>
+                                    <a href="/wap/tender/<%- tender.id %>/change/<%- c.cid %>/information#shenpi" class="btn btn-block btn-success">审批变更</a>
                                     <% } else if (c.status === auditChangeConst.status.uncheck) { %>
                                     <span>待上报</span>
                                     <% } else { %>
-                                    <span class="<%- auditChangeConst.auditStatusClass[c.curAuditor.status] %>"><%- c.curAuditor.name %>-<%- c.curAuditor.jobs %> <%- auditChangeConst.auditStatusString[c.curAuditor.status] %></span>
+                                        <% if (c.curAuditors.length > 0) { %>
+                                            <% if (c.curAuditors[0].audit_type === auditType.key.common) { %>
+                                                <span class="<%- auditChangeConst.statusClass[c.status] %>"><%- c.curAuditors[0].name %>-<%- c.curAuditors[0].role %> <%- auditChangeConst.statusString[c.status] %></span>
+                                            <% } else { %>
+                                                <span class="<%- auditChangeConst.statusClass[c.status] %>"><%- ctx.helper.transFormToChinese(c.curAuditors[0].audit_order) + '审' %> <%- auditChangeConst.statusString[c.status] %></span>
+                                            <% } %>
+                                        <% } %>
                                     <% } %>
                                 </td>
                             </tr>

+ 3 - 0
db_script/baseUtils.js

@@ -153,6 +153,8 @@ const ZhCalc = {
     },
 };
 
+const _ = require('lodash');
+
 const recursiveMkdirSync = async function(pathName) {
     if (!fs.existsSync(pathName)) {
         const upperPath = path.dirname(pathName);
@@ -184,4 +186,5 @@ module.exports = {
     getFileName: function(fileName) {
         return path.join(__dirname, fileName);
     },
+    _: _,
 };

+ 5 - 5
db_script/project_spread.js

@@ -48,21 +48,21 @@ const updateSpreadWithSpec = function(spreadSetting, specSetting) {
     for (const s of specSetting) {
         for (const c of spreadSetting.cols) {
             if (s.condition.value.indexOf(c[s.condition.key]) >= 0) {
-                this._.assignIn(c, s.update);
+                BaseUtil._.assignIn(c, s.update);
             }
         }
     }
 };
 
 const generateRelaSpread = function (colSetType, colSet) {
-    const baseSetCol = colSetType.indexOf('stage') > 0 ? SpreadConst.BaseSetCol.Stage : SpreadConst.BaseSetCol.Ledger;
-    const baseSpreadColSetting = colSetType.indexOf('stage') > 0 ? SpreadConst.BaseSpreadColSetting.Stage : SpreadConst.BaseSpreadColSetting.Ledger;
+    const baseSetCol = SpreadConst.BaseSetCol[colSetType];
+    const baseSpreadColSetting = SpreadConst.BaseSpreadColSetting[colSetType];
     const billsSpread = generateSpreadSetting(colSet, SpreadConst.EmptySpreadSetting[colSetType].bills, baseSetCol, baseSpreadColSetting.bills);
     const posSpread = generateSpreadSetting(colSet, SpreadConst.EmptySpreadSetting[colSetType].pos, baseSetCol, baseSpreadColSetting.pos, 'pos');
     const spreadSpec = SpreadConst.SpreadSpec[colSetType];
     if (spreadSpec) {
-        this.updateSpreadWithSpec(billsSpread, spreadSpec.bills);
-        this.updateSpreadWithSpec(posSpread, spreadSpec.pos);
+        updateSpreadWithSpec(billsSpread, spreadSpec.bills);
+        updateSpreadWithSpec(posSpread, spreadSpec.pos);
     }
     return [billsSpread, posSpread];
 };

+ 61 - 16
sql/update.sql

@@ -32,22 +32,6 @@ CREATE TABLE `zh_filing_template`  (
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
 
-INSERT INTO `zh_filing_template_list` (`id`, `project_id`, `ft_type`, `user_id`, `name`, `memo`, `create_time`, `update_time`) VALUES ('698e87d8-e947-4049-98e4-15aae7c5c7fc', 0, 0, 0, '建设项目档案管理规范DA_T 28-2018', '', '2024-03-22 15:04:31', '2024-03-22 15:06:07');
-
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('0395ade6-5fe6-4b36-9b0a-c3696b044aaf', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 1, 1, '立项文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 1);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('5efafc28-fef5-46b3-be92-581a47cc454e', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 2, 1, '招标投标、合同协议文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 2);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('ef7ce0ba-f503-4364-b73f-ed9a1fe8c98d', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 3, 1, '勘察、设计文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 3);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('e2ac9fb4-08f7-4968-b5d1-c2487c2f3f61', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 4, 1, '征地、拆迁、移民文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 4);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('da3b9fb7-646f-49fa-8522-64d1d5ee53b1', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 5, 1, '项目管理文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 5);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('32be53bb-86db-4e4d-ae2d-03d3586e3965', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 6, 1, '施工文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 6);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('4c759d53-50f4-40fe-8f3b-b5b6ba8d3db3', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 7, 1, '信息系统开发文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 7);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('94505d98-f661-4be8-b381-2735476948b9', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 8, 1, '设备文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 8);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('5aca0493-089e-4064-83fd-3ac061cc1b04', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 9, 1, '监理文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 9);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('52f26ad6-bcd3-4bea-b533-283281fe6124', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 10, 1, '科研项目文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 10);
-INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('b95ecebd-fbd4-4110-abf4-7c055255d88f', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 11, 1, '生产技术准备、试运行文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 11);
-
-UPDATE zh_sub_project SET filing_template_id = "698e87d8-e947-4049-98e4-15aae7c5c7fc", filing_template_name = '建设项目档案管理规范DA_T 28-2018' WHERE management <> "";
-
 CREATE TABLE `zh_account_cert`  (
   `id` int NOT NULL AUTO_INCREMENT,
   `pid` int NULL COMMENT '项目id',
@@ -75,3 +59,64 @@ CREATE TABLE `zh_tender_cert`  (
   `create_time` datetime NULL COMMENT '入库时间',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT = '标段从业人员表';
+
+ALTER TABLE `zh_change_audit`
+ADD COLUMN `audit_type`  tinyint(4) UNSIGNED NOT NULL DEFAULT 1 COMMENT '审批类型(1个人,2会签,3或签)' AFTER `sin_time`,
+ADD COLUMN `audit_order`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '审批顺序' AFTER `audit_type`;
+
+ALTER TABLE `zh_change_audit`
+ADD COLUMN `begin_time` datetime NULL DEFAULT NULL COMMENT '审批开始时间' AFTER `sdesc`,
+ADD COLUMN `end_time` datetime NULL DEFAULT NULL COMMENT '审批结束时间' AFTER `begin_time`,
+MODIFY COLUMN `name` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '审批人名称' AFTER `uid`,
+MODIFY COLUMN `jobs` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '审批人职称' AFTER `name`,
+MODIFY COLUMN `company` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL COMMENT '审批人单位' AFTER `jobs`,
+MODIFY COLUMN `sin_time` datetime NULL DEFAULT NULL COMMENT '审批结束时间' AFTER `end_time`;
+
+CREATE TABLE `zh_project_spread`  (
+  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `pid` int(11) NOT NULL COMMENT 'zh_project.id',
+  `code` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
+  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
+  `is_default` tinyint(4) UNSIGNED NOT NULL COMMENT '是否默认值',
+  `tz_ledger_set` json NULL COMMENT '台账-台账-设置',
+  `tz_ledger_bills_spread` json NULL COMMENT '台账-台账-清单spread',
+  `tz_ledger_pos_spread` json NULL COMMENT '台账-台账-计量单元spread',
+  `gcl_ledger_set` json NULL COMMENT '工程量清单-台账-设置',
+  `gcl_ledger_bills_spread` json NULL COMMENT '工程量清单-台账-清单spread',
+  `gcl_ledger_pos_spread` json NULL COMMENT '工程量清单-台账-计量单元spread',
+  `tz_stage_set` json NULL COMMENT '台账-期计量-设置',
+  `tz_stage_bills_spread` json NULL COMMENT '台账-期计量-清单spread',
+  `tz_stage_pos_spread` json NULL COMMENT '台账-期计量-计量单元spread',
+  `gcl_stage_set` json NULL COMMENT '工程量清单-期计量-设置',
+  `gcl_stage_bills_spread` json NULL COMMENT '工程量清单-期计量-清单spread',
+  `gcl_stage_pos_spread` json NULL COMMENT '工程量清单-期计量-计量单元spread',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
+
+CREATE TABLE `zh_project_col_set`  (
+  `id` int(11) NOT NULL COMMENT 'zh_project.id',
+  `info` json NULL COMMENT '金额概况页列设置(见/const/project_setting)',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
+
+INSERT INTO `zh_filing_template_list` (`id`, `project_id`, `ft_type`, `user_id`, `name`, `memo`, `create_time`, `update_time`) VALUES ('698e87d8-e947-4049-98e4-15aae7c5c7fc', 0, 0, 0, '建设项目档案管理规范DA_T 28-2018', '', '2024-03-22 15:04:31', '2024-03-22 15:06:07');
+
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('0395ade6-5fe6-4b36-9b0a-c3696b044aaf', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 1, 1, '立项文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 1);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('5efafc28-fef5-46b3-be92-581a47cc454e', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 2, 1, '招标投标、合同协议文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 2);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('ef7ce0ba-f503-4364-b73f-ed9a1fe8c98d', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 3, 1, '勘察、设计文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 3);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('e2ac9fb4-08f7-4968-b5d1-c2487c2f3f61', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 4, 1, '征地、拆迁、移民文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 4);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('da3b9fb7-646f-49fa-8522-64d1d5ee53b1', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 5, 1, '项目管理文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 5);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('32be53bb-86db-4e4d-ae2d-03d3586e3965', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 6, 1, '施工文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 6);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('4c759d53-50f4-40fe-8f3b-b5b6ba8d3db3', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 7, 1, '信息系统开发文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 7);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('94505d98-f661-4be8-b381-2735476948b9', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 8, 1, '设备文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 8);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('5aca0493-089e-4064-83fd-3ac061cc1b04', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 9, 1, '监理文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 9);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('52f26ad6-bcd3-4bea-b533-283281fe6124', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 10, 1, '科研项目文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 10);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('b95ecebd-fbd4-4110-abf4-7c055255d88f', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 11, 1, '生产技术准备、试运行文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 11);
+
+UPDATE zh_sub_project SET filing_template_id = "698e87d8-e947-4049-98e4-15aae7c5c7fc", filing_template_name = '建设项目档案管理规范DA_T 28-2018' WHERE management <> "";
+
+update `zh_change_audit` set `audit_order` = `usite`;
+
+update `zh_change_audit` set `begin_time` = `sin_time`;
+update `zh_change_audit` set `end_time` = `sin_time`;
+