Bläddra i källkod

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

# Conflicts:
#	sql/update.sql
Tony Kang 10 månader sedan
förälder
incheckning
cc89de5b59
44 ändrade filer med 3187 tillägg och 346 borttagningar
  1. 16 1
      app/controller/change_controller.js
  2. 22 0
      app/controller/ledger_audit_controller.js
  3. 1 1
      app/controller/ledger_controller.js
  4. 47 0
      app/controller/stage_extra_controller.js
  5. 179 53
      app/controller/wap_controller.js
  6. 2 0
      app/lib/rm/change.js
  7. 4 3
      app/public/js/change_information_add_list.js
  8. 50 67
      app/public/js/change_information_set.js
  9. 7 0
      app/public/js/gcl_gather.js
  10. 224 3
      app/public/js/ledger.js
  11. 444 0
      app/public/js/se_yjcl.js
  12. 6 0
      app/public/js/spreadjs_rela/spreadjs_zh.js
  13. 2 2
      app/public/js/stage.js
  14. 9 1
      app/router.js
  15. 21 17
      app/service/change.js
  16. 48 0
      app/service/change_apply_audit.js
  17. 2 0
      app/service/change_audit_list.js
  18. 48 0
      app/service/change_project_audit.js
  19. 72 3
      app/service/ledger_audit.js
  20. 3 0
      app/service/report_memory.js
  21. 2 0
      app/service/rpt_gather_memory.js
  22. 2 0
      app/service/stage.js
  23. 10 0
      app/service/stage_audit.js
  24. 264 0
      app/service/stage_yjcl.js
  25. 1 1
      app/view/change/plan_information.ejs
  26. 37 4
      app/view/change/relation.ejs
  27. 152 9
      app/view/ledger/audit_modal.ejs
  28. 2 1
      app/view/ledger/explode.ejs
  29. 9 7
      app/view/ledger/explode_modal.ejs
  30. 2 0
      app/view/report/index_archive.ejs
  31. 1 1
      app/view/stage/gather.ejs
  32. 1 0
      app/view/stage_extra/sub_menu_list.ejs
  33. 39 0
      app/view/stage_extra/yjcl.ejs
  34. 45 1
      app/view/wap/dashboard.ejs
  35. 28 13
      app/view/wap/shenpi_change.ejs
  36. 268 0
      app/view/wap/shenpi_change_apply.ejs
  37. 309 0
      app/view/wap/shenpi_change_index.ejs
  38. 27 25
      app/view/wap/shenpi_change_plan.ejs
  39. 247 0
      app/view/wap/shenpi_change_project.ejs
  40. 45 51
      app/view/wap/shenpi_stage.ejs
  41. 26 82
      app/view/wap/tender.ejs
  42. 18 0
      config/web.js
  43. 35 0
      sql/update.sql
  44. 410 0
      sql/update20240801.sql

+ 16 - 1
app/controller/change_controller.js

@@ -685,7 +685,7 @@ module.exports = app => {
                         await ctx.service.change.saveInfo(data.updateData);
                         break;
                     case 'order_by':
-                        const result = await ctx.service.change.saveOrderBy(data.updateData, data.newLedgerList);
+                        const result = await ctx.service.change.saveOrderBy(data.updateData, data.updateOrderList);
                         responseData.data = result;
                         break;
                     case 'order_site':
@@ -719,6 +719,21 @@ module.exports = app => {
                         responseData.data.changeLedgerList = await ctx.service.changeLedger.getAllDataByCondition({ where: { tender_id: ctx.tender.id } });
                         responseData.data.changePosList = await ctx.service.changePos.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                         break;
+                    case 'plan_code':
+                        responseData.data.planInfo = null;
+                        responseData.data.applyInfo = null;
+                        responseData.data.projectInfo = null;
+                        await ctx.service.change.defaultUpdate({ plan_code: data.plan_code }, { where: { cid: ctx.change.cid } });
+                        if (data.plan_code) {
+                            responseData.data.planInfo = await ctx.service.changePlan.getDataByCondition({ tid: ctx.tender.id, code: data.plan_code });
+                            if (responseData.data.planInfo && responseData.data.planInfo.apply_code) {
+                                responseData.data.applyInfo = await ctx.service.changeApply.getDataByCondition({ tid: ctx.tender.id, code: responseData.data.planInfo.apply_code });
+                                if (responseData.data.applyInfo && responseData.data.applyInfo.project_code) {
+                                    responseData.data.projectInfo = await ctx.service.changeProject.getDataByCondition({ tid: ctx.tender.id, code: responseData.data.applyInfo.project_code });
+                                }
+                            }
+                        }
+                        break;
                     default: throw '参数有误';
                 }
 

+ 22 - 0
app/controller/ledger_audit_controller.js

@@ -188,6 +188,28 @@ module.exports = app => {
                 ctx.redirect(ctx.request.header.referer);
             }
         }
+
+        async saveAudit(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                if (ctx.session.sessionUser.is_admin && ctx.tender.ledger_status !== auditConst.status.checked) {
+                    await ctx.service.ledgerAudit.saveAudit(ctx.tender.id, ctx.tender.data.ledger_times, data);
+                    const auditors = await ctx.service.ledgerAudit.getAuditorsWithOwner(ctx.tender.id, ctx.tender.data.ledger_times);
+                    ctx.body = { err: 0, msg: '', data: auditors };
+                } else {
+                    throw '您无权进行该操作';
+                }
+            } catch (err) {
+                this.log(err);
+                // ctx.session.postError = err.toString();
+                // ctx.redirect(ctx.request.header.referer);
+                ctx.body = {
+                    err: 1,
+                    // url: ctx.request.header.referer,
+                    msg: err,
+                };
+            }
+        }
     }
 
     return LedgerAuditController;

+ 1 - 1
app/controller/ledger_controller.js

@@ -156,7 +156,7 @@ module.exports = app => {
                     authMobile: pa.auth_mobile,
                     deleteFilePermission: PermissionCheck.delFile(this.ctx.session.sessionUser.permission),
                 };
-                if ((tender.data.ledger_status === auditConst.status.uncheck || tender.data.ledger_status === auditConst.status.checkNo) && tender.data.user_id === ctx.session.sessionUser.accountId) {
+                if ((tender.data.ledger_status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) || ((tender.data.ledger_status === auditConst.status.uncheck || tender.data.ledger_status === auditConst.status.checkNo) && tender.data.user_id === ctx.session.sessionUser.accountId)) {
                     // renderData.accountGroup = accountGroup;
                     // 获取所有项目参与者
                     const accountList = await ctx.service.projectAccount.getAllDataByCondition({

+ 47 - 0
app/controller/stage_extra_controller.js

@@ -85,6 +85,53 @@ module.exports = app => {
         }
 
         /**
+         * 永久材料(Get)
+         *
+         * @param {Object} ctx - egg全局变量
+         */
+        async yjcl (ctx) {
+            try {
+                const renderData = {
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.stageExtra.yjcl)
+                };
+                await this.layout('stage_extra/yjcl.ejs', renderData);
+            } catch (err) {
+                ctx.helper.log(err);
+            }
+        }
+
+        /**
+         * 获取永久材料页面数据 (Get)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async loadYjcl (ctx) {
+            try {
+                const data = await ctx.service.stageYjcl.getStageData(ctx.stage);
+                ctx.body = {err: 0, msg: '', data: data};
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.body = this.ajaxErrorBody(error, '获取永久材料数据失败,请刷新');
+            }
+        }
+
+        /**
+         * 提交永久材料数据 (Ajaz)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async updateYjcl (ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const result = await ctx.service.stageYjcl.updateDatas(data);
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.body = this.ajaxErrorBody(error, '提交永久材料数据失败,请重试');
+            }
+        }
+
+        /**
          * 奖罚金(Get)
          *
          * @param {Object} ctx - egg全局变量

+ 179 - 53
app/controller/wap_controller.js

@@ -135,6 +135,16 @@ module.exports = app => {
             }
             // 获取待审批的变更期
             const auditChanges = await ctx.service.changeAudit.getAuditChangeByWap(ctx.session.sessionUser.accountId);
+            // 获取待审批的变更立项
+            let auditChangeProjects = [];
+            if (ctx.session.sessionProject.page_show.openChangeProject) {
+                auditChangeProjects = await ctx.service.changeProjectAudit.getAuditChangeProjectByWap(ctx.session.sessionUser.accountId);
+            }
+            // 获取待审批的变更申请
+            let auditChangeApplys = [];
+            if (ctx.session.sessionProject.page_show.openChangeApply) {
+                auditChangeApplys = await ctx.service.changeApplyAudit.getAuditChangeApplyByWap(ctx.session.sessionUser.accountId);
+            }
             // 获取待审批的变更方案
             let auditChangePlans = [];
             if (ctx.session.sessionProject.page_show.openChangePlan) {
@@ -151,6 +161,8 @@ module.exports = app => {
             const renderData = {
                 auditStages,
                 auditChanges,
+                auditChangeProjects,
+                auditChangeApplys,
                 auditChangePlans,
                 auditRevise,
                 auditAdvance,
@@ -257,39 +269,6 @@ module.exports = app => {
                     p.end_ratio = ctx.helper.mul(ctx.helper.div(p.end_tp, tender.sum, 4), 100);
                 }
 
-                // 变更令列表
-                const changes = await ctx.service.change.getListByStatus(tender.id, 0, 0);
-
-                for (const c of changes) {
-                    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;
-                        }
-                    }
-                }
-
-                // 变更令列表
-                let changePlans = [];
-                if (ctx.session.sessionProject.page_show.openChangePlan) {
-                    changePlans = await ctx.service.changePlan.getListByStatus(tender.id, 0, 0);
-                    for (const c of changePlans) {
-                        c.curAuditor = await ctx.service.changePlanAudit.getAuditorByStatus(c.id, c.status, c.times);
-                    }
-                }
-
                 // 台账修订列表
                 const revises = await ctx.service.ledgerRevise.getReviseList(ctx.tender.id);
                 for (const lr of revises) {
@@ -308,15 +287,10 @@ module.exports = app => {
                 const renderData = {
                     tender,
                     stages,
-                    changes,
-                    changePlans,
                     revises,
                     advanceList,
                     auditConst: auditConst.stage,
-                    auditChangeConst: auditConst.change,
-                    auditChangePlanConst: auditConst.changePlan,
                     auditReviseConst: auditConst.revise,
-                    changeConst,
                     advanceConst,
                     tpUnit: ctx.tender.info.decimal.tp,
                     monthProgress,
@@ -361,16 +335,19 @@ module.exports = app => {
                     await this.ctx.service.stage.checkStageGatherData(lastStage);
                 }
                 const stage = lastStage;
+                await ctx.service.stage.loadStageAuditViewData(stage);
                 const renderData = {
+                    moment,
                     tender,
                     stage,
                     auditConst: auditConst.stage,
+                    auditType,
                 };
-                const times = renderData.stage.status === auditConst.stage.status.checkNo ? renderData.stage.times - 1 : renderData.stage.times;
-                renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stage.user_id);
-                renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stage.id, times);
-                // 获取审批流程中左边列表
-                renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stage.id, times);
+                // const times = renderData.stage.status === auditConst.stage.status.checkNo ? renderData.stage.times - 1 : renderData.stage.times;
+                // renderData.stage.user = await ctx.service.projectAccount.getAccountInfoById(renderData.stage.user_id);
+                // renderData.stage.auditors = await ctx.service.stageAudit.getAuditors(renderData.stage.id, times);
+                // // 获取审批流程中左边列表
+                // renderData.stage.auditors2 = await ctx.service.stageAudit.getAuditGroupByList(renderData.stage.id, times);
                 renderData.stage.lastAuditors = await ctx.service.stageAudit.getAuditorsByStatus(stage.id, stage.status, stage.times);
                 await ctx.render('wap/shenpi_stage.ejs', renderData);
             } catch (err) {
@@ -380,6 +357,106 @@ module.exports = app => {
         }
 
         /**
+         * 工程变更列表页
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async changeIndex(ctx) {
+            try {
+                // 变更令列表
+                const changes = await ctx.service.change.getListByStatus(ctx.tender.id, 0, 0);
+
+                for (const c of changes) {
+                    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.changeAudit.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;
+                        }
+                    }
+                }
+                // 变更立项列表
+                let changeProjects = [];
+                if (ctx.session.sessionProject.page_show.openChangeProject) {
+                    changeProjects = await ctx.service.changeProject.getListByStatus(ctx.tender.id, 0, 0);
+                    for (const c of changeProjects) {
+                        c.showApprovalBtn = false;
+                        c.curAuditors = await ctx.service.changeProjectAudit.getAuditorsByStatus(c.id, c.status, c.times);
+                        const curAudit = c.curAuditors.find(function(x) {
+                            return x.uid === ctx.session.sessionUser.accountId;
+                        });
+                        if (curAudit && curAudit.status === auditConst.changeProject.status.checking) {
+                            c.showApprovalBtn = true;
+                        }
+                    }
+                }
+
+                // 变更申请列表
+                let changeApplys = [];
+                if (ctx.session.sessionProject.page_show.openChangeApply) {
+                    changeApplys = await ctx.service.changeApply.getListByStatus(ctx.tender.id, 0, 0);
+                    for (const c of changeApplys) {
+                        c.showApprovalBtn = false;
+                        c.curAuditors = await ctx.service.changeApplyAudit.getAuditorsByStatus(c.id, c.status, c.times);
+                        const curAudit = c.curAuditors.find(function(x) {
+                            return x.uid === ctx.session.sessionUser.accountId;
+                        });
+                        if (curAudit && curAudit.status === auditConst.changeApply.status.checking) {
+                            c.showApprovalBtn = true;
+                        }
+                    }
+                }
+
+                // 变更方案列表
+                let changePlans = [];
+                if (ctx.session.sessionProject.page_show.openChangePlan) {
+                    changePlans = await ctx.service.changePlan.getListByStatus(ctx.tender.id, 0, 0);
+                    for (const c of changePlans) {
+                        c.showApprovalBtn = false;
+                        c.curAuditors = await ctx.service.changePlanAudit.getAuditorsByStatus(c.id, c.status, c.times);
+                        const curAudit = c.curAuditors.find(function(x) {
+                            return x.uid === ctx.session.sessionUser.accountId;
+                        });
+                        if (curAudit && curAudit.status === auditConst.changePlan.status.checking) {
+                            c.showApprovalBtn = true;
+                        }
+                    }
+                }
+
+                const renderData = {
+                    tender: ctx.tender,
+                    changes,
+                    changeProjects,
+                    changeApplys,
+                    changePlans,
+                    auditChangeConst: auditConst.change,
+                    auditChangeProjectConst: auditConst.changeProject,
+                    auditChangeApplyConst: auditConst.changeApply,
+                    auditChangePlanConst: auditConst.changePlan,
+                    changeConst,
+                    tpUnit: ctx.tender.info.decimal.tp,
+                    auditType: auditConst.auditType,
+                };
+                await ctx.render('wap/shenpi_change_index.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/wap/list');
+            }
+        }
+
+        /**
          * 变更审批详细页
          *
          * @param {Object} ctx - egg全局变量
@@ -412,6 +489,60 @@ module.exports = app => {
         }
 
         /**
+         * 变更立项审批详细页
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async changeProject(ctx) {
+            try {
+                const tender = ctx.tender.data;
+                const change = ctx.change;
+                await ctx.service.changeProject.loadChangeAuditViewData(ctx.change);
+                const renderData = {
+                    moment,
+                    tender,
+                    change,
+                    auditConst: auditConst.changeProject,
+                    changeConst,
+                    tpUnit: ctx.tender.info.decimal.tp,
+                    auditType,
+                };
+                await ctx.render('wap/shenpi_change_project.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/wap/list');
+            }
+        }
+
+        /**
+         * 变更申请审批详细页
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async changeApply(ctx) {
+            try {
+                const tender = ctx.tender.data;
+                const change = ctx.change;
+                await ctx.service.changeApply.loadChangeAuditViewData(ctx.change);
+                const renderData = {
+                    moment,
+                    tender,
+                    change,
+                    auditConst: auditConst.changeApply,
+                    changeConst,
+                    tpUnit: ctx.tender.info.decimal.tp,
+                    auditType,
+                };
+                await ctx.render('wap/shenpi_change_apply.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/wap/list');
+            }
+        }
+
+        /**
          * 变更方案审批详细页
          *
          * @param {Object} ctx - egg全局变量
@@ -420,22 +551,17 @@ module.exports = app => {
         async changePlan(ctx) {
             try {
                 const tender = ctx.tender.data;
-                if (!ctx.session.sessionProject.page_show.openChangePlan) {
-                    throw '该功能已关闭';
-                }
-                const change = await ctx.service.changePlan.getDataById(ctx.params.cpid);
+                const change = ctx.change;
+                await ctx.service.changePlan.loadChangeAuditViewData(ctx.change);
                 const renderData = {
+                    moment,
                     tender,
                     change,
-                    auditConst: auditConst.changePlan,
+                    auditConst: auditConst.changeApply,
                     changeConst,
                     tpUnit: ctx.tender.info.decimal.tp,
+                    auditType,
                 };
-                const times = change.status !== auditConst.changePlan.status.checkNo ? change.times : change.times - 1;
-                renderData.change.user = await ctx.service.projectAccount.getAccountInfoById(change.uid);
-                renderData.change.auditors = await ctx.service.changePlanAudit.getAuditors(change.id, times);
-                // 获取审批流程中左边列表
-                renderData.change.auditors2 = await ctx.service.changePlanAudit.getAuditGroupByList(change.id, times);
                 await ctx.render('wap/shenpi_change_plan.ejs', renderData);
             } catch (err) {
                 this.log(err);

+ 2 - 0
app/lib/rm/change.js

@@ -61,6 +61,8 @@ class rptMemChange extends RptMemBase {
         for (const d of changeBills) {
             d.o_qty = d.oamount;
             d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+            d.o_qty2 = d.oamount2;
+            d.o_tp2 = this.ctx.helper.mul(d.o_qty2, d.unit_price, decimal.tp);
             d.c_qty = d.camount;
             d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
             d.s_qty = d.samount ? parseFloat(d.samount) : 0;

+ 4 - 3
app/public/js/change_information_add_list.js

@@ -144,6 +144,7 @@ $(document).ready(() => {
                     });
                 }
             }
+            console.log(xmjs, changeList);
             SpreadJsObj.loadSheetData(xmjSpreadSheet, SpreadJsObj.DataType.Data, xmjs);
             checkSelectAll(data);
         },
@@ -265,7 +266,7 @@ $(document).ready(() => {
                                 xmj_fbgc: xmjInfo.fbgc || '',
                                 xmj_fxgc: xmjInfo.fxgc || '',
                                 gcl_id: select.gcl_id,
-                                mx_id: select.mx_id,
+                                mx_id: select.mx_id || '',
                             }
                             _.assign(data, newData);
                         }
@@ -596,7 +597,7 @@ $(document).ready(() => {
                             xmj_fbgc: leaf.fbgc || '',
                             xmj_fxgc: leaf.fxgc || '',
                             gcl_id: leaf.gcl_id,
-                            mx_id: leaf.mx_id,
+                            mx_id: leaf.mx_id || '',
                         });
                     }
                 }
@@ -625,7 +626,7 @@ $(document).ready(() => {
             let hadContinue = false;
             for (const c of cList) {
                 const cInfo = c.deal_id ? _.find(changeList, { lid: c.deal_id }) : _.find(changeList, function (item) {
-                   return item.gcl_id === c.gcl_id && item.mx_id === c.mx_id;
+                   return item.gcl_id === c.gcl_id && item.mx_id === (c.mx_id || '');
                 });
                 if (_.find(changeUsedData, {cbid: cInfo.id})) {
                     hadContinue = true;

+ 50 - 67
app/public/js/change_information_set.js

@@ -961,71 +961,11 @@ $(document).ready(() => {
         changeListData = gclGatherData.concat(dealBillList).sort(sortByCode);
         tableDataRemake(changeListData);
         console.log(changeListData);
-        // 先加载台账数据
-        let listHtml = '';
-        let list_index = 1;
-        let gcl_index = 0;
-        const newChangeList = [];
-        for (const gcl of changeListData) {
-            const unit = gcl.unit !== undefined && gcl.unit !== null ? gcl.unit : '';
-            const quantity = gcl.quantity !== 0 && gcl.quantity !== null && gcl.quantity !== undefined ? (unit !== '' ? ZhCalc.round(gcl.quantity, findDecimal(gcl.unit)) : gcl.quantity) : 0;
-            const unit_price = gcl.unit_price !== null && gcl.unit_price !== undefined ? gcl.unit_price : 0;
-            let gclhtml = gcl.leafXmjs !== undefined && gcl.leafXmjs !== null ? ' data-gcl="' + gcl_index + '"' : '';
-            gcl_index = gclhtml !== '' ? ++gcl_index : gcl_index;
-            const lid = gcl.leafXmjs !== undefined && gcl.leafXmjs !== null ? (gcl.leafXmjs.length !== 0 ? gcl.leafXmjs[0].gcl_id : false) : gcl.id;
-            if (lid) {
-                listHtml += '<tr data-lid="' + lid + '"' + gclhtml + ' data-index="' + list_index + '" data-bwmx="">' +
-                    '<td class="text-center">' + list_index + (gcl.cid ? '<i class="text-danger" style="font-weight: 900">*</i>' : '') + '</td>' +
-                    '<td>' + gcl.code + '</td>' +
-                    '<td class="text-left">' + gcl.name + '</td>' +
-                    '<td class="text-center">' + unit + '</td>' +
-                    '<td class="text-right">' + (ZhCalc.round(unit_price, unitPriceUnit) ? ZhCalc.round(unit_price, unitPriceUnit) : 0) + '</td>' +
-                    '<td class="text-right">' + quantity + '</td>' +
-                    '</tr>';
-                list_index++;
-            }
-            if (!changeOrder) {
-                if (gcl.leafXmjs !== undefined && gcl.leafXmjs !== null) {
-                    const cl = _.filter(changeList, function (item) {
-                        return _.findIndex(gcl.leafXmjs, { gcl_id: item.gcl_id }) !== -1;
-                    });
-                    if (cl.length > 0) {
-                        if (gcl.leafXmjs.length === 1 && !gcl.leafXmjs[0].bwmx) {
-                            newChangeList.push(cl[0]);
-                        } else {
-                            for (const l of gcl.leafXmjs) {
-                                const c = _.find(cl, { mx_id: l.mx_id });
-                                if (c) newChangeList.push(c);
-                            }
-                        }
-                    }
-                } else {
-                    // 签约清单
-                    const c = _.find(changeList, { lid: gcl.id });
-                    if (c) newChangeList.push(c);
-                }
-            }
-        }
-        // 按台账去重新排序changeList,空白清单居后
-        if (!changeOrder) {
-            const sycList = _.difference(changeList, newChangeList);
-            console.log(sycList);
-            changeList = newChangeList.concat(sycList);
-            console.log(changeList);
-            // order如果不同,则修改并提交
-            const updateOrderList = [];
-            for (let i = 0; i < changeList.length; i++) {
-                if (changeList[i].order !== i + 1) {
-                    changeList[i].order = i + 1;
-                    updateOrderList.push({ id: changeList[i].id, order: i + 1 });
-                }
-            }
-            if (updateOrderList.length > 0) {
-                postData(window.location.pathname + '/save', { type:'changeOrder', postData: updateOrderList }, function (result) {
-                });
-            }
+        const updateOrderList = setUpdateOrder();
+        if (updateOrderList.length > 0) {
+            postData(window.location.pathname + '/save', { type:'changeOrder', postData: updateOrderList }, function (result) {
+            });
         }
-        $('#table-list-select').html(listHtml);
 
         SpreadJsObj.initSpreadSettingEvents(changeSpreadSetting, changeCol);
         SpreadJsObj.initSheet(changeSpreadSheet, changeSpreadSetting);
@@ -1070,6 +1010,48 @@ $(document).ready(() => {
         changeSpreadObj.refreshActn();
     });
 
+    function setUpdateOrder(newOrder = changeOrder) {
+        // 先加载台账数据
+        const newChangeList = [];
+        for (const gcl of changeListData) {
+            if (!newOrder) {
+                if (gcl.leafXmjs !== undefined && gcl.leafXmjs !== null) {
+                    const cl = _.filter(changeList, function (item) {
+                        return _.findIndex(gcl.leafXmjs, { gcl_id: item.gcl_id }) !== -1;
+                    });
+                    if (cl.length > 0) {
+                        if (gcl.leafXmjs.length === 1 && !gcl.leafXmjs[0].bwmx) {
+                            newChangeList.push(cl[0]);
+                        } else {
+                            for (const l of gcl.leafXmjs) {
+                                const c = _.find(cl, { mx_id: l.mx_id });
+                                if (c) newChangeList.push(c);
+                            }
+                        }
+                    }
+                } else {
+                    // 签约清单
+                    const c = _.find(changeList, { lid: gcl.id });
+                    if (c) newChangeList.push(c);
+                }
+            }
+        }
+        const updateOrderList = [];
+        // 按台账去重新排序changeList,空白清单居后
+        if (!newOrder) {
+            const sycList = _.difference(changeList, newChangeList);
+            changeList = newChangeList.concat(sycList);
+            // order如果不同,则修改并提交
+            for (let i = 0; i < changeList.length; i++) {
+                if (changeList[i].order !== i + 1) {
+                    changeList[i].order = i + 1;
+                    updateOrderList.push({ id: changeList[i].id, order: i + 1 });
+                }
+            }
+        }
+        return updateOrderList;
+    }
+
     if (!readOnly) {
         $('#add-white-btn').click(changeSpreadObj.add);
         $('#up-move').click(changeSpreadObj.upMove);
@@ -1992,9 +1974,9 @@ $(document).ready(() => {
     $('.dropdown-menu input[name="paixu"]').on('click', function () {
         const newChangeOrder = parseInt($(this).val());
         if (newChangeOrder !== changeOrder) {
-            const newLedgerList = changeOrder ? remakeChangeSpread(0) : [];
+            const updateOrderList = !newChangeOrder ? setUpdateOrder(newChangeOrder) : [];
             // 更新至服务器
-            postData(window.location.pathname + '/save', { type:'order_by', updateData: newChangeOrder, newLedgerList }, function (result) {
+            postData(window.location.pathname + '/save', { type:'order_by', updateData: newChangeOrder, updateOrderList }, function (result) {
                 if (newChangeOrder === 0) {
                     $('#bpaixu').text('清单排序:清单编号');
                     $('#upAndMoveBtn').attr('style', 'display: none !important');
@@ -2013,6 +1995,7 @@ $(document).ready(() => {
                 SpreadJsObj.loadSheetData(changeSpreadSheet, SpreadJsObj.DataType.Data, changeList);
                 changeSpreadObj.makeSjsFooter();
                 changeSpreadObj.resetXmjSpread(SpreadJsObj.getSelectObject(changeSpreadSheet));
+                changeSpreadObj.refreshActn();
             });
         }
     });
@@ -2334,7 +2317,7 @@ function makeWhiteList(clinfo) {
     clinfo.xmj_fbgc = null;
     clinfo.xmj_fxgc = null;
     clinfo.gcl_id = '';
-    clinfo.mx_id = null;
+    clinfo.mx_id = '';
     return clinfo;
 }
 

+ 7 - 0
app/public/js/gcl_gather.js

@@ -715,6 +715,13 @@ const gclGatherModel = (function () {
                 gatherfields(glx, lx, ancillaryGclGatherFields);
             }
         }
+        gcl.gatherAncGcl.sort((a, b) => {
+            if (a.is_aux === b.is_aux) {
+                return a.name < b.name ? -1 : 1;
+            } else {
+                return a.is_aux - b.is_aux;
+            }
+        });
     }
 
     function reGatherAncillaryGcl(fields) {

+ 224 - 3
app/public/js/ledger.js

@@ -4130,7 +4130,7 @@ $(document).ready(function() {
     });
 
     // 添加审批流程按钮逻辑
-    $('.book-list').on('click', 'dt', function () {
+    $('body').on('click', '.book-list dt', function () {
         const idx = $(this).find('.acc-btn').attr('data-groupid')
         const type = $(this).find('.acc-btn').attr('data-type')
         if (type === 'hide') {
@@ -4149,7 +4149,7 @@ $(document).ready(function() {
     });
 
     // 添加到审批流程中
-    $('dl').on('click', 'dd', function () {
+    $('#book-list').on('click', 'dd', function () {
         const auditorId = parseInt($(this).data('id'))
         if (auditorId) {
             postData('/tender/' + getTenderId() + '/ledger/audit/add', { auditorId }, (datas) => {
@@ -4222,11 +4222,232 @@ $(document).ready(function() {
         $('#sp-list').modal('hide');
     });
 
+    $('a[f-target]').click(function () {
+        $($(this).attr('f-target')).modal('show');
+    });
+
     // 多层modal关闭后的滚动bug修复
     $('#sp-list').on('hidden.bs.modal', function (e) {
         $(document.body).addClass('modal-open');
     });
 
+    // 管理员更改审批流程js部分
+    let timer2 = null;
+    let oldSearchVal2 = null;
+    $('body').on('input propertychange', '.gr-search', function(e) {
+        oldSearchVal2 = e.target.value;
+        timer2 && clearTimeout(timer2);
+        timer2 = setTimeout(() => {
+            const newVal = $(this).val();
+            const code = $(this).attr('data-code');
+            let html = '';
+            if (newVal && newVal === oldSearchVal2) {
+                accountList.filter(item => item && (item.name.indexOf(newVal) !== -1 || (item.mobile && item.mobile.indexOf(newVal) !== -1))).forEach(item => {
+                    html += `<dd class="border-bottom p-2 mb-0 " data-id="${item.id}" >
+                        <p class="mb-0 d-flex"><span class="text-primary">${item.name}</span><span
+                                class="ml-auto">${item.mobile || ''}</span></p>
+                        <span class="text-muted">${item.role || ''}</span>
+                    </dd>`
+                });
+                $('#' + code + '_dropdownMenu .book-list').empty();
+                $('#' + code + '_dropdownMenu .book-list').append(html);
+            } else {
+                if (!$('#' + code + '_dropdownMenu .acc-btn').length) {
+                    accountGroup.forEach((group, idx) => {
+                        if (!group) return;
+                        html += `<dt><a href="javascript: void(0);" class="acc-btn" data-groupid="${idx}" data-type="hide"><i class="fa fa-plus-square"></i>
+                        </a> ${group.groupName}</dt>
+                        <div class="dd-content" data-toggleid="${idx}">`;
+                        group.groupList.forEach(item => {
+                            html += `<dd class="border-bottom p-2 mb-0 " data-id="${item.id}" >
+                                <p class="mb-0 d-flex"><span class="text-primary">${item.name}</span><span
+                                        class="ml-auto">${item.mobile || ''}</span></p>
+                                <span class="text-muted">${item.role || ''}</span>
+                            </dd>`;
+                        });
+                        html += '</div>';
+                    });
+                    $('#' + code + '_dropdownMenu .book-list').empty();
+                    $('#' + code + '_dropdownMenu .book-list').append(html);
+                }
+            }
+        }, 400);
+    });
+
+    $('body').on('click', '#admin-edit-shenpi dl dd', function () {
+        const id = parseInt($(this).attr('data-id'));
+        if (!id) return;
+
+        let this_aid = parseInt($(this).parents('.book-list').attr('data-aid'));
+        let this_operate = $(this).parents('.book-list').attr('data-operate');
+        const user = _.find(accountList, function (item) {
+            return item.id === id;
+        });
+        const auditorIndex = _.findIndex(auditorList, { audit_id: id });
+        if (auditorIndex !== -1) {
+            toastr.warning('该审核人已存在,请勿重复添加');
+            return;
+        }
+        const order = parseInt($(this).parents('tr').find('.shenpi-order').text());
+        const curAuditorIndex = _.findIndex(auditorList, { audit_id: this_aid });
+        const prop = {
+            operate: this_operate,
+            old_aid: this_aid,
+            new_aid: user.id,
+        };
+        postData('/tender/' + getTenderId() + '/ledger/audit/save', prop, (datas) => {
+            if (this_operate === 'add') {
+                const addhtml = '<tr>\n' +
+                    `                                <td><span class="shenpi-order">${order+1}</span> ${user.name} <small class="text-muted">${user.role}</small></td>\n` +
+                    `                                <td style="text-align: center"><span class="">待审批</span></td>\n` +
+                    '                                <td style="text-align: center">\n' +
+                    '                                    <span class="dropdown mr-2">\n' +
+                    `                                    <a href="javascript: void(0)" class="add-audit" id="${user.id}_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>\n` +
+                    makeSelectAudit(user.id+'_add', user.id, 'add') +
+                    '                                        </div>\n' +
+                    '                                    </span>\n' +
+                    '                                    <span class="dropdown mr-2">\n' +
+                    `                                        <a href="javascript: void(0)" class="change-audit" id="${user.id}_change_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>\n` +
+                    makeSelectAudit(user.id+'_change', user.id, 'change') +
+                    '                                    </span>\n' +
+                    '                                    <span class="dropdown">\n' +
+                    '                                    <a href="javascript: void(0)" class="text-danger" title="移除" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">移除</a>\n' +
+                    '                                    <div class="dropdown-menu">\n' +
+                    '                                        <span class="dropdown-item">确认移除审批人?</span>\n' +
+                    '                                        <div class="dropdown-divider"></div>\n' +
+                    '                                        <div class="px-2 py-1 text-center">\n' +
+                    `                                            <button class="remove-audit btn btn-sm btn-danger" data-id="${user.id}">移除</button>\n` +
+                    '                                            <button class="btn btn-sm btn-secondary">取消</button>\n' +
+                    '                                        </div>\n' +
+                    '                                    </div>\n' +
+                    '                                    </span>\n' +
+                    '                                </td>\n' +
+                    '                            </tr>';
+                $(this).parents('tr').after(addhtml);
+                auditorList.splice(curAuditorIndex+1, 0, { audit_id: user.id, company: user.company, name: user.name, role: user.role });
+                updateOrder(user.id);
+            } else if (this_operate === 'change') {
+                const this_user = _.find(auditorList, { audit_id: this_aid });
+                this_user.audit_id = user.id;
+                this_user.company = user.company;
+                this_user.role = user.role;
+                this_user.name = user.name;
+                auditorList.splice(curAuditorIndex, 1, this_user);
+                $(this).parents('tr').children('td').eq(0).html(`<span class="shenpi-order">${order}</span> ${user.name} <small class="text-muted">${user.role}</small>`);
+                // 替换所有aid
+                $(this).parents('.book-list').attr('data-aid', user.id);
+                $(this).parents('.dropdown-menu').attr('id', user.id +'_change_dropdownMenu').attr('aria-labelledby', user.id +'_change_dropdownMenuButton');
+                $(this).parents('.dropdown-menu').children('mb-2').children('input').attr('data-code', user.id +'_change');
+                $(this).parents('.dropdown-menu').siblings('.change-audit').attr('id', user.id +'_change_dropdownMenuButton');
+                $(this).parents('td').children('span').eq(0).find('.add-audit').attr('id', user.id +'_add_dropdownMenuButton');
+                $(this).parents('td').children('span').eq(0).find('.dropdown-menu').attr('id', user.id +'_add_dropdownMenu').attr('aria-labelledby', user.id +'_add_dropdownMenuButton');
+                $(this).parents('td').children('span').eq(0).find('.dropdown-menu').children('mb-2').children('input').attr('data-code', user.id +'_add');
+                $(this).parents('td').children('span').eq(0).find('.dropdown-menu').children('.book-list').attr('data-aid', user.id);
+                $(this).parents('td').children('span').eq(2).find('.remove-audit').attr('data-id', user.id);
+            }
+            changeLiucheng(datas);
+        });
+    });
+
+    // 移除审批人
+    $('body').on('click', '.remove-audit', function () {
+        const id = parseInt($(this).attr('data-id'));
+        const prop = {
+            operate: 'del',
+            old_aid: id,
+        };
+        postData('/tender/' + getTenderId() + '/ledger/audit/save', prop, (datas) => {
+            updateOrder(id, 0);
+            const curAuditorIndex = _.findIndex(auditorList, { audit_id: id });
+            auditorList.splice(curAuditorIndex, 1);
+            $(this).parents('tr').remove();
+            changeLiucheng(datas);
+        });
+    });
+
+    // 比uid大的序号进行调整
+    function updateOrder(aid, num = 1) {
+        const index = _.findIndex(auditorList, { audit_id: aid });
+        for (let i = index;i < auditorList.length; i++) {
+            $('#admin-edit-shenpi tbody').children('tr').eq(i).find('.shenpi-order').text(i+num);
+        }
+    }
+
+    function changeLiucheng(datas) {
+        const auditorshtml = [];
+        let lastAuditorHtml = '';
+        for (const [index,data] of datas.entries()) {
+            auditorshtml.push('<li class="list-group-item" data-auditorid="' + data.audit_id + '">');
+            auditorshtml.push('<i class="fa ' + (index+1 === datas.length ? 'fa-stop-circle' : 'fa-chevron-circle-down') + '"></i> ');
+            auditorshtml.push(data.name + ' <small class="text-muted">' + data.role + '</small>');
+            if (index === 0) {
+                auditorshtml.push('<span class="pull-right">原报</span>');
+            } else if (index+1 === datas.length) {
+                auditorshtml.push('<span class="pull-right">终审</span>');
+            } else {
+                auditorshtml.push('<span class="pull-right">'+ transFormToChinese(index) +'审</span>');
+            }
+            auditorshtml.push('</li>');
+            if (data.status === auditConst.status.uncheck) {
+                lastAuditorHtml += '<li class="timeline-list-item pb-2 is_uncheck">\n' +
+                    '                                            <div class="timeline-item-date">\n' +
+                    '                                                \n' +
+                    '                                            </div>\n' +
+                    '                                            <div class="timeline-item-icon bg-secondary text-light">\n' +
+                    '                                            </div>\n' +
+                    '                                            <div class="timeline-item-content">\n' +
+                    '                                                <div class="card">\n' +
+                    '                                                    <div class="card-body p-3">\n' +
+                    '                                                        <div class="card-text">\n' +
+                    `                                                            <p class="mb-1"><span class="h5">${data.name}</span>\n` +
+                    '                                                                <span class="pull-right ">\n' +
+                    '                                                                </span>\n' +
+                    '                                                            </p>\n' +
+                    `                                                            <p class="text-muted mb-0">${data.role}</p>\n` +
+                    '                                                        </div>\n' +
+                    '                                                    </div>\n' +
+                    '                                                </div>\n' +
+                    '                                            </div>\n' +
+                    '                                        </li>';
+            }
+        }
+        $('.last-auditor-list .is_uncheck').remove();
+        $('.last-auditor-list').append(lastAuditorHtml);
+        $('.auditors-list').html(auditorshtml.join(''));
+
+    }
+
+    // 审批流程-选择审批人html 生成
+    function makeSelectAudit(code, aid, status) {
+        let divhtml = '';
+        accountGroup.forEach((group, idx) => {
+            let didivhtml = '';
+            if(group) {
+                group.groupList.forEach(item => {
+                    didivhtml += '<dd class="border-bottom p-2 mb-0 " data-id="' + item.id + '" >\n' +
+                        '<p class="mb-0 d-flex"><span class="text-primary">' + item.name + '</span><span\n' +
+                        '                                                                                class="ml-auto">' + item.mobile + '</span></p>\n' +
+                        '                                                                    <span class="text-muted">' + item.role + '</span>\n' +
+                        '                                                                    </dd>\n';
+                });
+                divhtml += '<dt><a href="javascript: void(0);" class="acc-btn" data-groupid="' + idx + '" data-type="hide"><i class="fa fa-plus-square"></i></a> ' + group.groupName + '</dt>\n' +
+                    '                                                                <div class="dd-content" data-toggleid="' + idx + '">\n' + didivhtml +
+                    '                                                                </div>\n';
+            }
+        });
+        let html = '<div class="dropdown-menu dropdown-menu-right" id="' + code + '_dropdownMenu" aria-labelledby="' + code + '_dropdownMenuButton" style="width:220px">\n' +
+            '                                                        <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"\n' +
+            '                                                                                     placeholder="姓名/手机 检索" autocomplete="off" data-code="' + code + '"></div>\n' +
+            '                                                        <dl class="list-unstyled book-list" data-aid="'+ aid +'" data-operate="'+ status +'">\n' + divhtml +
+            '                                                        </dl>\n' +
+            '                                                    </div>\n' +
+            '                                                </div>\n' +
+            '                                            </span>\n' +
+            '                                        </span>\n' +
+            '                                        </li>';
+        return html;
+    }
+
     // 显示层次
     (function (select, sheet) {
         $(select).click(function () {
@@ -4806,4 +5027,4 @@ function auditCheck(i) {
     const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
     $('textarea[name="opinion"]').eq(i).val(opinion);
     return true;
-}
+}

+ 444 - 0
app/public/js/se_yjcl.js

@@ -0,0 +1,444 @@
+'use strict';
+
+/**
+ * 期 - 甲供材料
+ *
+ * @author Mai
+ * @date 2020/2/12
+ * @version
+ */
+
+$(document).ready(() => {
+    autoFlashHeight();
+    const spreadSetting = {
+        cols: [
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 100, formatter: '@'},
+            {title: '规格型号', colSpan: '1', rowSpan: '2', field: 'spec', hAlign: 0, width: 100, formatter: '@'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '除税单价', colSpan: '1', rowSpan: '2', field: 'ex_tax_up', hAlign: 2, width: 100, type: 'Number', readOnly: true},
+            {title: '税率', colSpan: '1', rowSpan: '2', field: 'tax', hAlign: 1, width: 50, type: 'Number'},
+            {title: '到场|数量',  colSpan: '2|1', rowSpan: '1|1', field: 'arrive_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额',  colSpan: '|1', rowSpan: '|1', field: 'arrive_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '截止本期计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '到场信息|到场时间', colSpan: '5|1', rowSpan: '1|1', field: 'arrive_time', hAlign: 1, width: 80, formatter: '@'},
+            {title: '|材料来源', colSpan: '|1', rowSpan: '|1', field: 'source', hAlign: 0, width: 150, formatter: '@', wordWrap: true},
+            {title: '|单据号', colSpan: '|1', rowSpan: '|1', field: 'bills_code', hAlign: 0, width: 100, formatter: '@', wordWrap: true},
+            {title: '|存放位置', colSpan: '|1', rowSpan: '|1', field: 'location', hAlign: 0, width: 80, formatter: '@', wordWrap: true},
+            {title: '|拟用于部位', colSpan: '|1', rowSpan: '|1', field: 'prepare_pos', hAlign: 0, width: 150, formatter: '@', wordWrap: true},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}
+        ],
+        emptyRows: readOnly ? 0 : 3,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: readOnly,
+        localCache: {
+            key: 'stage-extra-yjcl',
+            colWidth: true,
+        },
+        getColor: function (sheet, data, row, col, defaultColor) {
+            if (!data || !data.end_tp) return defaultColor;
+
+            return data.end_qty >= 0
+                ? data.end_qty > data.arrive_qty ? '#f8d7da' : defaultColor
+                : data.end_qty < data.arrive_qty ? '#f8d7da' : defaultColor;
+        },
+    };
+    const yjclSpread = SpreadJsObj.createNewSpread($('#yjcl-spread')[0]);
+    const yjclSheet = yjclSpread.getActiveSheet();
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(spreadSetting);
+    SpreadJsObj.initSheet(yjclSheet, spreadSetting);
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+            yjclSpread.refresh();
+        }
+    });
+
+    class Yjcl {
+        constructor () {
+            this.data = [];
+        }
+        resortData() {
+            this.data.sort(function (a, b) {
+                return a.m_order - b.m_order;
+            });
+        }
+        calculateAll() {
+            for (const d of this.data) {
+                d.end_qty = ZhCalc.add(d.pre_qty, d.qty);
+                d.end_tp = ZhCalc.add(d.pre_tp, d.tp);
+            }
+        }
+        loadDatas(datas) {
+            this.data = datas;
+            this.calculateAll();
+            this.resortData();
+        }
+        loadUpdateData(updateData) {
+            if (updateData.add) {
+                for (const a of updateData.add) {
+                    this.data.push(a);
+                }
+            }
+            if (updateData.update) {
+                for (const u of updateData.update) {
+                    const d = this.data.find(function (x) {
+                        return u.id === x.id;
+                    });
+                    if (d) {
+                        _.assign(d, u);
+                    } else {
+                        this.data.push(d);
+                    }
+                }
+            }
+            if (updateData.del) {
+                _.remove(this.data, function (d) {
+                    return updateData.del.indexOf(d.id) >= 0;
+                });
+            }
+            this.calculateAll();
+            this.resortData();
+        }
+        getMaxOrder() {
+            return this.data.length > 0 ? this.data[this.data.length - 1].m_order : 0;
+        }
+    }
+    const yjclObj = new Yjcl();
+
+    postData(window.location.pathname + '/load', null, function (result) {
+        yjclObj.loadDatas(result);
+        SpreadJsObj.loadSheetData(yjclSheet, SpreadJsObj.DataType.Data, yjclObj.data);
+    });
+
+    if (!readOnly) {
+        const yjclOprObj = {
+            /**
+             * 删除按钮响应事件
+             * @param sheet
+             */
+            deletePress: function (sheet) {
+                if (!sheet.zh_setting || readOnly) return;
+
+                const sortData = sheet.zh_data;
+                const datas = [];
+                const sels = sheet.getSelections();
+                if (!sels || !sels[0]) return;
+
+                for (let iRow = sels[0].row; iRow < sels[0].row + sels[0].rowCount; iRow++) {
+                    let bDel = false;
+                    const node = sortData[iRow];
+                    if (node) {
+                        const data = {id: node.id};
+                        for (let iCol = sels[0].col; iCol < sels[0].col + sels[0].colCount; iCol++) {
+                            const colSetting = sheet.zh_setting.cols[iCol];
+                            if (colSetting.field === 'name') {
+                                toastr.error('名称不能为空,如需删除材料请使用右键删除');
+                                return;
+                            }
+                            const style = sheet.getStyle(iRow, iCol);
+                            if (!style.locked) {
+                                const colSetting = sheet.zh_setting.cols[iCol];
+                                data[colSetting.field] = colSetting.type === 'Number' ? 0 : '';
+                                bDel = true;
+                            }
+                        }
+                        if (bDel) {
+                            datas.push(data);
+                        }
+                    }
+                }
+                if (datas.length > 0) {
+                    postData(window.location.pathname + '/update', {update: datas}, function (result) {
+                        yjclObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    }, function () {
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    });
+                }
+            },
+            delete: function (sheet) {
+                if (!sheet.zh_setting || readOnly) return;
+
+                const sortData = sheet.zh_data;
+                const datas = [];
+                const sels = sheet.getSelections();
+                if (!sels || !sels[0]) return;
+                const hint = {
+                    isOld: {type: 'warning', msg: '该材料已计量,不可删除'},
+                    invalidDel: {type: 'warning', msg: '该材料不是您新增的,只有原报和新增人可删除'},
+                };
+
+                for (let iRow = sels[0].row, iLen = sels[0].row + sels[0].rowCount; iRow < iLen; iRow++) {
+                    const node = sortData[iRow];
+                    if (node.pre_used || !checkZero(node.end_qty) || !checkZero(node.end_qty)) {
+                        toastMessageUniq(hint.isOld);
+                        continue;
+                    } else {
+                        if (node.add_uid !== userID && stageUserId !== userID) {
+                            toastMessageUniq(hint.invalidDel);
+                            continue;
+                        }
+                        datas.push(node.id);
+                    }
+                }
+                if (datas.length > 0) {
+                    postData(window.location.pathname + '/update', {del: datas}, function (result) {
+                        yjclObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    }, function () {
+                        SpreadJsObj.reLoadSheetData(yjclSheet);
+                    });
+                }
+            },
+            editEnded: function (e, info) {
+                if (!info.sheet.zh_setting || !info.sheet.zh_data) return;
+
+                const node = info.sheet.zh_data[info.row];
+                const col = info.sheet.zh_setting.cols[info.col];
+                const data = {};
+                const maxOrder = yjclObj.getMaxOrder();
+
+                if (node) {
+                    data.update = {};
+                    data.update.id = node.id;
+
+                    const oldValue = node ? node[col.field] : null;
+                    const newValue = trimInvalidChar(info.editingText);
+                    if (oldValue == info.editingText || ((!oldValue || oldValue === '') && (newValue === ''))) {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    data.update[col.field] = newValue;
+                } else {
+                    if (col.field !== 'name') {
+                        toastr.warning('新增材料,请先输入名称');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    data.add = {};
+                    data.add.m_order = maxOrder + 1;
+                    data.add.name = trimInvalidChar(info.editingText);
+                }
+
+                postData(window.location.pathname + '/update', data, function (result) {
+                    yjclObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadSheetData(info.sheet);
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                });
+            },
+            editStarting(e, info) {
+                if (!info.sheet.zh_setting || !info.sheet.zh_data) {
+                    info.cancel = true;
+                    return;
+                }
+
+                const col = info.sheet.zh_setting.cols[info.col];
+                const node = info.sheet.zh_data[info.row];
+                if (!node) return;
+
+                switch (col.field) {
+                    case 'name':
+                    case 'spec':
+                    case 'unit':
+                    case 'tax':
+                    case 'arrive_qty':
+                    case 'arrive_tp':
+                    case 'arrive_time':
+                    case 'source':
+                    case 'bills_code':
+                    case 'location':
+                    case 'prepare_pos':
+                        info.cancel = readOnly || node.add_sid !== stageId;
+                        break;
+                }
+            },
+            clipboardPasting(e, info) {
+                const setting = info.sheet.zh_setting, sortData = info.sheet.zh_data;
+                info.cancel = true;
+
+                if (!setting || !sortData) return;
+                const pasteData = info.pasteData.html
+                    ? SpreadJsObj.analysisPasteHtml(info.pasteData.html)
+                    : (info.pasteData.text === ''
+                        ? SpreadJsObj.Clipboard.getAnalysisPasteText()
+                        : SpreadJsObj.analysisPasteText(info.pasteData.text));
+                const hint = {
+                    name: {type: 'warning', msg: '材料名称不可为空,已过滤'},
+                    tax: {type: 'warning', msg: '输入的 税率 非法,已过滤'},
+                    arrive: {type: 'warning', msg: '输入的 到场数量/金额 非法,已过滤'},
+                    qty: {type: 'warning', msg: '输入的 本期计量-数量 非法,已过滤'},
+                };
+
+                const uDatas = [], iDatas = [];
+                const maxOrder = yjclObj.getMaxOrder();
+                for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                    const curRow = info.cellRange.row + iRow;
+                    const node = sortData[curRow];
+
+                    let bPaste = false;
+                    const data = {};
+                    for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
+                        const curCol = info.cellRange.col + iCol;
+                        const colSetting = setting.cols[curCol];
+                        const value = trimInvalidChar(pasteData[iRow][iCol]);
+
+                        if (colSetting.field === 'name' && (!value || value === '')) {
+                            toastMessageUniq(hint.name);
+                            break;
+                        }
+                        if (colSetting.type === 'Number') {
+                            const num = _.toNumber(value);
+                            if (num) {
+                                data[colSetting.field] = num;
+                                bPaste = true;
+                            }
+                        } else {
+                            data[colSetting.field] = value;
+                            bPaste = true;
+                        }
+                    }
+                    if (bPaste) {
+                        if (node) {
+                            data.id = node.id;
+                            uDatas.push(data);
+                        } else {
+                            data.m_order = maxOrder + iDatas.length + 1;
+                            iDatas.push(data);
+                        }
+                    }
+                }
+                const updateData = {};
+                if (uDatas.length > 0) updateData.update = uDatas;
+                if (iDatas.length > 0) updateData.add = iDatas;
+                if (uDatas.length > 0 || iDatas.length > 0) {
+                    postData(window.location.pathname + '/update', updateData, function (result) {
+                        yjclObj.loadUpdateData(result);
+                        SpreadJsObj.reLoadSheetData(info.sheet);
+                    });
+                } else {
+                    SpreadJsObj.reLoadSheetData(info.sheet);
+                }
+            },
+            upMove: function () {
+                const sels = yjclSheet.getSelections(), sortData = yjclSheet.zh_data;
+                const node = sortData[sels[0].row];
+                const preNode = sortData[sels[0].row - 1];
+                const data = [
+                    { id: node.id, m_order: preNode.m_order },
+                    { id: preNode.id, m_order: node.m_order }
+                ];
+                postData(window.location.pathname + '/update', {update: data}, function (result) {
+                    yjclObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadRowsData(yjclSheet, [sels[0].row, sels[0].row - 1]);
+                    yjclSheet.setSelection(sels[0].row - 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
+                });
+            },
+            downMove: function () {
+                const sels = yjclSheet.getSelections(), sortData = yjclSheet.zh_data;
+                const node = sortData[sels[0].row];
+                const nextNode = sortData[sels[0].row + 1];
+                const data = [
+                    {id: node.id, m_order: nextNode.m_order},
+                    {id: nextNode.id, m_order: node.m_order}
+                ];
+                postData(window.location.pathname + '/update', {update: data}, function (result) {
+                    yjclObj.loadUpdateData(result);
+                    SpreadJsObj.reLoadRowsData(yjclSheet, [sels[0].row, sels[0].row + 1]);
+                    yjclSheet.setSelection(sels[0].row + 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
+                });
+            }
+        };
+        yjclSheet.bind(spreadNS.Events.EditEnded, yjclOprObj.editEnded);
+        yjclSheet.bind(spreadNS.Events.EditStarting, yjclOprObj.editStarting);
+        yjclSheet.bind(spreadNS.Events.ClipboardPasting, yjclOprObj.clipboardPasting);
+        SpreadJsObj.addDeleteBind(yjclSpread, yjclOprObj.deletePress);
+        $.contextMenu({
+            selector: '#yjcl-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, yjclSpread);
+                return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+            },
+            items: {
+                del: {
+                    name: '删除',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        yjclOprObj.delete(yjclSheet);
+                    },
+                    disabled: function (key, opt) {
+                        const sels = yjclSheet.getSelections();
+                        if (!sels || !sels[0]) return true;
+
+                        const row = sels[0].row;
+                        const node = yjclObj.data[row];
+                        return node === undefined || node === null;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                },
+                sprDel: '------------',
+                upMove: {
+                    name: '上移',
+                    icon: 'fa-arrow-up',
+                    callback: function (key, opt) {
+                        yjclOprObj.upMove();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = yjclSheet.getSelections();
+                        if (!sels || !sels[0] || sels[0].row === 0) return true;
+
+                        const row = sels[0].row;
+                        const node = yjclObj.data[row];
+                        return node === undefined || node === null;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                },
+                downMove: {
+                    name: '下移',
+                    icon: 'fa-arrow-down',
+                    callback: function (key, opt) {
+                        yjclOprObj.downMove();
+                    },
+                    disabled: function (key, opt) {
+                        const sels = yjclSheet.getSelections();
+                        if (!sels || !sels[0] || sels[0].row >= yjclObj.data.length - 1) return true;
+
+                        const row = sels[0].row;
+                        const node = yjclObj.data[row];
+                        return node === undefined || node === null;
+                    },
+                    visible: function (key, opt) {
+                        return !readOnly;
+                    }
+                }
+            },
+        })
+    }
+
+    $('#exportExcel').click(function () {
+        SpreadExcelObj.exportSimpleXlsxSheet(spreadSetting, yjclObj.data, $('.sidebar-title').attr('data-original-title') + "-永久材料.xlsx");
+    });
+});

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

@@ -521,6 +521,7 @@ const SpreadJsObj = {
             data.waitingLoading = true;
             return;
         }
+        let autoFit = false;
         sheet.zh_setting.cols.forEach(function (col, j) {
             const cell = sheet.getCell(row, j);
             if (col.getValue && Object.prototype.toString.apply(col.getValue) === "[object Function]") {
@@ -567,8 +568,13 @@ const SpreadJsObj = {
             cell.foreColor(SpreadJsObj._getForeColor(sheet, data, row, col));
 
             cell.setBorder(sheet.borderLine, {all: true});
+            if (col.wordWrap) {
+                cell.wordWrap(true);
+                autoFit = true;
+            }
             data.waitingLoading = false;
         });
+        if (autoFit) sheet.autoFitRow(row);
     },
     _addActivePaintEvents: function (sheet, cellType) {
         if (!sheet.ActiveType) {

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

@@ -130,7 +130,7 @@ function getAllList(currPageNum = 1) {
         <td>
         <div class="d-flex">
             <a href="javascript:void(0)" class="pl-0 col-10 att-file-name" file-id=${att.id}>${att.filename}${att.fileext}</a>
-            <div class="att-file-btn col-2"><a href="/tender/${tender.id}/ledger/download/file/${att.id}" class="pl-0"><i class="fa fa-download"></i></a>${delHtml}</div>
+            <div class="att-file-btn col-2"><a href="/tender/${tender.id}/measure/stage/${stage.order}/download/file/${att.id}" class="pl-0"><i class="fa fa-download"></i></a>${delHtml}</div>
         </div>
         </td><td>${att.username}</td></tr>`
     }
@@ -154,7 +154,7 @@ function getNodeList(node) {
             <td>
             <div class="d-flex">
                 <a href="javascript:void(0)" class="pl-0 col-10 att-file-name" file-id=${att.id}>${att.filename}${att.fileext}</a>
-                <div class="att-file-btn col-2"><a href="/tender/${tender.id}/ledger/download/file/${att.id}" class="pl-0"><i class="fa fa-download"></i></a>${delHtml}</div>
+                <div class="att-file-btn col-2"><a href="/tender/${tender.id}/measure/stage/${stage.order}/download/file/${att.id}" class="pl-0"><i class="fa fa-download"></i></a>${delHtml}</div>
             </div>
             </td><td>${att.username}</td></tr>`
         }

+ 9 - 1
app/router.js

@@ -252,6 +252,7 @@ module.exports = app => {
     // 台账审批相关
     app.post('/tender/:id/ledger/audit/add', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.add');
     app.post('/tender/:id/ledger/audit/delete', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.remove');
+    app.post('/tender/:id/ledger/audit/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'ledgerAuditController.saveAudit');
     app.post('/tender/:id/ledger/audit/start', sessionAuth, tenderCheck, uncheckTenderCheck, ledgerAuditCheck, tenderBuildCheck, 'ledgerAuditController.start');
     app.post('/tender/:id/ledger/audit/check', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'ledgerAuditController.check');
     app.post('/tender/:id/ledger/audit/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, 'ledgerAuditController.checkAgain');
@@ -406,6 +407,10 @@ module.exports = app => {
     app.get('/tender/:id/measure/stage/:order/extra/jgcl', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.jgcl');
     app.post('/tender/:id/measure/stage/:order/extra/jgcl/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadJgcl');
     app.post('/tender/:id/measure/stage/:order/extra/jgcl/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateJgcl');
+    // 永久材料
+    app.get('/tender/:id/measure/stage/:order/extra/yjcl', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.yjcl');
+    app.post('/tender/:id/measure/stage/:order/extra/yjcl/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadYjcl');
+    app.post('/tender/:id/measure/stage/:order/extra/yjcl/update', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.updateYjcl');
     // 奖罚金
     app.get('/tender/:id/measure/stage/:order/extra/bonus', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.bonus');
     app.post('/tender/:id/measure/stage/:order/extra/bonus/load', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageExtraController.loadBonus');
@@ -745,8 +750,11 @@ 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', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.changeIndex');
     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');
+    app.get('/wap/tender/:id/change/project/:cpid/information', sessionAuth, tenderCheck, uncheckTenderCheck, changeProjectCheck, changeProjectAuditCheck, 'wapController.changeProject');
+    app.get('/wap/tender/:id/change/apply/:caid/information', sessionAuth, tenderCheck, uncheckTenderCheck, changeApplyCheck, changeApplyAuditCheck, 'wapController.changeApply');
+    app.get('/wap/tender/:id/change/plan/:cpid/information', sessionAuth, tenderCheck, uncheckTenderCheck, changePlanCheck, changePlanAuditCheck, 'wapController.changePlan');
 
     // 微信
     app.get('/wx', 'wechatController.index');

+ 21 - 17
app/service/change.js

@@ -840,28 +840,31 @@ module.exports = app => {
          * @param {int} order_by - 表单提交的数据
          * @return {void}
          */
-        async saveOrderBy(order_by, newLedgerList = []) {
+        async saveOrderBy(order_by, updateOrderList) {
             const transaction = await this.db.beginTransaction();
             let result = [];
             try {
                 const postData = { order_by };
-                let changeList = await this.ctx.service.changeAuditList.getList(this.ctx.change.cid);
-                if (order_by) {
-                    let i = 1;
-                    const updateArray = [];
-                    for (const cl of changeList) {
-                        updateArray.push({
-                            id: cl.id,
-                            order: i,
-                        });
-                        cl.order = i;
-                        i++;
-                    }
-                    if (updateArray.length > 0) await transaction.updateRows(this.ctx.service.changeAuditList.tableName, updateArray);
-                } else {
-                    await this.ctx.service.changeAuditList.saveLedgerListDatas(newLedgerList, null, order_by);
-                    changeList = await this.ctx.service.changeAuditList.getList(this.ctx.change.cid, order_by);
+                if (updateOrderList.length > 0) {
+                    await transaction.updateRows(this.ctx.service.changeAuditList.tableName, updateOrderList);
                 }
+                // let changeList = await this.ctx.service.changeAuditList.getList(this.ctx.change.cid);
+                // if (order_by) {
+                //     let i = 1;
+                //     const updateArray = [];
+                //     for (const cl of changeList) {
+                //         updateArray.push({
+                //             id: cl.id,
+                //             order: i,
+                //         });
+                //         cl.order = i;
+                //         i++;
+                //     }
+                //     if (updateArray.length > 0) await transaction.updateRows(this.ctx.service.changeAuditList.tableName, updateArray);
+                // } else {
+                //     // await this.ctx.service.changeAuditList.saveLedgerListDatas(newLedgerList, null, order_by);
+                //     changeList = await this.ctx.service.changeAuditList.getList(this.ctx.change.cid);
+                // }
                 const options = {
                     where: {
                         cid: this.ctx.change.cid,
@@ -869,6 +872,7 @@ module.exports = app => {
                 };
                 await transaction.update(this.tableName, postData, options);
                 await transaction.commit();
+                const changeList = await this.ctx.service.changeAuditList.getList(this.ctx.change.cid, order_by);
                 result = { changeList,
                     usedList: await this.ctx.service.stageChange.getAllFinalUsedData(this.ctx.tender.id, this.ctx.change.cid) };
             } catch (error) {

+ 48 - 0
app/service/change_apply_audit.js

@@ -347,8 +347,13 @@ module.exports = app => {
                     id: caId, status: auditConst.status.checking,
                 });
                 // 微信模板通知
+                const shenpiUrl = await this.ctx.helper.urlToShort(
+                    this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/apply/' + caId + '/information#shenpi'
+                );
+                // 微信模板通知
                 const wechatData = {
                     type: 'apply',
+                    wap_url: shenpiUrl,
                     status: wxConst.status.check,
                     tips: wxConst.tips.check,
                     code: this.ctx.session.sessionProject.code,
@@ -534,8 +539,13 @@ module.exports = app => {
                             id: caId, status: auditConst.status.checking,
                         });
                         // 微信模板通知
+                        const shenpiUrl = await this.ctx.helper.urlToShort(
+                            this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/apply/' + caId + '/information#shenpi'
+                        );
+                        // 微信模板通知
                         const wechatData = {
                             type: 'apply',
+                            wap_url: shenpiUrl,
                             status: wxConst.status.check,
                             tips: wxConst.tips.check,
                             code: this.ctx.session.sessionProject.code,
@@ -568,8 +578,13 @@ module.exports = app => {
                         });
                         // 微信模板通知
                         const users = this._.uniq(this._.concat(this._.map(auditors, 'aid'), this.ctx.change.uid));
+                        // 微信模板通知
+                        const shenpiUrl = await this.ctx.helper.urlToShort(
+                            this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/apply/' + caId + '/information#shenpi'
+                        );
                         const wechatData = {
                             type: 'apply',
+                            wap_url: shenpiUrl,
                             status: wxConst.status.success,
                             tips: wxConst.tips.success,
                             code: this.ctx.session.sessionProject.code,
@@ -640,8 +655,13 @@ module.exports = app => {
                 await transaction.insert(this.tableName, newAuditors);
                 // 微信模板通知
                 const users = this._.uniq(this._.concat(this._.map(auditors, 'aid'), this.ctx.change.uid));
+                // 微信模板通知
+                const shenpiUrl = await this.ctx.helper.urlToShort(
+                    this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/apply/' + caId + '/information#shenpi'
+                );
                 const wechatData = {
                     type: 'apply',
+                    wap_url: shenpiUrl,
                     status: wxConst.status.back,
                     tips: wxConst.tips.back,
                     code: this.ctx.session.sessionProject.code,
@@ -1357,6 +1377,34 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        /**
+         * 取待审批期列表(wap用)
+         *
+         * @param auditorId
+         * @return {Promise<*>}
+         */
+        async getAuditChangeApplyByWap(auditorId) {
+            const sql =
+                'SELECT sa.`aid`, sa.`times`, sa.`begin_time`, sa.`end_time`, sa.`tid`, sa.`caid`,' +
+                '    s.*,' +
+                '    t.`name` as `t_name`, t.`project_id`, t.`type`, t.`user_id`,' +
+                '    ti.`deal_info`, ti.`decimal` ' +
+                '  FROM ?? AS sa' +
+                '    Left Join ?? AS s On sa.`caid` = s.`id`' +
+                '    Left Join ?? As t On sa.`tid` = t.`id`' +
+                '    Left Join ?? AS ti ON ti.`tid` = t.`id`' +
+                '  WHERE sa.`aid` = ? and sa.`status` = ?';
+            const sqlParam = [
+                this.tableName,
+                this.ctx.service.changeApply.tableName,
+                this.ctx.service.tender.tableName,
+                this.ctx.service.tenderInfo.tableName,
+                auditorId,
+                auditConst.status.checking,
+            ];
+            return await this.db.query(sql, sqlParam);
+        }
     }
 
     return ChangeApplyAudit;

+ 2 - 0
app/service/change_audit_list.js

@@ -107,6 +107,7 @@ module.exports = app => {
                     xmj_fbgc: null,
                     xmj_fxgc: null,
                     gcl_id: '',
+                    mx_id: '',
                     order,
                     is_valuation: 1,
                     delimit,
@@ -219,6 +220,7 @@ module.exports = app => {
                         xmj_fbgc: null,
                         xmj_fxgc: null,
                         gcl_id: '',
+                        mx_id: '',
                         order: order ? order + i : null,
                         is_valuation: 1,
                         delimit,

+ 48 - 0
app/service/change_project_audit.js

@@ -355,8 +355,12 @@ module.exports = app => {
                     id: cpId, status: auditConst.status.checking,
                 });
                 // 微信模板通知
+                const shenpiUrl = await this.ctx.helper.urlToShort(
+                    this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/project/' + cpId + '/information#shenpi'
+                );
                 const wechatData = {
                     type: 'project',
+                    wap_url: shenpiUrl,
                     status: wxConst.status.check,
                     tips: wxConst.tips.check,
                     code: this.ctx.session.sessionProject.code,
@@ -557,8 +561,12 @@ module.exports = app => {
                         });
 
                         // 微信模板通知
+                        const shenpiUrl = await this.ctx.helper.urlToShort(
+                            this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/project/' + cpId + '/information#shenpi'
+                        );
                         const wechatData = {
                             type: 'project',
+                            wap_url: shenpiUrl,
                             status: wxConst.status.check,
                             tips: wxConst.tips.check,
                             code: this.ctx.session.sessionProject.code,
@@ -589,8 +597,12 @@ module.exports = app => {
 
                         // 微信模板通知
                         const users = this._.uniq(this._.map(auditors, 'aid'));
+                        const shenpiUrl = await this.ctx.helper.urlToShort(
+                            this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/project/' + cpId + '/information#shenpi'
+                        );
                         const wechatData = {
                             type: 'project',
+                            wap_url: shenpiUrl,
                             status: wxConst.status.success,
                             tips: wxConst.tips.success,
                             code: this.ctx.session.sessionProject.code,
@@ -662,8 +674,12 @@ module.exports = app => {
                 await transaction.insert(this.tableName, newAuditors);
                 // 微信模板通知
                 const users = this._.uniq(this._.concat(this._.map(auditors, 'aid'), this.ctx.change.uid));
+                const shenpiUrl = await this.ctx.helper.urlToShort(
+                    this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/project/' + cpId + '/information#shenpi'
+                );
                 const wechatData = {
                     type: 'project',
+                    wap_url: shenpiUrl,
                     status: wxConst.status.back,
                     tips: wxConst.tips.back,
                     code: this.ctx.session.sessionProject.code,
@@ -726,8 +742,12 @@ module.exports = app => {
 
                 // 微信模板通知
                 const users = this._.uniq(this._.concat(this._.map(auditors, 'aid'), this.ctx.change.uid));
+                const shenpiUrl = await this.ctx.helper.urlToShort(
+                    this.ctx.protocol + '://' + this.ctx.host + '/wap/tender/' + this.ctx.tender.id + '/change/project/' + cpId + '/information#shenpi'
+                );
                 const wechatData = {
                     type: 'project',
+                    wap_url: shenpiUrl,
                     status: wxConst.status.stop,
                     tips: wxConst.tips.stop,
                     code: this.ctx.session.sessionProject.code,
@@ -1493,6 +1513,34 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        /**
+         * 取待审批期列表(wap用)
+         *
+         * @param auditorId
+         * @return {Promise<*>}
+         */
+        async getAuditChangeProjectByWap(auditorId) {
+            const sql =
+                'SELECT sa.`aid`, sa.`times`, sa.`begin_time`, sa.`end_time`, sa.`tid`, sa.`cpid`,' +
+                '    s.*,' +
+                '    t.`name` as `t_name`, t.`project_id`, t.`type`, t.`user_id`,' +
+                '    ti.`deal_info`, ti.`decimal` ' +
+                '  FROM ?? AS sa' +
+                '    Left Join ?? AS s On sa.`cpid` = s.`id`' +
+                '    Left Join ?? As t On sa.`tid` = t.`id`' +
+                '    Left Join ?? AS ti ON ti.`tid` = t.`id`' +
+                '  WHERE sa.`aid` = ? and sa.`status` = ?';
+            const sqlParam = [
+                this.tableName,
+                this.ctx.service.changeProject.tableName,
+                this.ctx.service.tender.tableName,
+                this.ctx.service.tenderInfo.tableName,
+                auditorId,
+                auditConst.status.checking,
+            ];
+            return await this.db.query(sql, sqlParam);
+        }
     }
 
     return ChangeProjectAudit;

+ 72 - 3
app/service/ledger_audit.js

@@ -605,13 +605,13 @@ module.exports = app => {
          * @param {Number} times 审核次数
          * @return {Promise<Array>} 查询结果集
          */
-        async getAuditGroupByList(tender_id, times = 1) {
+        async getAuditGroupByList(tender_id, times = 1, transaction = null) {
             const sql =
-                'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`tender_id`, la.`audit_order` ' +
+                'SELECT la.`audit_id`, la.`status`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`tender_id`, la.`audit_order` ' +
                 '  FROM ?? AS la Left Join ?? AS pa On la.`audit_id` = pa.`id`' +
                 '  WHERE la.`tender_id` = ? and la.`times` = ? GROUP BY la.`audit_id` ORDER BY la.`audit_order`';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, tender_id, times];
-            return await this.db.query(sql, sqlParam);
+            return transaction ? await transaction.query(sql, sqlParam) : await this.db.query(sql, sqlParam);
         }
 
         /**
@@ -682,6 +682,75 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        /**
+         * 删除本次审批流程
+         * @param {Number} stageId - 标段id
+         * @param {Number} times - 第几次审批
+         * @param {Object} data - 更改参数
+         * @return {Promise<void>}
+         */
+        async saveAudit(tenderId, times, data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const auditors = await this.getAuditGroupByList(tenderId, times);
+                const now_audit = this._.find(auditors, { audit_id: data.old_aid });
+                if (data.operate === 'add') {
+                    if (now_audit.status !== auditConst.status.uncheck && now_audit.status !== auditConst.status.checking) {
+                        throw '当前人下无法操作新增';
+                    }
+                    const newAudit = {
+                        tender_id: tenderId,
+                        audit_id: data.new_aid,
+                        audit_order: now_audit.audit_order + 1,
+                        times,
+                        status: auditConst.status.uncheck,
+                    };
+                    // order+1
+                    await this._syncOrderByDelete(transaction, tenderId, now_audit.audit_order + 1, times, '+');
+                    await transaction.insert(this.tableName, newAudit);
+                    // 更新审批流程页数据,如果存在
+                } else if (data.operate === 'del') {
+                    if (now_audit.status !== auditConst.status.uncheck) {
+                        throw '当前人无法操作删除';
+                    }
+                    await transaction.delete(this.tableName, { tender_id: tenderId, times, audit_id: now_audit.audit_id, audit_order: now_audit.audit_order });
+                    await this._syncOrderByDelete(transaction, tenderId, now_audit.audit_order, times);
+                    // // 旧的更新为is_old为1
+                    // await transaction.update(this.tableName, { is_old: 1 }, {
+                    //     where: {
+                    //         sid: stageId,
+                    //         times,
+                    //         aid: data.old_aid,
+                    //     }
+                    // });
+                } else if (data.operate === 'change') {
+                    const nowAudit = await this.getDataByCondition({ tender_id: tenderId, times, audit_id: now_audit.audit_id, audit_order: now_audit.audit_order });
+                    if (now_audit.status !== auditConst.status.uncheck || !nowAudit) {
+                        throw '当前人无法操作替换';
+                    }
+                    nowAudit.audit_id = data.new_aid;
+                    await transaction.update(this.tableName, nowAudit);
+                    // 旧的更新为is_old为1
+                    // await transaction.update(this.tableName, { is_old: 1 }, {
+                    //     where: {
+                    //         sid: stageId,
+                    //         times,
+                    //         aid: data.old_aid,
+                    //     }
+                    // });
+                }
+                if (this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdspl || this.ctx.tender.info.shenpi.ledger === shenpiConst.sp_status.gdzs) {
+                    const newAuditors = await this.getAuditGroupByList(tenderId, times, transaction);
+                    await this.ctx.service.shenpiAudit.updateAuditList(transaction, this.ctx.tender.id, this.ctx.tender.info.shenpi.ledger, shenpiConst.sp_type.ledger, this._.map(newAuditors, 'audit_id'));
+                }
+                // 更新到审批流程方法
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
 
     return LedgerAudit;

+ 3 - 0
app/service/report_memory.js

@@ -927,6 +927,8 @@ module.exports = app => {
                 for (const d of changeBills) {
                     d.o_qty = d.oamount;
                     d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+                    d.o_qty2 = d.oamount2;
+                    d.o_tp2 = this.ctx.helper.mul(d.o_qty2, d.unit_price, decimal.tp);
                     d.c_qty = d.camount;
                     d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
                     d.s_qty = d.samount ? parseFloat(d.samount) : 0;
@@ -1033,6 +1035,7 @@ module.exports = app => {
                     const bills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: c.cid } });
                     for (const b of bills) {
                         b.o_qty = b.oamount;
+                        d.o_qty2 = d.oamount2;
                         b.c_qty = b.camount;
                         b.s_qty = b.samount ? parseFloat(b.samount) : 0;
                         b.sp_qty = b.spamount;

+ 2 - 0
app/service/rpt_gather_memory.js

@@ -1299,6 +1299,8 @@ module.exports = app => {
                     d.tender_name = tender.name;
                     d.o_qty = d.oamount;
                     d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+                    d.o_qty2 = d.oamount2;
+                    d.o_tp2 = this.ctx.helper.mul(d.o_qty2, d.unit_price, decimal.tp);
                     d.c_qty = d.camount;
                     d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
                     d.s_qty = d.samount ? parseFloat(d.samount) : 0;

+ 2 - 0
app/service/stage.js

@@ -570,6 +570,8 @@ module.exports = app => {
                 if (preCheckedStage) {
                     const jgclResult = await this.ctx.service.stageJgcl.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!jgclResult) throw '初始化甲供材料数据失败';
+                    const yjclResult = await this.ctx.service.stageYjcl.addInitialStageData(newStage, preCheckedStage, transaction);
+                    if (!yjclResult) throw '初始化甲供材料数据失败';
                     const otherResult = await this.ctx.service.stageOther.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!otherResult) throw '初始化其他台账数据失败';
                     const safeResult = await this.ctx.service.stageSafeProd.addInitialStageData(newStage, preCheckedStage, transaction);

+ 10 - 0
app/service/stage_audit.js

@@ -328,6 +328,7 @@ module.exports = app => {
                 // 复制一份下一审核人数据
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, 1, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageYjcl.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -498,6 +499,7 @@ module.exports = app => {
                         // 复制一份下一审核人数据
                         await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, nextAudits[0].order, transaction);
                         await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                        await this.ctx.service.stageYjcl.updateHistory(this.ctx.stage, transaction);
                         await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                         await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                         await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -576,6 +578,7 @@ module.exports = app => {
                                 await this.ctx.service.stageOther.addInitialStageData(ns, this.ctx.stage, transaction);
                                 await this.ctx.service.stageSafeProd.addInitialStageData(ns, this.ctx.stage, transaction);
                                 await this.ctx.service.stageJgcl.addInitialStageData(ns, this.ctx.stage, transaction);
+                                await this.ctx.service.stageYjcl.addInitialStageData(ns, this.ctx.stage, transaction);
                                 await this.ctx.service.stageTempLand.addInitialStageData(ns, this.ctx.stage, transaction);
                             }
                             const preStageTp = {
@@ -727,6 +730,7 @@ module.exports = app => {
                 // 复制一份最新数据给原报
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times + 1, 0, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageYjcl.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -881,6 +885,7 @@ module.exports = app => {
                 // 复制一份最新数据给下一人
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, selfAudit.order + 1, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
+                await this.ctx.service.stageYjcl.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory(this.ctx.stage, transaction);
@@ -1037,6 +1042,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, finalAudit.order + 1, transaction);
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, finalAudit.order + 2, transaction);
                 await this.ctx.service.stageJgcl.updateHistory4CheckAgain(this.ctx.stage, transaction);
+                await this.ctx.service.stageYjcl.updateHistory4CheckAgain(this.ctx.stage, transaction);
                 await this.ctx.service.stageBonus.updateHistory4CheckAgain(this.ctx.stage, transaction);
                 await this.ctx.service.stageOther.updateHistory4CheckAgain(this.ctx.stage, transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4CheckAgain(this.ctx.stage, transaction);
@@ -1276,6 +1282,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(stage, stage.times, selfAuditor.order + 2, transaction, stage.times, selfAuditor.order + 1);
                 // 其他台账明细:更新两份历史数据
                 await this.ctx.service.stageJgcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
+                await this.ctx.service.stageYjcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageBonus.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageOther.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
@@ -1366,6 +1373,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.copyAuditStagePays(stage, stage.times, selfAuditor.order + 2, transaction, stage.times, selfAuditor.order + 1);
                 // 其他台账明细:更新一份历史数据
                 await this.ctx.service.stageJgcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
+                await this.ctx.service.stageYjcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageBonus.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageOther.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
@@ -1468,6 +1476,7 @@ module.exports = app => {
                 await this.ctx.service.stagePay.deleteAuditStagePays(stage, stage.times, 0, transaction);
                 // 其他台账明细:更新一份历史数据
                 await this.ctx.service.stageJgcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
+                await this.ctx.service.stageYjcl.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageBonus.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageOther.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
                 await this.ctx.service.stageSafeProd.updateHistory4TimesOrder(stage, stage.times, [selfAuditor.order + 1], transaction);
@@ -1861,6 +1870,7 @@ module.exports = app => {
             await transaction.delete(this.ctx.service.stageAuditAss.tableName, { sid, times });
             // 其他台账
             await this.ctx.service.stageJgcl.deleteStageTimesData(sid, times, transaction);
+            await this.ctx.service.stageYjcl.deleteStageTimesData(sid, times, transaction);
             await this.ctx.service.stageOther.deleteStageTimesData(sid, times, transaction);
             await this.ctx.service.stageBonus.deleteStageTimesData(sid, times, transaction);
             await this.ctx.service.stageSafeProd.deleteStageTimesData(sid, times, transaction);

+ 264 - 0
app/service/stage_yjcl.js

@@ -0,0 +1,264 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const auditConst = require('../const/audit').stage;
+const decimal = { up: 6, qty: 3 };
+
+module.exports = app => {
+    class StageYjcl extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'stage_yjcl';
+        }
+
+        async getStageData(stage) {
+            const data = await this.getAllDataByCondition({ where: { sid: stage.id } });
+            if (!stage.readOnly || stage.status === auditConst.status.checked) return data;
+
+            for (const d of data) {
+                const his = d.shistory ? JSON.parse(d.shistory) : [];
+
+                const h = this.ctx.helper._.find(his, {
+                    stimes: stage.curTimes, sorder: stage.curOrder,
+                });
+                d.qty = h ? h.qty : 0;
+                d.tp = h ? h.tp : 0;
+            }
+            return data;
+        }
+
+        async _addDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
+            const datas = data instanceof Array ? data : [data];
+            const insertData = [];
+            for (const d of datas) {
+                if (!d.name || !d.m_order) throw '新增永久材料,提交的数据错误';
+                const nd = {
+                    uuid: this.uuid.v4(),
+                    add_sid: this.ctx.stage.id,
+                    add_sorder: this.ctx.stage.order,
+                    add_uid: this.ctx.session.sessionUser.accountId,
+                    tid: this.ctx.tender.id,
+                    sid: this.ctx.stage.id,
+                    sorder: this.ctx.stage.order,
+                };
+                nd.name = d.name;
+                nd.m_order = d.m_order;
+                nd.spec = d.spec || '';
+                nd.unit = d.unit || '';
+                nd.tax = d.tax ? this.ctx.helper.round(d.tax, 0) : 0;
+                nd.arrive_time = d.arrive_time || '';
+                nd.source = d.source || '';
+                nd.bills_code = d.bills_code || '';
+                nd.location = d.location || '';
+                nd.prepare_pos = d.prepare_pos || '';
+                nd.memo = d.memo || '';
+                const extraPre = 1 + this.ctx.helper.div(nd.tax, 100, 2);
+                nd.arrive_qty = d.arrive_qty ? this.ctx.helper.round(d.arrive_qty, decimal.qty) : 0;
+                nd.arrive_tp = d.arrive_tp ? this.ctx.helper.round(d.arrive_tp, tpDecimal) : 0;
+                nd.unit_price = d.arrive_qty ? this.ctx.helper.div(d.arrive_tp, d.arrive_qty, decimal.up) : 0;
+                nd.ex_tax_up = d.arrive_qty ? this.ctx.helper.div(this.ctx.helper.div(d.arrive_tp, d.arrive_qty), extraPre, decimal.up) : 0;
+                // nd.unit_price = d.unit_price ? this.ctx.helper.round(d.unit_price, decimal.up) : 0;
+                // const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, d.unit);
+                // if (d.arrive_qty) {
+                //     nd.arrive_qty = this.ctx.helper.round(d.arrive_qty, decimal.qty);
+                //     nd.arrive_tp = this.ctx.helper.mul(this.ctx.helper.mul(nd.unit_price, nd.arrive_qty), extraPre, tpDecimal);
+                // }
+                nd.qty = d.qty ? this.ctx.helper.round(d.qty, decimal.qty) : 0;
+                // nd.tp = this.ctx.helper.mul(this.ctx.helper.mul(nd.unit_price, nd.qty), extraPre, tpDecimal);
+                nd.tp = this.ctx.helper.mul(nd.unit_price, nd.qty, tpDecimal);
+                insertData.push(nd);
+            }
+            await this.db.insert(this.tableName, insertData);
+            return await this.getAllDataByCondition({
+                where: { sid: this.ctx.stage.id, uuid: this.ctx.helper._.map(insertData, 'uuid') },
+            });
+        }
+
+        async _delDatas(data) {
+            const datas = data instanceof Array ? data : [data];
+            const orgDatas = await this.getAllDataByCondition({
+                where: { sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id') },
+            });
+            for (const od of orgDatas) {
+                if (od.pre_used) throw '永久材料往期已经计量,不可删除';
+            }
+            await this.db.delete(this.tableName, { id: datas });
+            return datas;
+        }
+
+        async _updateDatas(data) {
+            const tpDecimal = this.ctx.tender.info.decimal.extra
+                ? this.ctx.tender.info.decimal.extraTp
+                : this.ctx.tender.info.decimal.tp;
+
+            const datas = data instanceof Array ? data : [data];
+            const orgDatas = await this.getAllDataByCondition({
+                where: { sid: this.ctx.stage.id, id: this.ctx.helper._.map(datas, 'id') },
+            });
+
+            const uDatas = [];
+            for (const d of datas) {
+                const od = this.ctx.helper._.find(orgDatas, { id: d.id });
+                if (!od) continue;
+
+                const nd = { id: od.id };
+                if (d.name !== undefined) nd.name = d.name;
+                if (d.m_order !== undefined) nd.m_order = d.m_order;
+                if (d.spec !== undefined) nd.spec = d.spec || '';
+                if (d.unit !== undefined) nd.unit = d.unit || '';
+                if (d.tax !== undefined) nd.tax = this.ctx.helper.round(d.tax, 0);
+
+                if (d.arrive_time !== undefined) nd.arrive_time = d.arrive_time || '';
+                if (d.source !== undefined) nd.source = d.source || '';
+                if (d.bills_code !== undefined) nd.bills_code = d.bills_code || '';
+                if (d.location !== undefined) nd.location = d.location || '';
+                if (d.prepare_pos !== undefined) nd.prepare_pos = d.prepare_pos || '';
+                if (d.memo !== undefined)nd.memo = d.memo || '';
+
+                if (d.arrive_qty !== undefined) nd.arrive_qty = this.ctx.helper.round(d.arrive_qty, decimal.qty);
+                if (d.arrive_tp !== undefined) nd.arrive_tp = this.ctx.helper.round(d.arrive_tp, tpDecimal);
+                let unit_price = od.unit_price, ex_tax_up = od.ex_tax_up;
+                if (nd.arrive_qty !== undefined || nd.arrive_tp !== undefined || nd.tax !== undefined) {
+                    const tp = nd.arrive_tp !== undefined ? nd.arrive_tp : od.arrive_tp;
+                    const qty = nd.arrive_qty !== undefined ? nd.arrive_qty : od.arrive_qty;
+                    const extraPre = nd.tax !== undefined ? 1 + this.ctx.helper.div(nd.tax, 100, 2) : 1 + this.ctx.helper.div(od.tax, 100, 2);
+                    nd.unit_price = qty ? this.ctx.helper.div(tp, qty, decimal.up) : 0;
+                    nd.ex_tax_up = qty ? this.ctx.helper.div(this.ctx.helper.div(tp, qty), extraPre, decimal.up) : 0;
+                    unit_price = nd.unit_price;
+                    ex_tax_up = nd.ex_tax_up;
+                }
+                if (d.qty !== undefined) {
+                    nd.qty = d.qty ? this.ctx.helper.round(d.qty, decimal.qty) : 0;
+                } else if (nd.unit_price) {
+                    nd.qty = od.qty;
+                }
+                if (nd.qty !== undefined) nd.tp = this.ctx.helper.mul(unit_price, nd.qty, tpDecimal);
+                uDatas.push(nd);
+            }
+            if (uDatas.length > 0) {
+                await this.db.updateRows(this.tableName, uDatas);
+                return uDatas;
+            } else {
+                return [];
+            }
+        }
+
+        async updateDatas(data) {
+            const result = { add: [], del: [], update: [] };
+            try {
+                if (data.add) {
+                    result.add = await this._addDatas(data.add);
+                }
+                if (data.update) {
+                    result.update = await this._updateDatas(data.update);
+                }
+                if (data.del) {
+                    result.del = await this._delDatas(data.del);
+                }
+                return result;
+            } catch (err) {
+                if (err) result.err = err;
+                return result;
+            }
+        }
+
+        async updateHistory4TimesOrder(stage, times, order, transaction) {
+            const datas = await this.getStageData(stage);
+            if (datas.length === 0) return;
+
+            const updateDatas = [];
+            for (const d of datas) {
+                for (const curOrder of order) {
+                    const history = d.shistory ? JSON.parse(d.shistory) : [];
+                    const his = history.find(function (x) {
+                        return x.stimes === times && x.sorder === curOrder;
+                    });
+                    if (his) {
+                        his.qty = d.qty;
+                        his.tp = d.tp;
+                    } else {
+                        history.push({ stimes: times || 1, sorder: curOrder || 0, qty: d.qty, tp: d.tp });
+                    }
+                    updateDatas.push({ id: d.id, shistory: JSON.stringify(history) });
+                }
+            }
+            await transaction.updateRows(this.tableName, updateDatas);
+        }
+
+        async updateHistory(stage, transaction) {
+            await this.updateHistory4TimesOrder(stage, stage.curTimes, [stage.curOrder], transaction);
+        }
+
+        async updateHistory4CheckAgain(stage, transaction) {
+            await this.updateHistory4TimesOrder(stage, stage.curTimes, [stage.curOrder + 1], transaction);
+        }
+
+        async addInitialStageData(stage, preStage, transaction) {
+            if (!stage || !preStage) {
+                throw '标段数据有误';
+            }
+            const preDatas = await this.getAllDataByCondition({
+                columns: ['uuid', 'add_sid', 'add_sorder', 'add_uid', 'tid', 'name', 'spec', 'm_order', 'unit', 'tax', 'arrive_time', 'source', 'bills_code', 'location', 'prepare_pos', 'memo',
+                    'arrive_qty', 'arrive_tp', 'unit_price', 'ex_tax_up', 'qty', 'tp', 'pre_qty', 'pre_tp', 'pre_used'],
+                where: { sid: preStage.id },
+            });
+            if (preDatas.length > 0) {
+                for (const pd of preDatas) {
+                    pd.pre_used = pd.pre_used || !this.ctx.helper.checkZero(pd.qty);
+                    pd.pre_qty = this.ctx.helper.add(pd.qty, pd.pre_qty);
+                    pd.pre_tp = this.ctx.helper.add(pd.tp, pd.pre_tp);
+                    delete pd.qty;
+                    delete pd.tp;
+                    pd.sid = stage.id;
+                    pd.sorder = stage.order;
+                }
+                await transaction.delete(this.tableName, { sid: stage.id });
+                const result = await transaction.insert(this.tableName, preDatas);
+                return result.affectedRows === preDatas.length;
+            } else {
+                return true;
+            }
+        }
+
+        async deleteStageTimesData(sid, times, transaction) {
+            const datas = await this.getAllDataByCondition({ where: { sid } });
+            if (datas.length === 0) return;
+
+            const updateDatas = [];
+            for (const d of datas) {
+                const history = d.shistory && d.shistory !== '' ? JSON.parse(d.shistory) : [];
+                const his = history.filter(x => { return x.stimes && x.stimes < times; });
+                his.sort(function(x, y) {
+                    return (x.stimes * 1000 + x.sorder) - (y.stimes * 1000 + y.sorder);
+                });
+                const ud = {
+                    id: d.id,
+                    shistory: JSON.stringify(his),
+                    qty: his.length > 0 ? his[his.length - 1].qty : 0,
+                    tp: his.length > 0 ? his[his.length - 1].tp : 0,
+                };
+                updateDatas.push(ud);
+            }
+            await transaction.updateRows(this.tableName, updateDatas);
+        }
+    }
+
+    return StageYjcl;
+};

+ 1 - 1
app/view/change/plan_information.ejs

@@ -79,7 +79,7 @@
                                 <th width="120" class="text-center" style="vertical-align: middle">变更方案编号<b class="text-danger">*&nbsp;</b></th>
                                 <td><input class="form-control form-control-sm" value="<%- change.code %>" data-name="code" <% if (change.readOnly) { %>readonly<% } %> type="text" placeholder=""></td>
                                 <th width="140" class="text-center" style="vertical-align: middle">变更申请编号</th>
-                                <td><input class="form-control form-control-sm" type="text" value="<%- change.apply_code %>" data-name="apply_code" <% if (change.readOnly) { %>readonly<% } %> placeholder="自动读取,没有就为空,可编辑"></td>
+                                <td><input class="form-control form-control-sm" type="text" value="<%- change.apply_code %>" data-name="apply_code" <% if (ctx.session.sessionUser.accountId !== change.uid) { %>readonly<% } %> placeholder="自动读取,没有就为空,可编辑"></td>
                             </tr>
                             <tr>
                                 <th width="120" class="text-center" style="vertical-align: middle">变更工程名称<b class="text-danger">*&nbsp;</b></th>

+ 37 - 4
app/view/change/relation.ejs

@@ -29,7 +29,7 @@
                     <tbody>
                     <tbody>
                     <% if (ctx.session.sessionProject.page_show.openChangeProject) { %>
-                    <tr>
+                    <tr id="project">
                         <td class="text-center">变更立项</td>
                         <td><% if (changeProjectInfo) { %><%- changeProjectInfo.code %><% } %></td>
                         <td><% if (changeProjectInfo) { %><%- changeProjectInfo.name %><% } %></td>
@@ -37,7 +37,7 @@
                     </tr>
                     <% } %>
                     <% if (ctx.session.sessionProject.page_show.openChangeApply) { %>
-                    <tr>
+                    <tr id="apply">
                         <td class="text-center">变更申请</td>
                         <td><% if (changeApplyInfo) { %><%- changeApplyInfo.code %><% } %></td>
                         <td><% if (changeApplyInfo) { %><%- changeApplyInfo.name %><% } %></td>
@@ -45,9 +45,9 @@
                     </tr>
                     <% } %>
                     <% if (ctx.session.sessionProject.page_show.openChangePlan) { %>
-                    <tr>
+                    <tr id="plan">
                         <td class="text-center">变更方案</td>
-                        <td><% if (changePlanInfo) { %><%- changePlanInfo.code %><% } %></td>
+                        <td><% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %><input id="plan_code" class="form-control form-control-sm" type="text" value="<% if (changePlanInfo) { %><%- changePlanInfo.code %><% } %>" data-name="plan_code" <% if (ctx.session.sessionUser.accountId !== change.uid) { %>readonly<% } %> placeholder="自动读取,没有就为空,可编辑"><% } else { %><% if (changePlanInfo) { %><%- changePlanInfo.code %><% } %><% } %></td>
                         <td><% if (changePlanInfo) { %><%- changePlanInfo.name %><% } %></td>
                         <td class="text-center"><% if (changePlanInfo) { %><a target="_blank" href="/tender/<%- tender.id %>/change/plan/<%- changePlanInfo.id %>/information">查看详情</a><% } %></td>
                     </tr>
@@ -60,4 +60,37 @@
 </div>
 <script>
     autoFlashHeight();
+    <% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %>
+    $(function () {
+        $('#plan input').change(function () {
+            postData('/tender/' + window.location.pathname.split('/')[2] + '/change/' + window.location.pathname.split('/')[4] + '/information/save', { type: 'plan_code', plan_code: $(this).val() }, function (data) {
+                if (data.projectInfo) {
+                    $('#project td').eq(1).text(data.projectInfo.code);
+                    $('#project td').eq(2).text(data.projectInfo.name);
+                    $('#project td').eq(3).html('<a target="_blank" href="/tender/' + window.location.pathname.split('/')[2] + '/change/project/' + data.projectInfo.id + '/information">查看详情</a>')
+                } else {
+                    $('#project td').eq(1).text('');
+                    $('#project td').eq(2).text('');
+                    $('#project td').eq(3).html('');
+                }
+                if (data.applyInfo) {
+                    $('#apply td').eq(1).text(data.applyInfo.code);
+                    $('#apply td').eq(2).text(data.applyInfo.name);
+                    $('#apply td').eq(3).html('<a target="_blank" href="/tender/' + window.location.pathname.split('/')[2] + '/change/apply/' + data.applyInfo.id + '/information">查看详情</a>')
+                } else {
+                    $('#apply td').eq(1).text('');
+                    $('#apply td').eq(2).text('');
+                    $('#apply td').eq(3).html('');
+                }
+                if (data.planInfo) {
+                    $('#plan td').eq(2).text(data.planInfo.name);
+                    $('#plan td').eq(3).html('<a target="_blank" href="/tender/' + window.location.pathname.split('/')[2] + '/change/plan/' + data.planInfo.id + '/information">查看详情</a>')
+                } else {
+                    $('#plan td').eq(2).text('');
+                    $('#plan td').eq(3).html('');
+                }
+            });
+        });
+    });
+    <% } %>
 </script>

+ 152 - 9
app/view/ledger/audit_modal.ejs

@@ -9,8 +9,11 @@
             <div class="modal-body">
                 <div class="row">
                     <div class="col-4">
+                        <% if(tender.ledger_status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+                            <a class="sp-list-item" href="#sub-sp2" data-toggle="modal" data-target="#sub-sp2" id="hideSp">修改审批流程</a>
+                        <% } %>
                         <div class="card mt-3">
-                            <ul class="list-group list-group-flush">
+                            <ul class="list-group list-group-flush auditors-list">
                                 <% auditors.forEach((item, idx) => { %>
                                 <% if (idx === 0) { %>
                                 <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
@@ -45,7 +48,7 @@
                             <% } %>
                         <div class="<%- idx < auditHistory.length - 1 ? 'fold-card' : '' %>">
                             <div class="text-center text-muted"><%- idx+1 %>#</div>
-                            <ul class="timeline-list list-unstyled mt-2">
+                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === auditHistory.length - 1) { %>last-auditor-list<% } %>">
                                 <% auditors.forEach((auditor, index) => { %>
                                 <% if (index === 0) { %>
                                 <li class="timeline-list-item pb-2">
@@ -70,7 +73,7 @@
                                         </div>
                                     </div>
                                 </li>
-                                <li class="timeline-list-item pb-2">
+                                <li class="timeline-list-item pb-2 <% if (auditor.status === auditConst.status.uncheck && idx === auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <div class="timeline-item-date">
                                         <%- ctx.helper.formatDate(auditor.end_time) %>
                                     </div>
@@ -119,7 +122,7 @@
                                     </div>
                                 </li>
                                 <% } else {%>
-                                <li class="timeline-list-item pb-2">
+                                <li class="timeline-list-item pb-2 <% if (auditor.status === auditConst.status.uncheck && idx === auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <div class="timeline-item-date">
                                         <%- ctx.helper.formatDate(auditor.end_time) %>
                                     </div>
@@ -200,8 +203,11 @@
             <div class="modal-body">
                 <div class="row">
                     <div class="col-4">
+                        <% if(tender.ledger_status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+                            <a class="sp-list-item" href="#sub-sp2" data-toggle="modal" data-target="#sub-sp2" id="hideSp">修改审批流程</a>
+                        <% } %>
                         <div class="card mt-3">
-                            <ul class="list-group list-group-flush">
+                            <ul class="list-group list-group-flush auditors-list">
                                 <% auditors.forEach((item, idx) => { %>
                                 <% if (idx === 0) { %>
                                 <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
@@ -236,7 +242,7 @@
                             <% } %>
                         <div class="<%- idx < auditHistory.length - 1 ? 'fold-card' : '' %>">
                             <div class="text-center text-muted"><%- idx+1 %>#</div>
-                            <ul class="timeline-list list-unstyled mt-2">
+                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === auditHistory.length - 1) { %>last-auditor-list<% } %>">
                                 <% auditors.forEach((auditor, index) => { %>
                                 <% if (index === 0) { %>
                                 <li class="timeline-list-item pb-2">
@@ -261,7 +267,7 @@
                                         </div>
                                     </div>
                                 </li>
-                                <li class="timeline-list-item pb-2">
+                                <li class="timeline-list-item pb-2 <% if (auditor.status === auditConst.status.uncheck && idx === auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <div class="timeline-item-date">
                                         <%- ctx.helper.formatDate(auditor.end_time) %>
                                     </div>
@@ -311,7 +317,7 @@
                                     </div>
                                 </li>
                                 <% } else {%>
-                                <li class="timeline-list-item pb-2">
+                                <li class="timeline-list-item pb-2 <% if (auditor.status === auditConst.status.uncheck && idx === auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <div class="timeline-item-date">
                                         <%- ctx.helper.formatDate(auditor.end_time) %>
                                     </div>
@@ -368,7 +374,6 @@
                                 <% }) %>
                             </ul>
                         </div>
-
                         <% }) %>
                     </div>
                 </div>
@@ -383,6 +388,144 @@
     </div>
 </div>
 <% } %>
+<% if (tender.ledger_status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+    <!--上报审批-->
+    <div class="modal fade" id="sub-sp2" data-backdrop="static">
+        <div class="modal-dialog" style="max-width: 650px" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">修改审批流程</h5>
+                </div>
+                <div class="modal-body">
+                    <div class="card mt-1">
+                        <div class="modal-height-500" style="overflow: visible">
+                            <style>
+                                #admin-edit-shenpi thead th {
+                                    border-bottom: 0;
+                                }
+                                #admin-edit-shenpi td, #admin-edit-shenpi th {
+                                    padding: 0.75rem;
+                                }
+                                #admin-edit-shenpi th {
+                                    background: none;
+                                    color: #212529;
+                                    border-top: 0;
+                                }
+                            </style>
+                            <table class="table table-hover" id="admin-edit-shenpi">
+                                <thead>
+                                <tr class="card-header">
+                                    <th>审批流程</th>
+                                    <th width="80" style="text-align: center">审批状态</th>
+                                    <th width="200" style="text-align: center">操作</th>
+                                </tr>
+                                </thead>
+                                <% for (let i = 1, iLen = auditors.length; i < iLen; i++) { %>
+                                    <tr>
+                                        <td><span class="shenpi-order"><%- i %></span> <%- auditors[i].name %> <small class="text-muted"><%- auditors[i].role %></small></td>
+                                        <td style="text-align: center"><span class="<%- auditConst.auditStringClass[auditors[i].status] %>"><%- auditors[i].status !== auditConst.status.uncheck ? auditConst.auditString[auditors[i].status] : '待审批'  %></span></td>
+                                        <td style="text-align: center">
+                                            <% if (auditors[i].status === auditConst.status.checking) { %>
+                                                <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditors[i].audit_id %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
+                                    <div class="dropdown-menu dropdown-menu-right" id="<%- auditors[i].audit_id %>_add_dropdownMenu" aria-labelledby="<%- auditors[i].audit_id %>_add_dropdownMenuButton" style="width:220px">
+                                        <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
+                                                                     placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditors[i].audit_id %>_add"></div>
+                                        <dl class="list-unstyled book-list" data-aid="<%- auditors[i].audit_id %>" data-operate="add">
+                                            <% accountGroup.forEach((group, idx) => { %>
+                                                <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
+                                                       data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
+                                                <div class="dd-content" data-toggleid="<%- idx %>">
+                                                    <% group.groupList.forEach(item => { %>
+                                                        <% if (item.id !== ctx.tender.user_id) { %>
+                                                            <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
+                                                                <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
+                                                                            class="ml-auto"><%- item.mobile %></span></p>
+                                                                <span class="text-muted"><%- item.role %></span>
+                                                            </dd>
+                                                        <% } %>
+                                                    <% });%>
+                                                </div>
+                                            <% }) %>
+                                        </dl>
+                                    </div>
+                                    </span>
+                                            <% } %>
+                                            <% if (auditors[i].status === auditConst.status.uncheck) { %>
+                                                <span class="dropdown mr-2">
+                                    <a href="javascript: void(0)" class="add-audit" id="<%- auditors[i].audit_id %>_add_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">增加</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditors[i].audit_id %>_add_dropdownMenu" aria-labelledby="<%- auditors[i].audit_id %>_add_dropdownMenuButton" style="width:220px">
+                                            <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
+                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditors[i].audit_id %>_add"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- auditors[i].audit_id %>" data-operate="add">
+                                                <% accountGroup.forEach((group, idx) => { %>
+                                                    <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
+                                                           data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
+                                                    <div class="dd-content" data-toggleid="<%- idx %>">
+                                                        <% group.groupList.forEach(item => { %>
+                                                            <% if (item.id !== ctx.tender.user_id) { %>
+                                                                <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
+                                                                    <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
+                                                                                class="ml-auto"><%- item.mobile %></span></p>
+                                                                    <span class="text-muted"><%- item.role %></span>
+                                                                </dd>
+                                                            <% } %>
+                                                        <% });%>
+                                                    </div>
+                                                <% }) %>
+                                            </dl>
+                                        </div>
+                                    </span>
+                                                <span class="dropdown mr-2">
+                                        <a href="javascript: void(0)" class="change-audit" id="<%- auditors[i].audit_id %>_change_dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">更换</a>
+                                        <div class="dropdown-menu dropdown-menu-right" id="<%- auditors[i].audit_id %>_change_dropdownMenu" aria-labelledby="<%- auditors[i].audit_id %>_change_dropdownMenuButton" style="width:220px">
+                                            <div class="mb-2 p-2"><input class="form-control form-control-sm gr-search"
+                                                                         placeholder="姓名/手机 检索" autocomplete="off" data-code="<%- auditors[i].audit_id %>_change"></div>
+                                            <dl class="list-unstyled book-list" data-aid="<%- auditors[i].audit_id %>" data-operate="change">
+                                                <% accountGroup.forEach((group, idx) => { %>
+                                                    <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>"
+                                                           data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
+                                                    <div class="dd-content" data-toggleid="<%- idx %>">
+                                                        <% group.groupList.forEach(item => { %>
+                                                            <% if (item.id !== ctx.tender.user_id) { %>
+                                                                <dd class="border-bottom p-2 mb-0 " data-id="<%- item.id %>">
+                                                                    <p class="mb-0 d-flex"><span class="text-primary"><%- item.name %></span><span
+                                                                                class="ml-auto"><%- item.mobile %></span></p>
+                                                                    <span class="text-muted"><%- item.role %></span>
+                                                                </dd>
+                                                            <% } %>
+                                                        <% });%>
+                                                    </div>
+                                                <% }) %>
+                                            </dl>
+                                        </div>
+                                    </span>
+                                                <span class="dropdown">
+                                    <a href="javascript: void(0)" class="text-danger" title="移除" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">移除</a>
+                                    <div class="dropdown-menu">
+                                        <span class="dropdown-item" href="javascript:void(0);">确认移除审批人?</span>
+                                        <div class="dropdown-divider"></div>
+                                        <div class="px-2 py-1 text-center">
+                                            <button class="remove-audit btn btn-sm btn-danger" data-id="<%- auditors[i].audit_id %>">移除</button>
+                                            <button class="btn btn-sm btn-secondary">取消</button>
+                                        </div>
+                                    </div>
+                                    </span>
+                                            <% } %>
+                                        </td>
+                                    </tr>
+                                <% } %>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+                <form class="modal-footer">
+                    <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                </form>
+            </div>
+        </div>
+    </div>
+<% } %>
 <% if (tender.ledger_status === auditConst.status.checked && auditors[auditors.length - 1].audit_id === ctx.session.sessionUser.accountId && !tender.hasStage && !tender.hasRevise) { %>
 <% if (!authMobile && ctx.session.sessionUser.loginStatus === 0) { %>
 <!--终审重新审批-->

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

@@ -391,9 +391,10 @@
     const syncLedgerUrl = '<%- syncLedgerUrl %>';
     const nodeType = JSON.parse('<%- JSON.stringify(nodeType) %>');
 </script>
-<% if ((tender.ledger_status === auditConst.status.uncheck || tender.ledger_status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === tender.user_id) { %>
+<% if ((tender.ledger_status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) || ((tender.ledger_status === auditConst.status.uncheck || tender.ledger_status === auditConst.status.checkNo) && ctx.session.sessionUser.accountId === tender.user_id)) { %>
 <script>
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
     const accountGroup = JSON.parse('<%- JSON.stringify(accountGroup) %>');
+    const auditorList = JSON.parse(unescape('<%- escape(JSON.stringify(auditors)) %>'));
 </script>
 <% } %>

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

@@ -136,7 +136,7 @@
                         style="width:220px">
                         <div class="mb-2 p-2"><input class="form-control form-control-sm"
                                 placeholder="姓名/手机 检索" id="gr-search" autocomplete="off"></div>
-                        <dl class="list-unstyled book-list">
+                        <dl class="list-unstyled book-list" id="book-list">
                             <% accountGroup.forEach((group, idx) => { %>
                                 <dt><a href="javascript: void(0);" class="acc-btn" data-groupid="<%- idx %>" data-type="hide"><i class="fa fa-plus-square"></i></a> <%- group.groupName %></dt>
                                 <div class="dd-content" data-toggleid="<%- idx %>">
@@ -182,7 +182,7 @@
     </div>
 </div>
 <% } %>
-<% if ((tender.ledger_status !== auditConst.status.unCheck) || (tender.ledger_times > 1)) { %>
+<% if ((tender.ledger_status !== auditConst.status.uncheck) || (tender.ledger_times > 1)) { %>
 <!--审批流程/结果-->
 <div class="modal fade" id="sp-list" data-backdrop="static">
     <div class="modal-dialog modal-lg" role="document">
@@ -195,9 +195,12 @@
                     <div class="col-4">
                         <% if(tender.ledger_status === auditConst.status.checkNo) { %>
                             <a class="sp-list-item" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" id="hideSp">修改审批流程</a>
+                        <% } else if(tender.ledger_status !== auditConst.status.checked && ctx.session.sessionUser.is_admin) { %>
+                            <a class="sp-list-item" href="#sub-sp2" data-toggle="modal" data-target="#sub-sp2"
+                               id="hideSp">修改审批流程</a>
                         <% } %>
                         <div class="card mt-3">
-                            <ul class="list-group list-group-flush" id="auditors-list">
+                            <ul class="list-group list-group-flush auditors-list" id="auditors-list">
                                 <% auditors.forEach((item, idx) => { %>
                                 <% if (idx === 0) { %>
                                 <li class="list-group-item" data-auditorId="<%- item.audit_id %>">
@@ -232,7 +235,7 @@
                         <% } %>
                         <div class="<%- idx < auditHistory.length - 1 ? 'fold-card' : '' %>">
                             <div class="text-center text-muted"><%- idx+1 %>#</div>
-                            <ul class="timeline-list list-unstyled mt-2">
+                            <ul class="timeline-list list-unstyled mt-2 <% if (idx === auditHistory.length - 1) { %>last-auditor-list<% } %>">
                                 <% auditors.forEach((auditor, index) => { %>
                                 <% if (index === 0) { %>
                                 <li class="timeline-list-item pb-2">
@@ -257,7 +260,7 @@
                                         </div>
                                     </div>
                                 </li>
-                                <li class="timeline-list-item pb-2">
+                                <li class="timeline-list-item pb-2 <% if (auditor.status === auditConst.status.uncheck && idx === auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <div class="timeline-item-date">
                                         <%- ctx.helper.formatDate(auditor.end_time) %>
                                     </div>
@@ -301,7 +304,7 @@
                                     </div>
                                 </li>
                                 <% } else {%>
-                                <li class="timeline-list-item pb-2">
+                                <li class="timeline-list-item pb-2 <% if (auditor.status === auditConst.status.uncheck && idx === auditHistory.length - 1) { %>is_uncheck<% } %>">
                                     <div class="timeline-item-date">
                                         <%- ctx.helper.formatDate(auditor.end_time) %>
                                     </div>
@@ -352,7 +355,6 @@
                                 <% }) %>
                             </ul>
                         </div>
-
                         <% }) %>
                     </div>
                 </div>

+ 2 - 0
app/view/report/index_archive.ejs

@@ -15,6 +15,7 @@
             <% include ../stage/stage_sub_mini_menu.ejs %>
             <% } %>
             <div>
+                <% if (stg_id === -1) { %>
                 <div class="d-inline-block">
                     <div class="dropdown">
                         <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="bizDropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -31,6 +32,7 @@
                         </div>
                     </div>
                 </div>
+                <% } %>
                 <div class="d-inline-block">
                     <div class="dropdown" id="divSelectableStages">
                         <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="btnCurrentStage" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>

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

@@ -133,7 +133,7 @@
         colWidth: true,
     }
     const gatherLeafXmjSpreadSetting = JSON.parse('<%- JSON.stringify(gatherLeafXmjSpread) %>');
-    leafXmjSpreadSetting.localCache = {
+    gatherLeafXmjSpreadSetting.localCache = {
         key: 'stage-gather-gatherLeafXmj',
         colWidth: true,
     }

+ 1 - 0
app/view/stage_extra/sub_menu_list.ejs

@@ -1,5 +1,6 @@
 <nav-menu title="返回" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order %>" tclass="text-primary" ml="1" icon="fa-chevron-left"></nav-menu>
 <nav-menu title="甲供材料" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/jgcl'%>" ml="3" active="<%= ctx.url.indexOf('extra/jgcl') %>"></nav-menu>
+<nav-menu title="永久材料" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/yjcl'%>" ml="3" active="<%= ctx.url.indexOf('extra/yjcl') %>"></nav-menu>
 <nav-menu title="奖罚金" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/bonus'%>" ml="3" active="<%= ctx.url.indexOf('extra/bonus') %>"></nav-menu>
 <nav-menu title="安全生产" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/safeProd'%>" ml="3" active="<%= ctx.url.indexOf('extra/safeProd') %>"></nav-menu>
 <nav-menu title="临时占地" url="/tender/<%= ctx.tender.id %>/measure/stage/<%= ctx.stage.order + '/extra/tempLand'%>" ml="3" active="<%= ctx.url.indexOf('extra/tempLand') %>"></nav-menu>

+ 39 - 0
app/view/stage_extra/yjcl.ejs

@@ -0,0 +1,39 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex">
+            <% include ./sub_mini_menu.ejs %>
+            <div>
+                永久材料
+            </div>
+            <% if (ctx.app.config.is_debug) { %>
+            <div class="d-inline-block ml-3">
+                <a id="exportExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导出永久材料Excel</a>
+            </div>
+            <% } %>
+            <div class="ml-auto"></div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header p-0"></div>
+        <div class="w-100 sub-content row">
+            <div class="c-body col-12">
+                <div class="sjs-height-0" id="yjcl-spread">
+                </div>
+            </div>
+            <!--<div class="c-body col-3">-->
+                <!--<table class="table table-bordered" style="width: 99%">-->
+                    <!--<tr class="text-center"><th width="66.6%">名称</th><th>规格</th><th>数量</th><th>金额</th></tr>-->
+                    <!--<tbody id="sum">-->
+                    <!--</tbody>-->
+                <!--</table>-->
+            <!--</div>-->
+        </div>
+    </div>
+</div>
+<script>
+    const stageId = <%- ctx.stage.id %>;
+    const stageUserId = <%- ctx.stage.user_id %>;
+    const readOnly = <%- ctx.stage.readOnly || ctx.stage.revising || (ctx.stage.order > 1 && (!ctx.stage.preCheckedStage || ctx.stage.preCheckedStage.order < ctx.stage.order - 1)) %>;
+    const thousandth = <%- ctx.tender.info.display.thousandth %>;
+</script>

+ 45 - 1
app/view/wap/dashboard.ejs

@@ -37,7 +37,7 @@
         </nav>
         <!--待审批期列表-->
         <div class="py-6">
-            <% if (auditStages.length !== 0 || auditChanges.length !== 0 || auditRevise.length !== 0 || auditAdvance.length !== 0 || auditChangePlans.length !== 0) { %>
+            <% if (auditStages.length !== 0 || auditChanges.length !== 0 || auditRevise.length !== 0 || auditAdvance.length !== 0 || auditChangeProjects.length !== 0|| auditChangeApplys.length !== 0 || auditChangePlans.length !== 0) { %>
                 <% for (const audit of auditStages) { %>
                 <div class="card mb-3">
                     <div class="card-header d-flex justify-content-between">
@@ -111,6 +111,50 @@
                         </div>
                     </div>
                 <% } %>
+                <% for (const change of auditChangeProjects) { %>
+                    <div class="card mb-3">
+                        <div class="card-header d-flex justify-content-between">
+                            <span><%- JSON.parse(change.deal_info).buildName %></span>
+                            <span class="badge badge-pill badge-danger">变更立项</span>
+                        </div>
+                        <div class="bg-light p-2 px-3"><b><%- change.t_name %></b></div>
+                        <div class="card-body">
+                            <div class="d-flex justify-content-between"><span><%- change.code %></span></div>
+                            <div class="my-2">
+                                <table class="table table-sm table-bordered">
+                                    <tr><th width="90">工程名称</th><td><%- change.name %></td></tr>
+                                    <tr><th>变更性质</th><td><%- change.quality %></td></tr>
+                                    <tr><th>增减金额</th><td class="text-right"><%- change.crease_price %></td></tr>
+                                </table>
+                            </div>
+                            <div class="">
+                                <a href="/wap/tender/<%- change.tid %>/change/project/<%- change.id %>/information#shenpi" class="btn btn-block btn-success">审批</a>
+                            </div>
+                        </div>
+                    </div>
+                <% } %>
+                <% for (const change of auditChangeApplys) { %>
+                    <div class="card mb-3">
+                        <div class="card-header d-flex justify-content-between">
+                            <span><%- JSON.parse(change.deal_info).buildName %></span>
+                            <span class="badge badge-pill badge-danger">变更申请</span>
+                        </div>
+                        <div class="bg-light p-2 px-3"><b><%- change.t_name %></b></div>
+                        <div class="card-body">
+                            <div class="d-flex justify-content-between"><span><%- change.code %></span></div>
+                            <div class="my-2">
+                                <table class="table table-sm table-bordered">
+                                    <tr><th width="90">工程名称</th><td><%- change.name %></td></tr>
+                                    <tr><th>变更性质</th><td><%- change.quality %></td></tr>
+                                    <tr><th>增减金额</th><td class="text-right"><%- change.crease_price %></td></tr>
+                                </table>
+                            </div>
+                            <div class="">
+                                <a href="/wap/tender/<%- change.tid %>/change/apply/<%- change.id %>/information#shenpi" class="btn btn-block btn-success">审批</a>
+                            </div>
+                        </div>
+                    </div>
+                <% } %>
                 <% for (const change of auditChangePlans) { %>
                     <div class="card mb-3">
                         <div class="card-header d-flex justify-content-between">

+ 28 - 13
app/view/wap/shenpi_change.ejs

@@ -22,7 +22,7 @@
     <!--顶部-->
     <nav class="fixed-top bg-dark">
         <div class="my-2 d-flex justify-content-between">
-            <span class="text-white ml-3"><a href="/wap/tender/<%- tender.id %>#biangeng" class="mr-2 text-white show-loading"><i class="fa fa-chevron-left"></i>工程变更</a></span>
+            <span class="text-white ml-3"><a href="/wap/tender/<%- tender.id %>/change#change" class="mr-2 text-white show-loading"><i class="fa fa-chevron-left"></i>工程变更</a></span>
             <a tabindex="0" href="javascript:void(0)" class="text-white text-truncate text-center"
                style="width:150px" data-toggle="popover" data-placement="top"
                data-content="<%- tender.name %>" data-trigger="focus"><%- tender.name %></a>
@@ -220,7 +220,7 @@
 <!--审批通过弹窗-->
 <div class="modal" tabindex="-1" role="dialog" id="sp-done">
     <div class="modal-dialog" role="document">
-        <form class="modal-content" action="/wap/tender/<%- tender.id %>/change/approval?_csrf_j=<%= ctx.csrf %>" method="post" id="success-approval">
+        <div class="modal-content" id="success-approval">
             <div class="modal-header">
                 <h5 class="modal-title">审批通过</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
@@ -246,15 +246,15 @@
                 <input type="hidden" name="status" value="<%- auditConst.status.checked %>">
                 <input type="hidden" name="w_code" value="<%- change.w_code %>">
                 <input type="hidden" name="change_id" value="<%- change.cid %>">
-                <button type="submit" class="btn btn-success approval-btn">审批通过</button>
+                <button type="button" class="btn btn-success approval-btn">审批通过</button>
             </div>
-        </form>
+        </div>
     </div>
 </div>
 <!--审批退回弹窗-->
 <div class="modal" tabindex="-1" role="dialog" id="sp-back">
     <div class="modal-dialog" role="document">
-        <form class="modal-content" action="/wap/tender/<%- tender.id %>/change/approval?_csrf_j=<%= ctx.csrf %>" method="post" id="fail-approval">
+        <div class="modal-content" id="fail-approval">
             <div class="modal-header">
                 <h5 class="modal-title">审批退回</h5>
                 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
@@ -285,9 +285,9 @@
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 <input type="hidden" name="w_code" value="<%- change.w_code %>">
                 <input type="hidden" name="change_id" value="<%- change.cid %>">
-                <button type="submit" class="btn btn-warning approval-btn">确认退回</button>
+                <button type="button" class="btn btn-warning approval-btn">确认退回</button>
             </div>
-        </form>
+        </div>
     </div>
 </div>
 <% } %>
@@ -311,6 +311,10 @@
         $('.approval-btn').on('click', function () {
             // 判断审批状态
             let returnflag = true;
+            const pData = {
+                change_id: '<%- change.cid %>',
+                w_code: '<%- change.w_code %>',
+            }
             if ($(this).hasClass('btn-success')) {
                 const sdesc = $('#success-approval').find('textarea').val();
                 if (sdesc === '') {
@@ -322,19 +326,22 @@
                     returnflag = false;
                 } else if ($('input[name="p_code"]').val() !== undefined) {
                     $('input[name="p_code"]').val($.trim($('input[name="p_code"]').val()));
-                    const postData = {
+                    const postData2 = {
                         p_code: $('input[name="p_code"]').val(),
                     };
-                    postDataWithAsync('/tender/<%- tender.id %>/change/<%- change.cid %>/check/codeRepeat',postData, function (result) {
+                    postDataWithAsync('/tender/<%- tender.id %>/change/<%- change.cid %>/check/codeRepeat',postData2, function (result) {
                     }, function (data) {
                         returnflag = false;
                     });
+                    pData.p_code = $('input[name="p_code"]').val();
                 }
                 if(returnflag) {
-                    $('input[name="w_code"]').val($.trim($('#w_code').val()));
+                    // $('input[name="w_code"]').val($.trim($('#w_code').val()));
 
                     $('#success-approval').find('textarea').val(sdesc.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '));
-                    $('#success-approval').submit();
+                    // $('#success-approval').submit();
+                    pData.status = <%- auditConst.status.checked %>;
+                    pData.sdesc = sdesc.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
                 }
             } else {
                 const sdesc = $('#fail-approval').find('textarea').val();
@@ -349,10 +356,18 @@
                 }
                 if(returnflag) {
                     $('#fail-approval').find('textarea').val(sdesc.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '));
-                    $('input[name="w_code"]').val($.trim($('#w_code').val()));
-                    $('#fail-approval').submit();
+                    // $('input[name="w_code"]').val($.trim($('#w_code').val()));
+                    // $('#fail-approval').submit();
+                    pData.status = parseInt(type);
+                    pData.sdesc = sdesc.replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
                 }
             }
+            if (pData.status) {
+                console.log(pData);
+                postData('/tender/<%- tender.id %>/change/approval', pData, function (result) {
+                    window.location.reload();
+                });
+            }
         })
     });
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 268 - 0
app/view/wap/shenpi_change_apply.ejs


+ 309 - 0
app/view/wap/shenpi_change_index.ejs

@@ -0,0 +1,309 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>标段概况-计量支付</title>
+    <link rel="stylesheet" href="/public/css/bootstrap/bootstrap.min.css">
+    <link rel="stylesheet" href="/public/css/wap/main.css">
+    <link rel="stylesheet" href="/public/css/toast.css">
+    <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" href="/public/css/toastr.css">
+    <script src=/public/js/echarts/echarts.min.js></script>
+    <link rel="shortcut icon" href="/public/images/favicon.ico">
+    <style>
+        body {
+            padding: 0;
+        }
+    </style>
+</head>
+<body>
+<div class="container">
+    <!--顶部-->
+    <nav class="fixed-top bg-dark">
+        <div class="my-2 d-flex justify-content-between">
+            <span class="text-white ml-3"><a href="/wap/tender/<%- tender.id %>#biangeng" class="mr-2 text-white show-loading"><i class="fa fa-chevron-left"></i>工程变更</a></span>
+            <a tabindex="0" href="javascript:void(0)" class="text-white text-truncate text-center"
+               style="width:150px" data-toggle="popover" data-placement="top"
+               data-content="<%- tender.name %>" data-trigger="focus"><%- tender.name %></a>
+            <div class="mr-3">
+                <div class="dropdown">
+                    <button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown">
+                        <%- ctx.session.sessionUser.name.substr(ctx.session.sessionUser.name.length > 2 ? ctx.session.sessionUser.name.length - 2 : 0) %>
+                    </button>
+                    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                        <a class="dropdown-item" href="/wap/logout">退出登录</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </nav>
+    <!--标段概况-->
+    <div class="py-6">
+        <ul class="nav nav-tabs nav-fill">
+            <% if (ctx.session.sessionProject.page_show.openChangeProject) { %>
+                <li class="nav-item">
+                    <a class="px-1 nav-link" data-toggle="tab" href="#changeProject" role="tab">变更立项</a>
+                </li>
+            <% } %>
+            <% if (ctx.session.sessionProject.page_show.openChangeApply) { %>
+                <li class="nav-item">
+                    <a class="px-1 nav-link" data-toggle="tab" href="#changeApply" role="tab">变更申请</a>
+                </li>
+            <% } %>
+            <% if (ctx.session.sessionProject.page_show.openChangePlan) { %>
+                <li class="nav-item">
+                    <a class="px-1 nav-link" data-toggle="tab" href="#changePlan" role="tab">变更方案</a>
+                </li>
+            <% } %>
+            <li class="nav-item">
+                <a class="px-1 nav-link active" data-toggle="tab" href="#change" role="tab">变更令</a>
+            </li>
+        </ul>
+        <div class="tab-content">
+            <% if (ctx.session.sessionProject.page_show.openChangeProject) { %>
+                <div class="tab-pane" id="changeProject">
+                    <dl class="mb-2 mt-3">
+                    <% for (const c of changeProjects) { %>
+                        <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/project/<%- c.id %>/information"><%- c.code %></a></span></dt>
+                        <dd>
+                            <table class="table table-hover">
+                                <tbody>
+                                <tr>
+                                    <td colspan="2">
+                                        <p class="mb-0">工程名称</p>
+                                        <%- c.name %>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <p class="mb-0">变更性质</p>
+                                        <b><%- c.quality %></b>
+                                    </td>
+                                    <td>
+                                        <p class="mb-0">增减金额</p>
+                                        <b><%- c.crease_price %></b>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td colspan="2">
+                                        <% if (c.showApprovalBtn){ %>
+                                            <a href="/wap/tender/<%- tender.id %>/change/project/<%- c.id %>/information#shenpi" class="btn btn-block btn-success">审批变更</a>
+                                        <% } else if (c.status === auditChangeProjectConst.status.uncheck) { %>
+                                            <span>待上报</span>
+                                        <% } else { %>
+                                            <% if (c.curAuditors.length > 0) { %>
+                                                <% if (c.curAuditors[0].audit_type === auditType.key.common) { %>
+                                                    <span class="<%- auditChangeProjectConst.statusClass[c.status] %>"><%- c.curAuditors[0].name %>-<%- c.curAuditors[0].role %> <%- auditChangeProjectConst.statusString[c.status] %></span>
+                                                <% } else { %>
+                                                    <span class="<%- auditChangeProjectConst.statusClass[c.status] %>"><%- ctx.helper.transFormToChinese(c.curAuditors[0].audit_order) + '审' %> <%- auditChangeProjectConst.statusString[c.status] %></span>
+                                                <% } %>
+                                            <% } %>
+                                        <% } %>
+                                    </td>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </dd>
+                    <% } %>
+                    </dl>
+                </div>
+            <% } %>
+            <% if (ctx.session.sessionProject.page_show.openChangeApply) { %>
+                <div class="tab-pane" id="changeApply">
+                    <dl class="mb-2 mt-3">
+                    <% for (const c of changeApplys) { %>
+                        <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/apply/<%- c.id %>/information"><%- c.code %></a></span></dt>
+                        <dd>
+                            <table class="table table-hover">
+                                <tbody>
+                                <tr>
+                                    <td colspan="2">
+                                        <p class="mb-0">工程名称</p>
+                                        <%- c.name %>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <p class="mb-0">变更性质</p>
+                                        <b><%- c.quality %></b>
+                                    </td>
+                                    <td>
+                                        <p class="mb-0">增减金额</p>
+                                        <b><%- c.crease_price %></b>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td colspan="2">
+                                        <% if (c.showApprovalBtn){ %>
+                                            <a href="/wap/tender/<%- tender.id %>/change/apply/<%- c.id %>/information#shenpi" class="btn btn-block btn-success">审批变更</a>
+                                        <% } else if (c.status === auditChangeApplyConst.status.uncheck) { %>
+                                            <span>待上报</span>
+                                        <% } else { %>
+                                            <% if (c.curAuditors.length > 0) { %>
+                                                <% if (c.curAuditors[0].audit_type === auditType.key.common) { %>
+                                                    <span class="<%- auditChangeApplyConst.statusClass[c.status] %>"><%- c.curAuditors[0].name %>-<%- c.curAuditors[0].role %> <%- auditChangeApplyConst.statusString[c.status] %></span>
+                                                <% } else { %>
+                                                    <span class="<%- auditChangeApplyConst.statusClass[c.status] %>"><%- ctx.helper.transFormToChinese(c.curAuditors[0].audit_order) + '审' %> <%- auditChangeApplyConst.statusString[c.status] %></span>
+                                                <% } %>
+                                            <% } %>
+                                        <% } %>
+                                    </td>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </dd>
+                    <% } %>
+                    </dl>
+                </div>
+            <% } %>
+            <% if (ctx.session.sessionProject.page_show.openChangePlan) { %>
+                <div class="tab-pane" id="changePlan">
+                    <dl class="mb-2 mt-3">
+                    <% for (const c of changePlans) { %>
+                        <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/plan/<%- c.id %>/information"><%- c.code %></a></span></dt>
+                        <dd>
+                            <table class="table table-hover">
+                                <tbody>
+                                <tr>
+                                    <td colspan="2">
+                                        <p class="mb-0">工程名称</p>
+                                        <%- c.name %>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <p class="mb-0">变更性质</p>
+                                        <b><%- c.quality %></b>
+                                    </td>
+                                    <td>
+                                        <p class="mb-0">变更金额</p>
+                                        <b><%- ctx.helper.roundNum(c.total_price, tpUnit) %></b>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td colspan="2">
+                                        <% if (c.showApprovalBtn){ %>
+                                            <a href="/wap/tender/<%- tender.id %>/change/plan/<%- c.id %>/information#shenpi" class="btn btn-block btn-success">审批变更</a>
+                                        <% } else if (c.status === auditChangePlanConst.status.uncheck) { %>
+                                            <span>待上报</span>
+                                        <% } else { %>
+                                            <% if (c.curAuditors.length > 0) { %>
+                                                <% if (c.curAuditors[0].audit_type === auditType.key.common) { %>
+                                                    <span class="<%- auditChangePlanConst.statusClass[c.status] %>"><%- c.curAuditors[0].name %>-<%- c.curAuditors[0].role %> <%- auditChangePlanConst.statusString[c.status] %></span>
+                                                <% } else { %>
+                                                    <span class="<%- auditChangePlanConst.statusClass[c.status] %>"><%- ctx.helper.transFormToChinese(c.curAuditors[0].audit_order) + '审' %> <%- auditChangePlanConst.statusString[c.status] %></span>
+                                                <% } %>
+                                            <% } %>
+                                        <% } %>
+                                    </td>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </dd>
+                    <% } %>
+                    </dl>
+                </div>
+            <% } %>
+            <div class="tab-pane active" id="change">
+                <dl class="mb-2 mt-3">
+                    <% for (const c of changes) { %>
+                        <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/<%- c.cid %>/information"><% if (c.status !== auditChangeConst.status.checked) { %><%- c.code %><% } else { %><%- c.p_code %><% } %></a></span></dt>
+                        <dd>
+                            <table class="table table-hover">
+                                <tbody>
+                                <tr>
+                                    <td colspan="2">
+                                        <p class="mb-0">工程名称</p>
+                                        <%- c.name %>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <p class="mb-0">变更性质</p>
+                                        <b><% for (const q in changeConst.quality) { %>
+                                                <% const cQuality = changeConst.quality[q] %><% if (cQuality.value === c.quality) { %><%- cQuality.name %><% } %><% } %></b>
+                                    </td>
+                                    <td>
+                                        <p class="mb-0">变更金额</p>
+                                        <b><%- ctx.helper.roundNum(c.total_price, tpUnit) %></b>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td colspan="2">
+                                        <% 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 { %>
+                                            <% 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>
+                                </tbody>
+                            </table>
+                        </dd>
+                    <% } %>
+                </dl>
+            </div>
+        </div>
+    </div>
+    <!--底栏菜单-->
+    <nav class="fixed-bottom navbar-dark bg-light border-top">
+        <ul class="nav nav-fill my-2">
+            <li class="nav-item">
+                <a class="nav-link text-muted show-loading" href="/wap/dashboard"><i class="fa fa-check-square-o"></i> 待审批</a>
+            </li>
+            <li class="nav-item">
+                <a class="nav-link active show-loading" href="/wap/list"><i class="fa fa-list-ul"></i> 项目</a>
+            </li>
+        </ul>
+    </nav>
+</div>
+<!-- JS. -->
+<script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
+<script src="/public/js/popper/popper.min.js"></script>
+<script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/cookies.js"></script>
+<script src="/public/js/toastr.min.js"></script>
+<script src="/public/js/wap/global.js"></script>
+<script>
+    $(document).ready(function () {
+        <% if (ctx.session.sessionProject.page_show.openChangeProject) { %>
+        if (window.location.hash && window.location.hash === '#changeProject') {
+            $('#change').removeClass('active');
+            $('.nav-item a[href="#change"]').removeClass('active');
+
+            $('#changeProject').addClass('active');
+            $('.nav-item a[href="#changeProject"]').addClass('active');
+        }
+        <% } %>
+        <% if (ctx.session.sessionProject.page_show.openChangeApply) { %>
+        if (window.location.hash && window.location.hash === '#changeApply') {
+            $('#change').removeClass('active');
+            $('.nav-item a[href="#change"]').removeClass('active');
+
+            $('#changeApply').addClass('active');
+            $('.nav-item a[href="#changeApply"]').addClass('active');
+        }
+        <% } %>
+        <% if (ctx.session.sessionProject.page_show.openChangePlan) { %>
+        if (window.location.hash && window.location.hash === '#changePlan') {
+            $('#change').removeClass('active');
+            $('.nav-item a[href="#change"]').removeClass('active');
+
+            $('#changePlan').addClass('active');
+            $('.nav-item a[href="#changePlan"]').addClass('active');
+        }
+        <% } %>
+    });
+</script>
+</body>
+</html>

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 27 - 25
app/view/wap/shenpi_change_plan.ejs


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 247 - 0
app/view/wap/shenpi_change_project.ejs


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 45 - 51
app/view/wap/shenpi_stage.ejs


+ 26 - 82
app/view/wap/tender.ejs

@@ -208,88 +208,32 @@
                 </dl>
             </div>
             <div class="tab-pane" id="biangeng">
-                <!--工程变更-->
-                <dl class="mb-2 mt-3">
-                    <% for (const c of changePlans) { %>
-                        <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/plan/<%- c.id %>/info"><%- c.code %></a></span></dt>
-                        <dd>
-                            <table class="table table-hover">
-                                <tbody>
-                                <tr>
-                                    <td colspan="2">
-                                        <p class="mb-0">工程名称</p>
-                                        <%- c.name %>
-                                    </td>
-                                </tr>
-                                <tr>
-                                    <td>
-                                        <p class="mb-0">变更性质</p>
-                                        <b><%- c.quality %></b>
-                                    </td>
-                                    <td>
-                                        <p class="mb-0">变更金额</p>
-                                        <b><%- ctx.helper.roundNum(c.total_price, tpUnit) %></b>
-                                    </td>
-                                </tr>
-                                <tr>
-                                    <td colspan="2">
-                                        <% if (c.status === auditChangePlanConst.status.checking && c.curAuditor.aid === ctx.session.sessionUser.accountId) { %>
-                                            <a href="/wap/tender/<%- tender.id %>/change/plan/<%- c.id %>/info#shenpi" class="btn btn-block btn-success">审批变更</a>
-                                        <% } else if (c.status === auditChangePlanConst.status.uncheck) { %>
-                                            <span>待上报</span>
-                                        <% } else { %>
-                                            <span class="<%- auditChangePlanConst.auditStringClass[c.curAuditor.status] %>"><%- c.curAuditor.name %><%if (c.curAuditor.role !== '' && c.curAuditor.role !== null) { %>-<%- c.curAuditor.role %><% } %> <%- auditChangePlanConst.auditString[c.curAuditor.status] %></span>
-                                        <% } %>
-                                    </td>
-                                </tr>
-                                </tbody>
-                            </table>
-                        </dd>
-                    <% } %>
-                    <% for (const c of changes) { %>
-                    <dt class="bg-light p-2 d-flex justify-content-between"><span><a href="/wap/tender/<%- tender.id %>/change/<%- c.cid %>/info"><% if (c.status !== auditChangeConst.status.checked) { %><%- c.code %><% } else { %><%- c.p_code %><% } %></a></span></dt>
-                    <dd>
-                        <table class="table table-hover">
-                            <tbody>
-                            <tr>
-                                <td colspan="2">
-                                    <p class="mb-0">工程名称</p>
-                                    <%- c.name %>
-                                </td>
-                            </tr>
-                            <tr>
-                                <td>
-                                    <p class="mb-0">变更性质</p>
-                                    <b><% for (const q in changeConst.quality) { %>
-                                            <% const cQuality = changeConst.quality[q] %><% if (cQuality.value === c.quality) { %><%- cQuality.name %><% } %><% } %></b>
-                                </td>
-                                <td>
-                                    <p class="mb-0">变更金额</p>
-                                    <b><%- ctx.helper.roundNum(c.total_price, tpUnit) %></b>
-                                </td>
-                            </tr>
-                            <tr>
-                                <td colspan="2">
-                                    <% 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 { %>
-                                        <% 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>
-                            </tbody>
-                        </table>
-                    </dd>
-                    <% } %>
-                </dl>
+                <% if (ctx.session.sessionProject.page_show.openChangeProject) { %>
+                <div class="card my-3">
+                    <div class="card-body">
+                        <a href="/wap/tender/<%- tender.id %>/change#changeProject"><h5 class="card-title d-flex justify-content-between">变更立项</h5></a>
+                    </div>
+                </div>
+                <% } %>
+                <% if (ctx.session.sessionProject.page_show.openChangeApply) { %>
+                    <div class="card my-3">
+                        <div class="card-body">
+                            <a href="/wap/tender/<%- tender.id %>/change#changeApply"><h5 class="card-title d-flex justify-content-between">变更申请</h5></a>
+                        </div>
+                    </div>
+                <% } %>
+                <% if (ctx.session.sessionProject.page_show.openChangePlan) { %>
+                    <div class="card my-3">
+                        <div class="card-body">
+                            <a href="/wap/tender/<%- tender.id %>/change#changePlan"><h5 class="card-title d-flex justify-content-between">变更方案</h5></a>
+                        </div>
+                    </div>
+                <% } %>
+                <div class="card my-3">
+                    <div class="card-body">
+                        <a href="/wap/tender/<%- tender.id %>/change#change"><h5 class="card-title d-flex justify-content-between">变更令</h5></a>
+                    </div>
+                </div>
             </div>
         </div>
     </div>

+ 18 - 0
config/web.js

@@ -535,6 +535,24 @@ const JsFiles = {
                 ],
                 mergeFile: 'se_jgcl',
             },
+            yjcl: {
+                files: [
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
+                    '/public/js/component/menu.js',
+                ],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/se_yjcl.js',
+                ],
+                mergeFile: 'se_yjcl',
+            },
             bonus: {
                 files: [
                     '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',

+ 35 - 0
sql/update.sql

@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 ALTER TABLE `zh_material`
 ADD COLUMN `rate_tp` decimal(30, 8) NULL DEFAULT NULL COMMENT '建筑含税总金额' AFTER `rate`;
 
@@ -410,3 +411,37 @@ ALTER TABLE `zh_rpt_tree_node_cust`
 ADD COLUMN `tender_id` INT NULL DEFAULT -1 COMMENT '新需求,跟标段走,不跟客户走' AFTER `cust_acc_id`,
 ADD INDEX `tender` (`tender_id` ASC);
 ;
+=======
+CREATE TABLE `zh_stage_yjcl`  (
+  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+  `uuid` varchar(36) NOT NULL DEFAULT '' COMMENT 'uuid',
+  `add_sid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '新增期id',
+  `add_sorder` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '新增期序号',
+  `add_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人id',
+  `tid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '标段id',
+  `sid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '期id',
+  `sorder` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '期序号',
+  `name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
+  `m_order` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序',
+  `spec` varchar(255) NOT NULL DEFAULT '' COMMENT '规格型号',
+  `unit` varchar(20) NOT NULL DEFAULT '' COMMENT '单位',
+  `tax` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '税率',
+  `arrive_time` varchar(50) NOT NULL DEFAULT '' COMMENT '到场时间',
+  `source` varchar(255) NOT NULL DEFAULT '' COMMENT '材料来源',
+  `bills_code` varchar(255) NOT NULL DEFAULT '' COMMENT '单据号',
+  `location` varchar(50) NOT NULL DEFAULT '' COMMENT '存放位置',
+  `prepare_pos` varchar(255) NOT NULL DEFAULT '' COMMENT '拟用于部位',
+  `memo` varchar(1000) NOT NULL DEFAULT '' COMMENT '备注',
+  `arrive_qty` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '到场数量',
+  `arrive_tp` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '到场金额',
+  `unit_price` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '单价',
+  `ex_tax_up` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '除税单价',
+  `qty` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '本期数量',
+  `tp` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '本期金额',
+  `pre_qty` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '截止上期数量',
+  `pre_tp` decimal(24, 8) NOT NULL DEFAULT 0 COMMENT '截止上期金额',
+  `pre_used` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '上期是否使用',
+  `shistory` text NULL COMMENT '审批历史',
+  PRIMARY KEY (`id`)
+);
+>>>>>>> ed5450efff3314fa73d5c52cc3a3b3c91df57401

+ 410 - 0
sql/update20240801.sql

@@ -0,0 +1,410 @@
+ALTER TABLE `zh_material`
+ADD COLUMN `rate_tp` decimal(30, 8) NULL DEFAULT NULL COMMENT '建筑含税总金额' AFTER `rate`;
+
+ALTER TABLE `zh_ledger_0`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_1`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_2`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_3`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_4`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_5`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_6`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_7`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_8`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_9`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_10`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_11`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_12`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_13`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_14`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_15`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_16`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_17`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_18`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_19`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_20`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_21`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_22`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_23`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_24`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_25`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_26`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_27`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_28`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_29`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_30`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_31`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_32`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_33`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_34`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_35`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_36`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_37`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_38`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_39`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_40`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_41`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_42`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_43`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_44`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_45`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_46`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_47`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_48`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_49`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_50`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_51`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_52`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_53`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_54`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_55`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_56`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_57`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_58`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_59`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_60`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_61`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_62`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_63`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_64`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_65`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_66`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_67`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_68`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_69`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_70`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_71`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_72`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_73`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_74`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_75`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_76`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_77`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_78`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_79`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_80`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_81`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_82`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_83`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_84`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_85`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_86`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_87`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_88`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_89`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_90`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_91`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_92`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_93`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_94`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_95`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_96`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_97`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_98`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_ledger_99`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+
+ALTER TABLE `zh_revise_bills_0`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_1`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_2`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_3`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_4`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_5`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_6`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_7`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_8`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_9`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_10`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_11`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_12`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_13`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_14`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_15`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_16`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_17`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_18`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_19`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_20`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_21`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_22`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_23`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_24`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_25`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_26`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_27`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_28`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_29`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_30`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_31`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_32`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_33`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_34`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_35`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_36`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_37`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_38`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_39`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_40`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_41`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_42`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_43`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_44`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_45`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_46`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_47`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_48`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_49`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_50`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_51`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_52`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_53`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_54`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_55`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_56`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_57`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_58`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_59`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_60`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_61`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_62`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_63`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_64`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_65`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_66`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_67`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_68`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_69`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_70`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_71`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_72`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_73`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_74`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_75`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_76`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_77`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_78`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_79`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_80`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_81`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_82`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_83`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_84`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_85`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_86`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_87`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_88`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_89`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_90`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_91`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_92`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_93`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_94`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_95`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_96`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_97`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_98`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+ALTER TABLE `zh_revise_bills_99`
+ADD COLUMN `features` varchar(1000) NOT NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
+
+ALTER TABLE `zh_change`
+ADD COLUMN `order_site` int(11) NULL DEFAULT NULL COMMENT 'order_by为自定义时插入到清单id值' AFTER `order_by`;
+
+ALTER TABLE `zh_stage`
+ADD COLUMN `rpt_filed` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '报表是否归档' AFTER `final_auditor_str`;