Просмотр исходного кода

投资进度功能迁移及进度管理功能

ellisran 1 месяц назад
Родитель
Сommit
b129dae024
46 измененных файлов с 663 добавлено и 427 удалено
  1. 49 30
      app/base/base_controller.js
  2. 1 1
      app/const/source_type.js
  3. 2 2
      app/const/sp_page_show.js
  4. 17 0
      app/controller/change_controller.js
  5. 1 1
      app/controller/quality_controller.js
  6. 37 1
      app/controller/schedule_controller.js
  7. 5 6
      app/controller/sub_proj_setting_controller.js
  8. 5 2
      app/middleware/schedule_check.js
  9. 25 18
      app/middleware/tender_check.js
  10. 49 2
      app/public/js/change_information.js
  11. 1 1
      app/public/js/schedule_ledger.js
  12. 2 2
      app/public/js/schedule_plan.js
  13. 3 3
      app/public/js/schedule_stage_gcl.js
  14. 7 7
      app/public/js/schedule_stage_tp.js
  15. 58 0
      app/public/js/schedule_tender.js
  16. 98 108
      app/public/js/setting_manage.js
  17. 18 17
      app/router.js
  18. 2 2
      app/service/budget.js
  19. 20 0
      app/service/change.js
  20. 1 1
      app/service/sub_proj_permission.js
  21. 17 0
      app/service/tender_permission.js
  22. 1 1
      app/view/budget/list.ejs
  23. 9 0
      app/view/change/information.ejs
  24. 3 5
      app/view/schedule/index.ejs
  25. 3 3
      app/view/schedule/ledger.ejs
  26. 17 0
      app/view/schedule/list_sub_menu.ejs
  27. 10 0
      app/view/schedule/list_sub_menu_list.ejs
  28. 16 0
      app/view/schedule/list_sub_mini_menu.ejs
  29. 6 6
      app/view/schedule/modal.ejs
  30. 3 3
      app/view/schedule/plan.ejs
  31. 4 4
      app/view/schedule/stage_gcl.ejs
  32. 1 1
      app/view/schedule/stage_gcl_modal.ejs
  33. 6 6
      app/view/schedule/stage_tp.ejs
  34. 1 1
      app/view/schedule/stage_tp_modal.ejs
  35. 24 0
      app/view/schedule/tender.ejs
  36. 1 0
      app/view/schedule/tender_modal.ejs
  37. 23 161
      app/view/sp_setting/manage.ejs
  38. 1 1
      app/view/sp_setting/manage_modal.ejs
  39. 1 1
      app/view/sp_setting/permission.ejs
  40. 2 2
      app/view/sub_proj/modal.ejs
  41. 0 10
      app/view/tender/tender_sub_menu.ejs
  42. 0 10
      app/view/tender/tender_sub_mini_menu.ejs
  43. 20 3
      config/menu.js
  44. 26 4
      config/web.js
  45. 65 0
      db_script/tender_permission.js
  46. 2 1
      sql/update.sql

+ 49 - 30
app/base/base_controller.js

@@ -40,48 +40,67 @@ class BaseController extends Controller {
             menuList.contract.display = (ctx.subProject.page_show.openContract && contractPermission.length > 0) || ctx.subProject.page_show.openTenderContract || false;
             menuList.contract.children.find(item => item.msg === 'subproj').display = (ctx.subProject.page_show.openContract && contractPermission.length > 0) || false;
             menuList.contract.children.find(item => item.msg === 'tender').display = ctx.subProject.page_show.openTenderContract || false;
-            menuList.financial.display = ctx.subProject.page_show.openFinancial || false;
-            menuList.budget.display = ctx.subProject.page_show.openBudget || false;
-            menuList.payment.display = ctx.subProject.page_show.openPayment || false;
             menuList.quality.display = ctx.subProject.page_show.quality || ctx.subProject.page_show.qualityInspection || false;
             menuList.quality.children.find(item => item.msg === 'quality').display = ctx.subProject.page_show.quality || false;
             menuList.quality.children.find(item => item.msg === 'inspection').display = ctx.subProject.page_show.qualityInspection || false;
             menuList.safe.display = ctx.subProject.page_show.safePayment || ctx.subProject.page_show.safeInspection || false;
             menuList.safe.children.find(item => item.msg === 'payment').display = ctx.subProject.page_show.safePayment || false;
             menuList.safe.children.find(item => item.msg === 'inspection').display = ctx.subProject.page_show.safeInspection || false;
+            const budgetPermission = ctx.subProject.permission.budget_permission;
+            menuList.budget.display = (ctx.subProject.page_show.openBudget && budgetPermission.length > 0) || ctx.subProject.page_show.xxjd || false;
+            menuList.budget.children.find(item => item.msg === 'budget').display = (ctx.subProject.page_show.openBudget && budgetPermission.length > 0) || false;
+            menuList.budget.children.find(item => item.msg === 'schedule').display = ctx.subProject.page_show.xxjd || false;
+            menuList.financial.display = ctx.subProject.page_show.openFinancial || false;
+            menuList.payment.display = ctx.subProject.page_show.openPayment || false;
             for (const index in menuList) {
                 const im = menuList[index];
                 if (!im.url) {
-                    if (index === 'tender') {
-                        im.url = `/sp/${ctx.subProject.id}${ctx.curListUrl}`;
-                    } else if (index === 'contract') {
-                        for (const child of im.children) {
-                            if (child.msg === 'subproj') {
-                                child.url = `/sp/${ctx.subProject.id}/contract/panel`;
-                            } else if (child.msg === 'tender') {
-                                child.url = `/sp/${ctx.subProject.id}/contract/tender`;
+                    switch (index) {
+                        case 'tender':
+                            im.url = `/sp/${ctx.subProject.id}${ctx.curListUrl}`;
+                            break;
+                        case 'contract':
+                            for (const child of im.children) {
+                                if (child.msg === 'subproj') {
+                                    child.url = `/sp/${ctx.subProject.id}/contract/panel`;
+                                } else if (child.msg === 'tender') {
+                                    child.url = `/sp/${ctx.subProject.id}/contract/tender`;
+                                }
+                            }
+                            break;
+                        case 'quality':
+                            for (const child of im.children) {
+                                if (child.msg === 'quality') {
+                                    child.url = `/sp/${ctx.subProject.id}/quality`;
+                                } else if (child.msg === 'inspection') {
+                                    child.url = `/sp/${ctx.subProject.id}/quality/inspection`;
+                                }
                             }
-                        }
-                    } else if (index === 'quality') {
-                        for (const child of im.children) {
-                            if (child.msg === 'quality') {
-                                child.url = `/sp/${ctx.subProject.id}/quality`;
-                            } else if (child.msg === 'inspection') {
-                                child.url = `/sp/${ctx.subProject.id}/quality/inspection`;
+                            break;
+                        case 'safe':
+                            for (const child of im.children) {
+                                if (child.msg === 'payment') {
+                                    child.url = `/sp/${ctx.subProject.id}/safe`;
+                                } else if (child.msg === 'inspection') {
+                                    child.url = `/sp/${ctx.subProject.id}/safe/inspection`;
+                                }
                             }
-                        }
-                    } else if (index === 'safe') {
-                        for (const child of im.children) {
-                            if (child.msg === 'payment') {
-                                child.url = `/sp/${ctx.subProject.id}/safe`;
-                            } else if (child.msg === 'inspection') {
-                                child.url = `/sp/${ctx.subProject.id}/safe/inspection`;
+                            break;
+                        case 'financial':
+                            im.url = `/sp/${ctx.subProject.id}/${im.controller}/${ctx.subProject.financialToUrl}`;
+                            break;
+                        case 'budget':
+                            for (const child of im.children) {
+                                if (child.msg === 'budget') {
+                                    child.url = `/sp/${ctx.subProject.id}/budget`;
+                                } else if (child.msg === 'schedule') {
+                                    child.url = `/sp/${ctx.subProject.id}/schedule/tender`;
+                                }
                             }
-                        }
-                    } else if (index === 'financial') {
-                        im.url = `/sp/${ctx.subProject.id}/${im.controller}/${ctx.subProject.financialToUrl}`;
-                    } else {
-                        im.url = `/sp/${ctx.subProject.id}/${im.controller}`;
+                            break;
+                        default:
+                            im.url = `/sp/${ctx.subProject.id}/${im.controller}`;
+                            break;
                     }
                 }
             }

+ 1 - 1
app/const/source_type.js

@@ -11,7 +11,7 @@ const sourceTypeData = [
     { id: 40, name: '安全计量', key: 'safe_stage', params: { safe_stage_id: 'uuid' } },
     { id: 100, name: '支付审批', key: 'payment', params: { tender_id: 1, detail_id: 1 } },
     { id: 101, name: '安全生产费', key: 'payment_safe', params: { tender_id: 1, detail_id: 1 } },
-    { id: 200, name: '动态投资', key: 'budget', params: { sp_id: 'uuid', budget_id: 1 } },
+    { id: 200, name: '项目进度', key: 'budget', params: { sp_id: 'uuid', budget_id: 1 } },
     { id: 300, name: '合同管理', key: 'contract_management', params: {} },
     // { id: 301, name: '标段合同', key: 'tender_contract' },
 ];

+ 2 - 2
app/const/sp_page_show.js

@@ -19,7 +19,7 @@ const managerPageControl = [
     { title: '决策大屏', name: 'openDataCollect', value: pageStatus.show, type: 'checkbox', tip: '开启后,前台配置用户权限后方可显示' },
     { title: '项目合同', name: 'openContract', value: pageStatus.show, type: 'checkbox' },
     { title: '资料管理', name: 'openFile', value: pageStatus.show, type: 'checkbox' },
-    { title: '动态投资', name: 'openBudget', value: pageStatus.show, type: 'checkbox', tip: '开启后,前台配置用户权限后方可显示' },
+    { title: '项目进度', name: 'openBudget', value: pageStatus.show, type: 'checkbox', tip: '开启后,前台配置用户权限后方可显示' },
     { title: '支付审批', name: 'openPayment', value: pageStatus.show, type: 'checkbox', tip: '开启后,前台配置用户权限后方可显示' },
     { title: '资金监管', name: 'openFinancial', value: pageStatus.show, type: 'checkbox' },
 ];
@@ -28,7 +28,6 @@ const tenderPageControl = [
     { title: '部位台帐', name: 'bwtz', value: pageStatus.show, type: 'checkbox', tip: '「部位台帐」显示在「0号台帐」以及「各期计量」侧栏菜单中', tipClass: '' },
     { title: '其他台账', name: 'stageExtra', value: pageStatus.show, type: 'checkbox' },
     { title: '合同支付独立审批', name: 'phasePay', value: pageStatus.show, type: 'checkbox' },
-    { title: '投资进度', name: 'xxjd', value: pageStatus.show, type: 'checkbox' },
     { title: '材料调差', name: 'openMaterial', value: pageStatus.show, type: 'checkbox' },
     { title: '过程结算', name: 'openSettle', value: pageStatus.show, type: 'checkbox' },
     { title: '施工日志', name: 'openConstruction', value: pageStatus.show, type: 'checkbox' },
@@ -37,6 +36,7 @@ const tenderPageControl = [
     { title: '质量巡检', name: 'qualityInspection', value: pageStatus.show, type: 'checkbox' },
     { title: '安全计量', name: 'safePayment', value: pageStatus.show, type: 'checkbox' },
     { title: '安全巡检', name: 'safeInspection', value: pageStatus.show, type: 'checkbox' },
+    { title: '标段进度', name: 'xxjd', value: pageStatus.show, type: 'checkbox' },
 ];
 // 报表相关开关
 const reportPageControl = [

+ 17 - 0
app/controller/change_controller.js

@@ -474,6 +474,14 @@ module.exports = app => {
 
                 // 处理清单数据
                 const removeSettleNum = change.status !== audit.change.status.checked ? await ctx.service.changeSettleList.updateChangeList(change.cid, settleBills, settlePos, changeList) : 0;
+
+                let revising = false;
+                // 判断是否台账修订中,修订中则不获取changeLedger及changePos值
+                const lastRevise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
+                if (lastRevise && lastRevise.status !== audit.revise.status.checked) {
+                    // throw '台账修订中,无法操作台账数据';
+                    revising = true;
+                }
                 const renderData = {
                     tender,
                     change,
@@ -503,6 +511,7 @@ module.exports = app => {
                     removeSettleNum,
                     deleteFilePermission,
                     changeMode: tenderData.c_mode,
+                    revising,
                 };
                 // 获取是否已存在调用变更令
                 let changeUsedData = await ctx.service.stageChange.getAllFinalUsedData(ctx.tender.id, change.cid);
@@ -842,6 +851,10 @@ module.exports = app => {
                 if (!(ctx.change.status === audit.change.status.uncheck || ctx.change.status === audit.change.status.checkNo || ctx.change.status === audit.change.status.revise)) {
                     throw '该变更令当前无法上报';
                 }
+                const revising = await ctx.service.change.checkRevising(ctx.change.tid, ctx.change.cid);
+                if (revising) {
+                    throw '台账修订中并本变更令存在新增清单,无法上报';
+                }
                 // 判断是否是修订,判断有无审批人员作弊
                 if ((ctx.change.status === audit.change.status.revise || ctx.change.is_revise) && ctx.tender.info.shenpi.change === shenpiConst.sp_status.sqspr) {
                     // 获取上一次的审批人流程
@@ -1132,6 +1145,10 @@ module.exports = app => {
                 const pid = this.ctx.session.sessionProject.id;
                 switch (status) {
                     case 3:// 审批通过
+                        const revising = await ctx.service.change.checkRevising(changeData.tid, changeData.cid);
+                        if (revising) {
+                            throw '台账修订中并本变更令存在新增清单,无法审批通过';
+                        }
                         result = await ctx.service.change.approvalSuccess(pid, data, changeData);
                         break;
                     // case 4:// 审批终止

+ 1 - 1
app/controller/quality_controller.js

@@ -148,7 +148,7 @@ module.exports = app => {
                 }
                 let uids;
                 let auditList = [];
-                const tenderPermissionKeys = ['quality', 'inspection', 'safe_inspection', 'safe_payment'];
+                const tenderPermissionKeys = ['quality', 'inspection', 'safe_inspection', 'safe_payment', 'schedule'];
                 const tPsKeys = {
                     quality: ['quality', 'inspection'],
                     safe: ['safe_inspection', 'safe_payment'],

+ 37 - 1
app/controller/schedule_controller.js

@@ -37,11 +37,46 @@ module.exports = app => {
             if (await this._getLastReviseStatus(ctx)) {
                 throw '台账修订中,请勿修改提交进度数据';
             }
-            if (ctx.tender.schedule_permission !== scheduleConst.permission.edit) {
+            if (!ctx.tender.user_permission.schedule.edit) {
                 throw '权限不足,无法修改进度数据';
             }
         }
 
+        async tender(ctx) {
+            try {
+                if (!ctx.subProject.page_show.xxjd) throw '该功能已关闭';
+
+                const renderData = {
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.tender),
+                };
+
+                const accountList = await ctx.service.projectAccount.getAllSubProjectAccount(ctx.subProject);
+                renderData.accountList = accountList;
+                const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
+                const accountGroupList = unitList.map(item => {
+                    const groupList = accountList.filter(item1 => item1.company === item.name);
+                    return { groupName: item.name, groupList };
+                }).filter(x => { return x.groupList.length > 0; });
+                // const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
+                // renderData.accountGroup = unitList.map(item => {
+                //     const groupList = accountList.filter(item1 => item1.company === item.name);
+                //     return { groupName: item.name, groupList };
+                // });
+                renderData.accountGroup = accountGroupList;
+                renderData.accountInfo = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                renderData.tenderList = await ctx.service.tender.getSpecList(ctx.service.tenderPermission, 'schedule', ctx.session.sessionUser.is_admin ? 'all' : '');
+                renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.subProject);
+                renderData.selfCategoryLevel = this.ctx.subProject.permission.self_category_level;
+                renderData.permissionConst = ctx.service.tenderPermission.partPermissionConst('schedule');
+                renderData.permissionBlock = ctx.service.tenderPermission.partPermissionBlock('schedule');
+                await this.layout('schedule/tender.ejs', renderData, 'schedule/tender_modal.ejs');
+            } catch (err) {
+                ctx.log(err);
+                ctx.postError(err, '无法查看标段进度数据');
+                ctx.redirect(`/sp/${ctx.subProject.id}/dashboard`);
+            }
+        }
+
         async index(ctx) {
             try {
                 const schedule = await ctx.service.schedule.getDataByCondition({ tid: ctx.tender.id });
@@ -72,6 +107,7 @@ module.exports = app => {
                     preUrl: '/tender/' + ctx.tender.id,
                     scPermission: scheduleConst.permission,
                     revising: await this._getLastReviseStatus(ctx),
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.schedule.index),
                 };
                 await this.layout('schedule/index.ejs', renderData, 'schedule/modal.ejs');
             } catch (err) {

+ 5 - 6
app/controller/sub_proj_setting_controller.js

@@ -567,7 +567,6 @@ module.exports = app => {
                 const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
                 const accountGroupList = unitList.map(item => {
                     const groupList = accountList.filter(item1 => item1.company === item.name);
-                    console.log(groupList);
                     return { groupName: item.name, groupList };
                 }).filter(x => { return x.groupList.length > 0; });
                 // console.log(accountGroupList);
@@ -593,7 +592,7 @@ module.exports = app => {
                     change_type_list: shenpiConst.change_type_list,
                     subProjects,
                 };
-                const permissionKey = ['quality', 'inspection', 'safe_inspection', 'safe_payment'];
+                const permissionKey = ['quality', 'inspection', 'safe_inspection', 'safe_payment', 'schedule'];
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.permissionConst = ctx.service.tenderPermission.partPermissionConst(permissionKey);
                 renderData.permissionBlock = ctx.service.tenderPermission.partPermissionBlock(permissionKey);
@@ -619,7 +618,7 @@ module.exports = app => {
                 }
                 // 单个tenderPermission字段用这个
                 // const permissionKey = ['quality', 'inspection', 'safe_inspection', 'safe_payment'];
-                const permissionKey = [];
+                const permissionKey = ['schedule'];
                 // 多个tenderPermission字段融合处理用这个
                 const tPsKeys = {
                     quality: ['quality', 'inspection'],
@@ -646,7 +645,7 @@ module.exports = app => {
                             t.permission = await ctx.service.tenderTourist.getTouristPermission(t);
                         }
                         responseData.data.tourists = tourists;
-                        responseData.data.scheduleAuditList = await ctx.service.scheduleAudit.getAllDataByCondition({ where: { tid: tender.id } });
+                        // responseData.data.scheduleAuditList = await ctx.service.scheduleAudit.getAllDataByCondition({ where: { tid: tender.id } });
                         responseData.data.contractAuditList = await ctx.service.contractAudit.getList({ tid: tender.id });
                         responseData.data.constructionAuditList = await ctx.service.constructionAudit.getList(tender.id);
                         for (const key of permissionKey) {
@@ -659,8 +658,8 @@ module.exports = app => {
                     case 'copy2otu':
                         if (data.userType === 'tourist') {
                             await ctx.service.tenderTourist.setOtherTender(data.tidList, data.auditList);
-                        } else if (data.userType === 'schedule') {
-                            await ctx.service.scheduleAudit.setOtherTender(data.tidList, data.auditList);
+                        // } else if (data.userType === 'schedule') {
+                        //     await ctx.service.scheduleAudit.setOtherTender(data.tidList, data.auditList);
                         } else if (data.userType === 'contract') {
                             await ctx.service.contractAudit.setOtherTender(data.tidList, data.auditList);
                         } else if (data.userType === 'construction') {

+ 5 - 2
app/middleware/schedule_check.js

@@ -17,7 +17,10 @@ module.exports = options => {
      */
     return function* scheduleCheck(next) {
         try {
-            if (this.tender.schedule_permission === scPermission.no) {
+            if (!this.subProject.page_show.xxjd) {
+                throw '该功能已关闭';
+            }
+            if (!this.tender.user_permission.schedule.view) {
                 throw '您无权查看该内容';
             }
             yield next;
@@ -36,7 +39,7 @@ module.exports = options => {
             if (this.helper.isWap(this.request)) {
                 this.redirect('/wap/subproj');
             } else {
-                err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect(`/sp/${ctx.subProject.id}/list`);
+                err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect(`/sp/${ctx.subProject.id}/schedule/tender`);
             }
         }
     };

+ 25 - 18
app/middleware/tender_check.js

@@ -10,7 +10,7 @@
 
 const auditConst = require('../const/audit').ledger;
 const messageType = require('../const/message_type');
-const scPermission = require('../const/schedule').permission;
+// const scPermission = require('../const/schedule').permission;
 const buildStatus = require('../const/tender').buildStatus;
 
 module.exports = options => {
@@ -87,11 +87,17 @@ module.exports = options => {
             const changePlanAuditorsId = this.helper._.map(changePlanAuditors, 'aid');
             const tenderPermission = this.session.sessionUser.permission ? this.session.sessionUser.permission.tender : null;
             const isTenderTourist = yield this.service.tenderTourist.getDataByCondition({ tid: tender.id, user_id: accountId });
-            const scheduleUser = subProject.page_show.xxjd ? yield this.service.scheduleAudit.getDataByCondition({ tid: tender.id, audit_id: this.session.sessionUser.accountId }) : [];
+            // const scheduleUser = subProject.page_show.xxjd ? yield this.service.scheduleAudit.getDataByCondition({ tid: tender.id, audit_id: this.session.sessionUser.accountId }) : [];
             // 判断访问人是否具有游客身份
             tender.isTourist = isTenderTourist !== null;
             // 游客权限
             tender.touristPermission = yield this.service.tenderTourist.getTouristPermission(isTenderTourist);
+            // tender_permission表查看权限
+            if (this.session.sessionUser.is_admin) {
+                tender.user_permission = this.service.tenderPermission.getAdminPermission();
+            } else {
+                tender.user_permission = yield this.service.tenderPermission.getUserPermission(tender.id, this.session.sessionUser.accountId);
+            }
             if (auditorsId.indexOf(accountId) === -1 && tender.data.user_id !== accountId &&
                 (tenderPermission === null || tenderPermission === undefined || tenderPermission.indexOf('2') === -1) &&
                 stageAuditorsId.indexOf(accountId) === -1 && auditAssistsId.indexOf(accountId) === -1 &&
@@ -100,7 +106,8 @@ module.exports = options => {
                 changeProjectAuditorsId.indexOf(accountId) === -1 && changeProjectXsAuditorsId.indexOf(accountId) === -1 &&
                 changeApplyAuditorsId.indexOf(accountId) === -1 && changePlanAuditorsId.indexOf(accountId) === -1 &&
                 advanceAuditorsId.indexOf(accountId) === -1 && !this.session.sessionUser.is_admin && !isTenderTourist &&
-                (!scheduleUser || scheduleUser.permission === scPermission.no)) {
+                this.service.tenderPermission.getShowPermission(tender.user_permission)) {
+                // && (!scheduleUser || scheduleUser.permission === scPermission.no)) {
                 throw '您无权查看该项目';
             }
 
@@ -111,21 +118,21 @@ module.exports = options => {
             this.tender = tender;
             // this.session.sessionProject.page_show = yield this.service.project.getPageshow(this.session.sessionProject.id);
             // 投资进度权限获取
-            let schedule_permission = scPermission.no;
-            if (this.session.sessionUser.accountId === tender.data.user_id) {
-                schedule_permission = scPermission.edit;
-            } else {
-                if (scheduleUser) {
-                    if (tender.isTourist && scheduleUser.permission === scPermission.no) {
-                        schedule_permission = scPermission.show;
-                    } else {
-                        schedule_permission = scheduleUser.permission;
-                    }
-                } else if (tender.isTourist) {
-                    schedule_permission = scPermission.show;
-                }
-            }
-            tender.schedule_permission = schedule_permission;
+            // let schedule_permission = scPermission.no;
+            // if (this.session.sessionUser.accountId === tender.data.user_id) {
+            //     schedule_permission = scPermission.edit;
+            // } else {
+            //     if (scheduleUser) {
+            //         if (tender.isTourist && scheduleUser.permission === scPermission.no) {
+            //             schedule_permission = scPermission.show;
+            //         } else {
+            //             schedule_permission = scheduleUser.permission;
+            //         }
+            //     } else if (tender.isTourist) {
+            //         schedule_permission = scPermission.show;
+            //     }
+            // }
+            // tender.schedule_permission = schedule_permission;
             yield next;
         } catch (err) {
             console.log(err);

+ 49 - 2
app/public/js/change_information.js

@@ -1294,12 +1294,16 @@ $(document).ready(() => {
             }
             if (delList.length) {
                 postData(window.location.pathname + '/save', {type: 'del', ids: delList, postData: lastSelect ? lastSelect.order : null}, function (result) {
+                    _.remove(changeList, function (item) {
+                        return _.includes(delList, item.id);
+                    });
                     changeSpreadSheet.deleteRows(row, count);
                     changeSpreadSheet.zh_data.splice(row, count);
                     changeSpreadObj.countSum();
                     changeSpreadSheet.setSelection(0, 0, 1, 1);
                     changeSpreadObj.refreshXmjData();
                     changeSpreadObj.refreshActn();
+                    refreshBtn();
                 });
             }
         };
@@ -1956,6 +1960,7 @@ $(document).ready(() => {
                         changeSpreadObj.refreshXmjData();
                         changeSpreadObj.refreshActn();
                     }
+                    refreshBtn();
                 });
             }
         };
@@ -3399,6 +3404,9 @@ $(document).ready(() => {
             }
             if (delList.length) {
                 postData(window.location.pathname + '/save', {type: 'del', ids: delList, postData: lastSelect ? lastSelect.order : null}, function (result) {
+                    _.remove(changeList, function (item) {
+                        return _.includes(delList, item.id);
+                    });
                     const loadResult = {
                         delete: selects,
                     }
@@ -3418,6 +3426,7 @@ $(document).ready(() => {
                     ledgerTreeSpreadObj.refreshTree(ledgerSheet, refreshData);
                     ledgerSheet.setSelection(0, 0, 1, 1);
                     ledgerTreeSpreadObj.refreshPosData();
+                    refreshBtn();
                 });
             }
         };
@@ -3932,6 +3941,9 @@ $(document).ready(() => {
                 postData(window.location.pathname + '/save', {type: 'del', ids: delList, postData: lastSelect ? lastSelect.order : null}, function (result) {
                     pos.removeDatas(selects);
                     posSheet.deleteRows(row, count);
+                    _.remove(changeList, function (item) {
+                        return _.includes(delList, item.id);
+                    });
                     const billsNode = SpreadJsObj.getSelectObject(ledgerSheet);
                     const loadResult = {};
                     // 判断是移除还是更新数量和金额
@@ -3957,6 +3969,7 @@ $(document).ready(() => {
                             ledgerTreeSpreadObj.refreshPosData();
                         }
                     }
+                    refreshBtn();
                 });
             }
         };
@@ -5484,7 +5497,7 @@ $(document).ready(() => {
                 firstLoad = false;
             }
             if (readOnly) {
-                postData(preUrl + '/defaultBills', {}, function (result) {
+                postData(preUrl + '/defaultBills', {from: 'revise'}, function (result) {
                     ledgerList = result.bills;
                     posList = result.pos;
                     showLedgerAndPos();
@@ -5493,6 +5506,7 @@ $(document).ready(() => {
                 showLedgerAndPos();
             }
         }
+        refreshBtn();
     }
 
     function showLedgerAndPos() {
@@ -5514,7 +5528,7 @@ $(document).ready(() => {
     }
 
     function getAndCheck(showTips = false) {
-        postData(preUrl + '/defaultBills', {}, function (result) {
+        postData(preUrl + '/defaultBills', {from: 'revise'}, function (result) {
             ledgerList = result.bills;
             posList = result.pos;
             // if (!readOnly) {
@@ -5572,6 +5586,39 @@ $(document).ready(() => {
         getAndCheck(true);
     });
 
+    function refreshBtn() {
+        if (checkRevising() && ! $('#sp-btn .need-check-revising').hasClass('disabled')) {
+            $('#sp-btn .need-check-revising a').addClass('disabled');
+            $('#sp-btn .need-check-revising').attr('data-toggle', 'tooltip');
+            $('#sp-btn .need-check-revising').attr('data-placement', 'bottom');
+            $('#sp-btn .need-check-revising').attr('title', '');
+            $('#sp-btn .need-check-revising').attr('data-original-title', '台账修订中并本变更令存在新增清单,无法上报和审批通过');
+            $('[data-toggle="tooltip"]').tooltip();
+        } else {
+            $('#sp-btn .need-check-revising a').removeClass('disabled');
+            $('#sp-btn .need-check-revising').removeAttr('data-toggle');
+            $('#sp-btn .need-check-revising').removeAttr('data-placement');
+            $('#sp-btn .need-check-revising').removeAttr('title');
+            $('#sp-btn .need-check-revising').removeAttr('data-original-title');
+        }
+    }
+
+    function checkRevising() {
+        let flag = false;
+        if (revising) {
+            // 判断清单里是否又新增清单,有则返回true
+            for (const cl of changeList) {
+                if (cl.gcl_id || cl.mx_id) {
+                    if (_.findIndex(changeLedgerList, { id: cl.gcl_id }) !== -1 || _.findIndex(changePosList, { id: cl.mx_id }) !== -1) {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return flag;
+    }
+
     // 显示层次
     (function (select, sheet) {
         $(select).click(function () {

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

@@ -6,7 +6,7 @@
  * @version
  */
 function getTenderId() {
-    return window.location.pathname.split('/')[2];
+    return window.location.pathname.split('/')[5];
 }
 const selects = [];
 let slh = [];

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

@@ -6,7 +6,7 @@
  * @version
  */
 function getTenderId() {
-    return window.location.pathname.split('/')[2];
+    return window.location.pathname.split('/')[5];
 }
 $(function () {
     autoFlashHeight();
@@ -104,7 +104,7 @@ $(function () {
     ledgerSpread.getActiveSheet().frozenColumnCount(6);
     ledgerSpread.getActiveSheet().options.frozenlineColor = '#93b5e4';
 
-    postData('/tender/' + getTenderId() + '/schedule/ledger/load', {}, function (data) {
+    postData('/sp/' + spid + '/schedule/tender/' + getTenderId() + '/ledger/load', {}, function (data) {
         // let treeData = [];
         // for(const sl of selectedLedgerList) {
         //     const one = _.find(data, { 'ledger_id' : sl });

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

@@ -6,7 +6,7 @@
  * @version
  */
 function getTenderId() {
-    return window.location.pathname.split('/')[2];
+    return window.location.pathname.split('/')[5];
 }
 $(function () {
     autoFlashHeight();
@@ -103,7 +103,7 @@ $(function () {
     ledgerSpread.getActiveSheet().frozenColumnCount(6);
     ledgerSpread.getActiveSheet().options.frozenlineColor = '#93b5e4';
 
-    postData('/tender/' + getTenderId() + '/schedule/ledger/load', {}, function (data) {
+    postData('/sp/' + spid + '/schedule/tender/' + getTenderId() + '/ledger/load', {}, function (data) {
         // let treeData = [];
         // for(const sl of selectedLedgerList) {
         //     const one = _.find(data, { 'ledger_id' : sl });
@@ -526,7 +526,7 @@ $(function () {
             });
         },
         setSjs: function (order) {
-            postData('/tender/' + getTenderId() + '/schedule/stage/gcl/' + order + '/load', {}, function (data) {
+            postData('/sp/' + spid + '/schedule/tender/' + getTenderId() + '/stage/gcl/' + order + '/load', {}, function (data) {
                 const calcList = ['total_price'];
                 const showList = ['plan_gcl', 'plan_tp', 'next_plan_gcl', 'next_plan_tp', 'end_plan_gcl', 'end_plan_tp', 'year_plan_gcl', 'year_plan_tp',
                     'sj_gcl', 'sj_tp', 'year_sj_gcl', 'year_sj_tp', 'end_sj_gcl', 'end_sj_tp',

+ 7 - 7
app/public/js/schedule_stage_tp.js

@@ -6,7 +6,7 @@
  * @version
  */
 function getTenderId() {
-    return window.location.pathname.split('/')[2];
+    return window.location.pathname.split('/')[5];
 }
 $(function () {
     autoFlashHeight();
@@ -84,7 +84,7 @@ $(function () {
     ledgerSpread.getActiveSheet().options.frozenlineColor = '#93b5e4';
 
     if (curScheduleStage && curScheduleStage.order) {
-        postData('/tender/' + getTenderId() + '/schedule/stage/' + curScheduleStage.order + '/load', {}, function (data) {
+        postData('/sp/' + spid + '/schedule/tender/' + getTenderId() + '/stage/' + curScheduleStage.order + '/load', {}, function (data) {
             const calcList = ['year_gather_tp',
                 'qc_qty', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'contract_pc_tp', 'qc_pc_tp', 'pc_tp',
                 'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp',
@@ -173,7 +173,7 @@ $(function () {
             return;
         }
         const _self = $(this);
-        postData('/tender/'+ getTenderId() + '/schedule/stage/save', {type: 'add_stage', postData: { yearmonth, order }}, function (result) {
+        postData('/sp/' + spid + '/schedule/tender/'+ getTenderId() + '/stage/save', {type: 'add_stage', postData: { yearmonth, order }}, function (result) {
             _self.addClass('disabled').attr('disabled', true);
             toastr.success('新增成功');
             setTimeout(function () {
@@ -190,7 +190,7 @@ $(function () {
             return;
         }
         const _self = $(this);
-        postData('/tender/'+ getTenderId() + '/schedule/stage/save', {type: 'reload_stage', postData: { id, order }}, function (result) {
+        postData('/sp/' + spid + '/schedule/tender/'+ getTenderId() + '/stage/save', {type: 'reload_stage', postData: { id, order }}, function (result) {
             _self.addClass('disabled').attr('disabled', true);
             toastr.success('重新生成成功');
             setTimeout(function () {
@@ -202,11 +202,11 @@ $(function () {
     $('#del-stage').click(function () {
         const id = parseInt($(this).data('id'));
         const _self = $(this);
-        postData('/tender/'+ getTenderId() + '/schedule/stage/save', {type: 'del_stage', postData: { id }}, function (result) {
+        postData('/sp/' + spid + '/schedule/tender/'+ getTenderId() + '/stage/save', {type: 'del_stage', postData: { id }}, function (result) {
             _self.addClass('disabled').attr('disabled', true);
             toastr.success('删除成功');
             setTimeout(function () {
-                window.location.href = '/tender/'+ getTenderId() + '/schedule/stage';
+                window.location.href = '/sp/' + spid + '/schedule/tender/'+ getTenderId() + '/stage';
             }, 500)
         })
     });
@@ -246,7 +246,7 @@ function calcGatherTpAndUpdate(tree) {
         console.log(schedule.stage_sj_tp, final_total_tp);
         if (curScheduleStage.tp !== total_tp || schedule.stage_sj_tp !== final_total_tp) {
             // 更新计量总金额并更新金额模式总金额
-            postData('/tender/' + getTenderId() + '/schedule/stage/save', { type: 'update_tp', postData: { tp: total_tp, stage_sj_tp: final_total_tp, order: curScheduleStage.order } }, function (data) {
+            postData('/sp/' + spid + '/schedule/tender/' + getTenderId() + '/stage/save', { type: 'update_tp', postData: { tp: total_tp, stage_sj_tp: final_total_tp, order: curScheduleStage.order } }, function (data) {
                 console.log('总金额已更新');
             })
         }

+ 58 - 0
app/public/js/schedule_tender.js

@@ -0,0 +1,58 @@
+'use strict';
+
+const tenderListSpec = (function(){
+    function getTenderNodeHtml(node, arr, pid) {
+        const html = [];
+        html.push('<tr pid="' + pid + '">');
+        // 名称
+        html.push('<td style="min-width: 200px" class="in-' + node.level + '">');
+        if (node.cid) {
+            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ', node.name);
+        } else {
+            html.push('<span class="text-muted mr-2">');
+            html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+            html.push('</span>');
+            //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
+            html.push(`<a href="/sp/${spid}/schedule/tender/${node.id}" name="name" style="min-width: 200px;word-break:break-all;" id="${node.id}">${node.name}</a>`);
+        }
+        html.push('</td>');
+
+        // 创建时间
+        html.push('<td style="width: 8%" class="text-center">');
+        html.push(node.create_time ? moment(node.create_time).format('YYYY-MM-DD HH:mm:ss') : '');
+        html.push('</td>');
+        // 设置
+        if (is_admin) {
+            html.push('<td style="width: 10%" class="text-center">');
+            if (!node.cid) {
+                html.push(`<a href="javascript:void(0);" data-toggle="modal" data-tid="${node.id}" class="btn btn-sm btn-outline-primary member-manage"> 成员管理 </a>`);
+            }
+            html.push('</td>');
+        }
+        html.push('</tr>');
+        return html.join('');
+    }
+    function getTenderTreeHeaderHtml() {
+        const html = [];
+        const left = $('#sub-menu').css('display') === 'none' ? 56 : 176;
+        html.push('<table class="table table-hover table-bordered">');
+        html.push('<thead style="position: sticky;left:'+ left +'px;top: 0;" class="text-center">', '<tr>');
+        html.push('<th style="min-width: 50%">',  '标段名称',  tenderListOrder.getOrderButton('name'), '</th>');
+        html.push('<th style="width: 15%">', '创建时间',  tenderListOrder.getOrderButton('create_time'), '</th>');
+        if (is_admin) {
+            html.push('<th style="width: 15%">', '操作', '</th>');
+        }
+        html.push('</tr>');
+        html.push('</thead>');
+        return html.join('');
+    }
+    return { getTenderNodeHtml, getTenderTreeHeaderHtml }
+})();
+
+$(document).ready(() => {
+    const memberPermission = MemberPermission();
+    $('body').on('click', '.member-manage', function(){
+        const tid = this.getAttribute('data-tid');
+        memberPermission.show({ data: { tid }, loadUrl: `/sp/${spid}/quality/member`, saveUrl: `/sp/${spid}/quality/memberSave`});
+    });
+});

+ 98 - 108
app/public/js/setting_manage.js

@@ -173,7 +173,7 @@ $(document).ready(() => {
 
     const tabTypes = {
         tourist: '游客',
-        schedule: '投资进度',
+        schedule: '标段进度',
         contract: '合同管理',
         construction: '施工日志',
         quality: '质量管理',
@@ -181,7 +181,7 @@ $(document).ready(() => {
     };
     const tabTypeKeys = ['tourist', 'schedule', 'contract', 'construction', 'quality', 'safe'];
     // 单个tenderPermission字段用这个
-    const tenderPermissionKeys = [];
+    const tenderPermissionKeys = ['schedule'];
     // 多个tenderPermission字段融合处理用这个
     const tPsKeys = {
         quality: ['quality', 'inspection'],
@@ -219,7 +219,7 @@ $(document).ready(() => {
             cur_uid = result.tender.user_id;
             setShenpiHtml(result.shenpi, result.tender, result.revising);
             setTouristHtml(result.tourists);
-            setScheduleHtml(result.scheduleAuditList);
+            // setScheduleHtml(result.scheduleAuditList);
             setContractHtml(result.contractAuditList);
             setConstructionHtml(result.constructionAuditList);
             for (const tpkey of tenderPermissionKeys) {
@@ -246,8 +246,8 @@ $(document).ready(() => {
             const href = $(this).attr('href');
             if (href === '#guest') {
                 $('#add_user_dropdownMenuButton').attr('data-type', 'tourist');
-            } else if (href === '#tzpro') {
-                $('#add_user_dropdownMenuButton').attr('data-type', 'schedule');
+            // } else if (href === '#tzpro') {
+            //     $('#add_user_dropdownMenuButton').attr('data-type', 'schedule');
             } else if (href === '#htgl') {
                 $('#add_user_dropdownMenuButton').attr('data-type', 'contract');
                 $('#contract-tip').show();
@@ -269,7 +269,7 @@ $(document).ready(() => {
                 setTimeout(() => updateSelectedMarks(), 0);
             }
         }
-        
+
     });
 
     $('body').on('click', '.c-body a', function (e) {
@@ -294,34 +294,34 @@ $(document).ready(() => {
     });
 
     // 权限更改
-    $('body').on('click', '#schedule-users input[type="checkbox"]', function () {
-        let permission = scPermission.no;
-        const value = parseInt($(this).data('zhi'));
-        if ($(this).is(':checked')) {
-            if (value === scPermission.edit) {
-                permission = scPermission.edit;
-                $(this).parents('td').siblings().find('input').prop('checked', true);
-            } else if (value === scPermission.show) {
-                permission = scPermission.show;
-            }
-        } else {
-            if (value === scPermission.edit) {
-                permission = scPermission.show;
-            } else if (value === scPermission.show) {
-                permission = scPermission.no;
-                $(this).parents('td').siblings().find('input').prop('checked', false);
-            }
-        }
-        const id = parseInt($(this).data('id'));
-        const prop = {
-            id,
-            permission,
-            type: 'edit',
-        };
-        const _self = $(this);
-        postData('/tender/' + cur_tenderid + '/schedule/audit/save', prop, function (data) {
-        });
-    });
+    // $('body').on('click', '#schedule-users input[type="checkbox"]', function () {
+    //     let permission = scPermission.no;
+    //     const value = parseInt($(this).data('zhi'));
+    //     if ($(this).is(':checked')) {
+    //         if (value === scPermission.edit) {
+    //             permission = scPermission.edit;
+    //             $(this).parents('td').siblings().find('input').prop('checked', true);
+    //         } else if (value === scPermission.show) {
+    //             permission = scPermission.show;
+    //         }
+    //     } else {
+    //         if (value === scPermission.edit) {
+    //             permission = scPermission.show;
+    //         } else if (value === scPermission.show) {
+    //             permission = scPermission.no;
+    //             $(this).parents('td').siblings().find('input').prop('checked', false);
+    //         }
+    //     }
+    //     const id = parseInt($(this).data('id'));
+    //     const prop = {
+    //         id,
+    //         permission,
+    //         type: 'edit',
+    //     };
+    //     const _self = $(this);
+    //     postData('/tender/' + cur_tenderid + '/schedule/audit/save', prop, function (data) {
+    //     });
+    // });
 
     // 权限更改
     $('body').on('click', '#contract-users input[type="checkbox"]', function () {
@@ -459,17 +459,7 @@ $(document).ready(() => {
                 });
                 updateSelectedMarks();
             });
-        } else if (_.includes(Object.keys(tPsKeys), type)) {
-            postData('/sp/' + spid + '/quality/' + cur_tenderid + '/audit/save', { type: 'del-audit', id, key: type, together: 1 }, function (data) {
-                $('#'+ type + '-users').find('tr[data-uid="'+ id +'"]').remove();
-                $('#remove-user').modal('hide');
-                selectedUserIdsByType[type] = selectedUserIdsByType[type].filter(function(userId) {
-                    return userId !== showId;
-                });
-                updateSelectedMarks();
-            });
         } else {
-            
             const prop = {
                 id: id,
                 type: 'del',
@@ -482,7 +472,7 @@ $(document).ready(() => {
                 });
                 updateSelectedMarks();
             });
-            
+
         }
 
     });
@@ -530,7 +520,7 @@ $(document).ready(() => {
         const currentDropdownType = $('#add_user_dropdownMenuButton').attr('data-type');
         let currentSelectedIdsForType = [];
         if (currentDropdownType && selectedUserIdsByType.hasOwnProperty(currentDropdownType)) {
-            currentSelectedIdsForType = selectedUserIdsByType[currentDropdownType]; 
+            currentSelectedIdsForType = selectedUserIdsByType[currentDropdownType];
         }
         let html = '';
         accountGroup.forEach((group, idx) => {
@@ -624,48 +614,48 @@ $(document).ready(() => {
                     $('#tourist-users').append(html);
                     updateSelectedMarks();
                 });
-            } else if (type === 'schedule') {
-                const user = _.find(accountList, function (item) {
-                    return item.id === id;
-                });
-                const saIdList = [];
-                for (let i = 0; i < $('#schedule-users tr').length; i++) {
-                    saIdList.push(parseInt($('#schedule-users tr').eq(i).data('uid')));
-                }
-                if (_.includes(saIdList, id)) {
-                    toastr.error('该用户已存在列表中,无需重复添加');
-                    e.stopPropagation();
-                    return;
-                }
-
-                const prop = {
-                    audit_id: id,
-                    type: 'add',
-                };
-                postData('/tender/' + cur_tenderid + '/schedule/audit/save', prop, function (data) {
-                    selectedUserIdsByType.schedule.push(user.id);
-                    const html = `<tr data-uid="${user.id}" data-id="${data.id}">
-                                    <td>${user.name}</td>
-                                    <td>${user.role}</td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" data-zhi="${scPermission.show}" data-id="${data.id}" id="${data.id}_customRadio41" name="customCheckbox" class="custom-control-input" checked>
-                                            <label class="custom-control-label" for="${data.id}_customRadio41"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" data-zhi="${scPermission.edit}" data-id="${data.id}" id="${data.id}_customRadio42" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="${data.id}_customRadio42"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <a href="#remove-user1" data-id="${data.id}" data-show-id="${user.id}" data-toggle="modal" data-target="#remove-user" class="btn btn-sm btn-outline-danger remove-schedule-user">移除</a>
-                                    </td>
-                                </tr>`;
-                    $('#schedule-users').append(html);
-                    updateSelectedMarks();
-                });
+            // } else if (type === 'schedule') {
+            //     const user = _.find(accountList, function (item) {
+            //         return item.id === id;
+            //     });
+            //     const saIdList = [];
+            //     for (let i = 0; i < $('#schedule-users tr').length; i++) {
+            //         saIdList.push(parseInt($('#schedule-users tr').eq(i).data('uid')));
+            //     }
+            //     if (_.includes(saIdList, id)) {
+            //         toastr.error('该用户已存在列表中,无需重复添加');
+            //         e.stopPropagation();
+            //         return;
+            //     }
+            //
+            //     const prop = {
+            //         audit_id: id,
+            //         type: 'add',
+            //     };
+            //     postData('/tender/' + cur_tenderid + '/schedule/audit/save', prop, function (data) {
+            //         selectedUserIdsByType.schedule.push(user.id);
+            //         const html = `<tr data-uid="${user.id}" data-id="${data.id}">
+            //                         <td>${user.name}</td>
+            //                         <td>${user.role}</td>
+            //                         <td class="text-center">
+            //                             <div class="custom-control custom-checkbox mb-2">
+            //                                 <input type="checkbox" data-zhi="${scPermission.show}" data-id="${data.id}" id="${data.id}_customRadio41" name="customCheckbox" class="custom-control-input" checked>
+            //                                 <label class="custom-control-label" for="${data.id}_customRadio41"></label>
+            //                             </div>
+            //                         </td>
+            //                         <td class="text-center">
+            //                             <div class="custom-control custom-checkbox mb-2">
+            //                                 <input type="checkbox" data-zhi="${scPermission.edit}" data-id="${data.id}" id="${data.id}_customRadio42" name="customCheckbox" class="custom-control-input">
+            //                                 <label class="custom-control-label" for="${data.id}_customRadio42"></label>
+            //                             </div>
+            //                         </td>
+            //                         <td class="text-center">
+            //                             <a href="#remove-user1" data-id="${data.id}" data-show-id="${user.id}" data-toggle="modal" data-target="#remove-user" class="btn btn-sm btn-outline-danger remove-schedule-user">移除</a>
+            //                         </td>
+            //                     </tr>`;
+            //         $('#schedule-users').append(html);
+            //         updateSelectedMarks();
+            //     });
             } else if (type === 'contract') {
                 const user = _.find(accountList, function (item) {
                     return item.id === id;
@@ -878,16 +868,16 @@ $(document).ready(() => {
                     file: $('#tourist-users tr').eq(i).find('input[type="checkbox"]').eq(0).is(':checked') ? 1 : 0,
                     tag: $('#tourist-users tr').eq(i).find('input[type="checkbox"]').eq(1).is(':checked') ? 1 : 0,
                 };
-            } else if (userType === 'schedule') {
-                let permission = scPermission.no;
-                const _this = $('#schedule-users tr').eq(i).find('input[type="checkbox"]').eq(0);
-                const _other = $('#schedule-users tr').eq(i).find('input[type="checkbox"]').eq(1);
-                if (_this.is(':checked') && _other.is(':checked')) {
-                    permission = scPermission.edit;
-                } else if (_this.is(':checked') && !_other.is(':checked')) {
-                    permission = scPermission.show;
-                }
-                userData.permission = permission;
+            // } else if (userType === 'schedule') {
+            //     let permission = scPermission.no;
+            //     const _this = $('#schedule-users tr').eq(i).find('input[type="checkbox"]').eq(0);
+            //     const _other = $('#schedule-users tr').eq(i).find('input[type="checkbox"]').eq(1);
+            //     if (_this.is(':checked') && _other.is(':checked')) {
+            //         permission = scPermission.edit;
+            //     } else if (_this.is(':checked') && !_other.is(':checked')) {
+            //         permission = scPermission.show;
+            //     }
+            //     userData.permission = permission;
             } else if (userType === 'contract') {
                 userData.permission = {
                     add: $('#contract-users tr').eq(i).find('input[data-type="permission_add"]').eq(0).is(':checked') ? 1 : 0,
@@ -1085,10 +1075,10 @@ const tenderListSpec = (function(){
     return { getTenderNodeHtml, getTenderTreeHeaderHtml }
 })();
 
-function updateSelectedMarks(forcedType = null) { 
+function updateSelectedMarks(forcedType = null) {
     let currentUserListSelector = '';
-    let selectedIdsArray = []; 
-    let currentType = forcedType; 
+    let selectedIdsArray = [];
+    let currentType = forcedType;
     if (!currentType) {
         const $activeTabPane = $('.tab-pane.active');
         const activeTabId = $activeTabPane.attr('id');
@@ -1226,11 +1216,11 @@ function setTouristHtml(tourists) {
                                     </td>
                                 </tr>`;
         }
-        selectedUserIdsByType.tourist = []; 
+        selectedUserIdsByType.tourist = [];
         if (Array.isArray(tourists)) {
             tourists.forEach(function(tourist) {
                 if (tourist.user_id !== undefined && tourist.user_id !== null) {
-                    selectedUserIdsByType.tourist.push(parseInt(tourist.user_id, 10)); 
+                    selectedUserIdsByType.tourist.push(parseInt(tourist.user_id, 10));
                 }
             });
         }
@@ -1267,7 +1257,7 @@ function setScheduleHtml(scheduleAuditList) {
         if (Array.isArray(scheduleAuditList)) {
             scheduleAuditList.forEach(function(sa) {
                 if (sa.audit_id !== undefined && sa.audit_id !== null) {
-                    selectedUserIdsByType.schedule.push(parseInt(sa.audit_id, 10)); 
+                    selectedUserIdsByType.schedule.push(parseInt(sa.audit_id, 10));
                 }
             });
         }
@@ -1308,7 +1298,7 @@ function setContractHtml(datas) {
     if (Array.isArray(datas)) {
             datas.forEach(function(ca) {
                 if (ca.uid !== undefined && ca.uid !== null) {
-                    selectedUserIdsByType.contract.push(parseInt(ca.uid, 10)); 
+                    selectedUserIdsByType.contract.push(parseInt(ca.uid, 10));
                 }
             });
         }
@@ -1337,7 +1327,7 @@ function setConstructionHtml(constructionAuditList) {
         if (Array.isArray(constructionAuditList)) {
             constructionAuditList.forEach(function(sa) {
                 if (sa.uid !== undefined && sa.uid !== null) {
-                    selectedUserIdsByType.construction.push(parseInt(sa.uid, 10)); 
+                    selectedUserIdsByType.construction.push(parseInt(sa.uid, 10));
                 }
             });
         }
@@ -1354,7 +1344,7 @@ function setTenderPermissionsHtml(auditList, key, keys) {
     if (Array.isArray(auditList)) {
         auditList.forEach(function(sa) {
             if (sa.uid !== undefined && sa.uid !== null) {
-                selectedUserIdsByType[key].push(parseInt(sa.uid, 10)); 
+                selectedUserIdsByType[key].push(parseInt(sa.uid, 10));
             }
         });
     }
@@ -1387,7 +1377,7 @@ function setTenderPermissionHtml(auditList, key) {
     if (Array.isArray(auditList)) {
         auditList.forEach(function(sa) {
             if (sa.uid !== undefined && sa.uid !== null) {
-                selectedUserIdsByType[key].push(parseInt(sa.uid, 10)); 
+                selectedUserIdsByType[key].push(parseInt(sa.uid, 10));
             }
         });
     }

+ 18 - 17
app/router.js

@@ -399,7 +399,7 @@ module.exports = app => {
     app.post('/sp/:id/construction/:tid/log/:lid/file/delete', sessionAuth, subProjectCheck, constructionCheck, 'constructionController.deleteFile');
     app.get('/sp/:id/construction/:tid/log/:lid/file/:fid/download', sessionAuth, subProjectCheck, constructionCheck, 'constructionController.downloadFile');
 
-    // **概算投资/动态投资
+    // 进度管理-项目进度
     app.get('/sp/:id/budget', sessionAuth, subProjectCheck, budgetCheck, 'budgetController.budgetInfo');
     app.get('/sp/:id/budget/compare', sessionAuth, subProjectCheck, budgetCheck, 'budgetController.compare');
     app.post('/sp/:id/budget/compare/load', sessionAuth, subProjectCheck, budgetCheck, 'budgetController.compareLoad');
@@ -412,6 +412,23 @@ module.exports = app => {
     app.post('/sp/:id/budget/:btype/dsk', sessionAuth, subProjectCheck, budgetCheck, 'budgetController.importDsk');
     app.post('/sp/:id/budget/decimal', sessionAuth, subProjectCheck, budgetCheck, 'budgetController.decimal');
 
+    // 进度管理-标段进度
+    app.get('/sp/:id/schedule/tender', sessionAuth, subProjectCheck, 'scheduleController.tender');
+    app.get('/sp/:id/schedule/tender/:tid', sessionAuth, subProjectCheck, tenderCheck, scheduleCheck, 'scheduleController.index');
+    app.get('/sp/:id/schedule/tender/:tid/ledger', sessionAuth, subProjectCheck, tenderCheck, scheduleCheck, 'scheduleController.ledger');
+    app.post('/sp/:id/schedule/tender/:tid/ledger/load', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.loadLedgerData');
+    app.post('/sp/:id/schedule/tender/:tid/ledger/save', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.saveLedger');
+    app.get('/sp/:id/schedule/tender/:tid/plan', sessionAuth, subProjectCheck, tenderCheck, scheduleCheck, 'scheduleController.plan');
+    app.post('/sp/:id/schedule/tender/:tid/plan/save', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.savePlan');
+    app.get('/sp/:id/schedule/tender/:tid/stage', sessionAuth, subProjectCheck, tenderCheck, scheduleCheck, 'scheduleController.stageTp');
+    app.get('/sp/:id/schedule/tender/:tid/stage/order/:order', sessionAuth, subProjectCheck, tenderCheck, scheduleCheck, 'scheduleController.stageTp');
+    app.post('/sp/:id/schedule/tender/:tid/stage/save', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.saveStageTp');
+    app.get('/sp/:id/schedule/tender/:tid/stage/gcl', sessionAuth, subProjectCheck, tenderCheck, scheduleCheck, 'scheduleController.stageGcl');
+    app.post('/sp/:id/schedule/tender/:tid/stage/gcl/save', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.saveStageGcl');
+    app.post('/sp/:id/schedule/tender/:tid/stage/:order/load', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.loadTpLedgerData');
+    app.post('/sp/:id/schedule/tender/:tid/stage/gcl/:order/load', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.loadGclLedgerData');
+    app.post('/sp/:id/schedule/tender/:tid/audit/save', sessionAuth, subProjectCheck, tenderCheck, 'scheduleController.saveAudit');
+
     // 支付审批
     app.get('/sp/:id/payment', sessionAuth, subProjectCheck, 'paymentController.index');
     app.get('/sp/:id/payment/setting', sessionAuth, subProjectCheck, 'paymentController.setting');
@@ -1152,22 +1169,6 @@ module.exports = app => {
     app.get('/wx/test', 'wechatController.testwx');
     app.get('/MP_verify_t3MkWAMqplVxPjmr.txt', 'wechatController.oauthTxt');
 
-    // 投资进度
-    app.get('/tender/:id/schedule', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, scheduleCheck, 'scheduleController.index');
-    app.get('/tender/:id/schedule/ledger', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, scheduleCheck, 'scheduleController.ledger');
-    app.post('/tender/:id/schedule/ledger/load', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.loadLedgerData');
-    app.post('/tender/:id/schedule/ledger/save', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.saveLedger');
-    app.get('/tender/:id/schedule/plan', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, scheduleCheck, 'scheduleController.plan');
-    app.post('/tender/:id/schedule/plan/save', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.savePlan');
-    app.get('/tender/:id/schedule/stage', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, scheduleCheck, 'scheduleController.stageTp');
-    app.get('/tender/:id/schedule/stage/order/:order', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, scheduleCheck, 'scheduleController.stageTp');
-    app.post('/tender/:id/schedule/stage/save', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.saveStageTp');
-    app.get('/tender/:id/schedule/stage/gcl', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, scheduleCheck, 'scheduleController.stageGcl');
-    app.post('/tender/:id/schedule/stage/gcl/save', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.saveStageGcl');
-    app.post('/tender/:id/schedule/stage/:order/load', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.loadTpLedgerData');
-    app.post('/tender/:id/schedule/stage/gcl/:order/load', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.loadGclLedgerData');
-    app.post('/tender/:id/schedule/audit/save', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'scheduleController.saveAudit');
-
     // 书签
     app.post('/tender/:id/ledger/tag', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, 'tenderController.billsTag');
     app.post('/tender/:id/revise/:rid/info/tag', sessionAuth, tenderCheck, subProjectCheck, uncheckTenderCheck, reviseCheck, 'tenderController.billsTag');

+ 2 - 2
app/service/budget.js

@@ -95,7 +95,7 @@ module.exports = app => {
             data.in_time = new Date();
             data.std_id = budgetStd.id;
             const operate = await transaction.insert(this.tableName, data);
-            if (operate.insertId === 0) throw '初始化动态投资数据失败';
+            if (operate.insertId === 0) throw '初始化项目进度数据失败';
 
             // 获取合同支付模板 并添加到标段
             await this.ctx.service.budgetGu.initByTemplate(transaction, operate.insertId, budgetStd.gu_template_id);
@@ -290,4 +290,4 @@ module.exports = app => {
     }
 
     return Budget;
-};
+};

+ 20 - 0
app/service/change.js

@@ -2281,6 +2281,26 @@ module.exports = app => {
             });
             return change;
         }
+
+        async checkRevising(tenderId, cid) {
+            let flag = false;
+            // 判断修订及变更清单里是否有新增部位清单
+            const lastRevise = await this.ctx.service.ledgerRevise.getLastestRevise(tenderId);
+            if (lastRevise && lastRevise.status !== audit.revise.status.checked) {
+                const changeAuditList = await this.ctx.service.changeAuditList.getList(cid);
+                const changeLedgerList = await this.ctx.service.changeLedger.getAllDataByCondition({ where: { tender_id: tenderId } });
+                const changePosList = await this.ctx.service.changePos.getAllDataByCondition({ where: { tid: tenderId } });
+                for (const cl of changeAuditList) {
+                    if (cl.gcl_id || cl.mx_id) {
+                        if (this._.findIndex(changeLedgerList, { id: cl.gcl_id }) !== -1 || this._.findIndex(changePosList, { id: cl.mx_id }) !== -1) {
+                            flag = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            return flag;
+        }
     }
 
     return Change;

+ 1 - 1
app/service/sub_proj_permission.js

@@ -85,7 +85,7 @@ module.exports = app => {
                         '注:查看合同第5、6、7必须选择其一,否则无法查看本项目合同管理',
                     ] },
                 { key: 'file', name: '资料管理', field: 'file_permission' },
-                { key: 'budget', name: '动态投资', field: 'budget_permission' },
+                { key: 'budget', name: '项目进度', field: 'budget_permission' },
                 {
                     key: 'financial', name: '资金监管', children: [
                         { key: 'fund_trans', name: '资金划拨', field: 'fund_trans_permission' },

+ 17 - 0
app/service/tender_permission.js

@@ -41,6 +41,10 @@ module.exports = app => {
                 safe_payment: {
                     view: { title: '查看', value: 1, isDefault: 1 },
                     add: { title: '上报人', value: 2 },
+                },
+                schedule: {
+                    view: { title: '查看', value: 1, isDefault: 1 },
+                    edit: { title: '修改', value: 2 },
                 }
             };
             this.PermissionBlock = [
@@ -48,6 +52,7 @@ module.exports = app => {
                 { key: 'inspection', name: '质量巡检', field: 'inspection' },
                 { key: 'safe_inspection', name: '安全巡检', field: 'safe_inspection' },
                 { key: 'safe_payment', name: '安全计量', field: 'safe_payment' },
+                { key: 'schedule', name: '标段进度', field: 'schedule' },
             ];
             for (const p of this.PermissionBlock) {
                 if (p.children) {
@@ -256,6 +261,18 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        async getShowPermission(permission) {
+            // 存在1代表它有权限查看本标段
+            let tenderPermission = false;
+            for (const p in this.PermissionConst) {
+                if (permission[p] && permission[p].split(',').indexOf('1') > -1) {
+                    tenderPermission = true;
+                    break;
+                }
+            }
+            return tenderPermission;
+        }
     }
 
     return tenderPermission;

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

@@ -1,7 +1,7 @@
 <div class="panel-content">
     <div class="panel-title fluid">
         <div class="title-main  d-flex justify-content-between">
-            <div>动态投资</div>
+            <div>项目进度</div>
             <div class="d-inline-block ml-1" id="show-level"></div>
             <div class="ml-auto"></div>
         </div>

+ 9 - 0
app/view/change/information.ejs

@@ -26,20 +26,26 @@
                     <% } %>
                     <% if (ctx.change.status === auditConst.status.uncheck) { %>
                         <% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %>
+                        <span class="d-inline-block need-check-revising">
                             <a id="sub-sp-btn" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm">上报审批</a>
+                        </span>
                         <% } else { %>
                             <a id="sub-sp-btn" href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-outline-secondary btn-sm">上报中</a>
                         <% } %>
                     <% } else if (ctx.change.status === auditConst.status.checking) { %>
                         <% if (ctx.change.curAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) { %>
+                        <span class="d-inline-block need-check-revising">
                             <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm">审批通过</a>
+                        </span>
                             <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm">审批退回</a>
                         <% } else { %>
                             <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm">审批中</a>
                         <% } %>
                     <% } else if (ctx.change.status === auditConst.status.checkNoPre) { %>
                         <% if (ctx.change.curAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) { %>
+                        <span class="d-inline-block need-check-revising">
                             <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm">审批通过</a>
+                        </span>
                             <a href="#sp-back" data-toggle="modal" data-target="#sp-back" class="btn btn-warning btn-sm">审批退回</a>
                         <% } else { %>
                             <a href="#sp-list" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted">审批退回</a>
@@ -56,7 +62,9 @@
                     <% } else if (ctx.change.status === auditConst.status.checkNo || ctx.change.status === auditConst.status.revise) { %>
                         <a href="#sp-list" data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted sp-list-btn">审批<% if (ctx.change.status === auditConst.status.checkNo) { %>退回<% } else { %>修订<% } %></a>
                         <% if (ctx.session.sessionUser.accountId === ctx.change.uid) { %>
+                        <span class="d-inline-block need-check-revising">
                             <a href="#sp-list" data-type="show" data-toggle="modal" data-target="#sp-list" class="btn btn-primary btn-sm sp-list-btn">重新上报</a>
+                        </span>
                         <% } %>
                         <% if (ctx.change.status === auditConst.status.revise && (ctx.session.sessionUser.accountId === ctx.change.uid || ctx.session.sessionUser.is_admin)) { %>
                             <a href="#sub-revoke" data-toggle="modal" data-target="#sub-revoke" class="btn btn-warning btn-sm ml-2">撤销修订</a>
@@ -584,6 +592,7 @@
         }
     });
     const readOnly = <%- change.readOnly %>;
+    const revising = <%- revising %>;
     const shenpiPower = <%- change.shenpiPower %>;
     const filePermission = <%- change.filePermission %>;
     const changeSpread = SpreadJsObj.createNewSpread($('#change-spread')[0]);

+ 3 - 5
app/view/schedule/index.ejs

@@ -1,13 +1,13 @@
-<% include ../tender/tender_sub_menu.ejs %>
+<% include ./list_sub_menu.ejs %>
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main d-flex">
-            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <% include ./list_sub_mini_menu.ejs %>
             <h2>
                 <% if (planMonth) { %>计划至 <%- planMonth.split('-')[0] %>年<%- parseInt(planMonth.split('-')[1]) %>月 <% } %>
             </h2>
             <div class="ml-auto">
-                <a href="/tender/<%- ctx.tender.id %>/schedule/ledger" class="btn btn-sm btn-outline-primary">进度台账</a>
+                <a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/ledger" class="btn btn-sm btn-outline-primary">进度台账</a>
             </div>
         </div>
     </div>
@@ -123,7 +123,6 @@
         </div>
     </div>
 </div>
-<script src="/public/js/echarts/echarts.min.js"></script>
 <% if (schedule && schedule.total_tp !== 0) { %>
 <script type="text/javascript">
     var charts = new Array();
@@ -328,7 +327,6 @@
     })
 </script>
 <% } %>
-<script src="/public/js/sub_menu.js"></script>
 <script>
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',

+ 3 - 3
app/view/schedule/ledger.ejs

@@ -1,8 +1,8 @@
-<% include ../tender/tender_sub_menu.ejs %>
+<% include ./list_sub_menu.ejs %>
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main d-flex">
-            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <% include ./list_sub_mini_menu.ejs %>
             <div>
                 <div class="d-inline-block">
                     <a class="btn btn-sm btn-light">
@@ -29,7 +29,7 @@
                     </a>
                 </div>
             </div>
-            <% if (ctx.tender.schedule_permission === scPermission.edit && !revising) { %>
+            <% if (ctx.tender.user_permission.schedule.edit && !revising) { %>
             <div class="ml-auto">
                 <button type="button" id="ledger_submit" class="btn btn-primary btn-sm pull-right">确认提交</button>
             </div>

+ 17 - 0
app/view/schedule/list_sub_menu.ejs

@@ -0,0 +1,17 @@
+<div class="panel-sidebar" id="sub-menu">
+    <div class="sidebar-title text-center" data-toggle="tooltip" data-placement="right" data-original-title="<%- ctx.subProject.name %>">
+        <%- (ctx.subProject.name.length > 15 ? ctx.subProject.name.substring(0,15) + '...' : ctx.subProject.name) %>
+    </div>
+    <div class="scrollbar-auto">
+        <% include ./list_sub_menu_list.ejs %>
+        <div class="side-show"></div>
+        <div class="side-fold" data-toggle="tooltip" data-placement="top" data-original-title="折叠侧栏" id="to-mini-menu">
+            <i class="fa fa-angle-left"></i>
+        </div>
+    </div>
+    <script>
+        new Vue({
+            el: '.scrollbar-auto',
+        });
+    </script>
+</div>

+ 10 - 0
app/view/schedule/list_sub_menu_list.ejs

@@ -0,0 +1,10 @@
+<nav-menu title="返回" url="/sp/<%- ctx.subProject.id %>/schedule/tender" tclass="text-primary" ml="1" icon="fa-chevron-left"></nav-menu>
+<% if (ctx.subProject.page_show.xxjd) { %>
+<div class="nav-box">
+    <ul class="nav-list list-unstyled">
+        <li <% if (ctx.url === '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id || ctx.url === '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/ledger') { %>class="active"<% } %>><a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>"><span class="ml-3">进度概况</span></a></li>
+        <li <% if (ctx.url === '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/plan') { %>class="active"<% } %>><a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/plan"><span class="ml-3">计划进度</span></a></li>
+        <li <% if (ctx.url.indexOf('/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/stage') !== -1) { %>class="active"<% } %>><a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/stage"><span class="ml-3">计量进度</span></a></li>
+    </ul>
+</div>
+<% } %>

+ 16 - 0
app/view/schedule/list_sub_mini_menu.ejs

@@ -0,0 +1,16 @@
+<!--折起的菜单-->
+<div class="min-side" id="sub-mini-menu" style="display: none;">
+    <div class="side-switch" data-toggle="tooltip" data-placement="left" data-original-title="点击这里打开收起的菜单栏">
+        <i class="fa fa-bars mt-2"></i>
+        <i class="fa fa-indent mt-2 text-primary" style="display: none;cursor: pointer;" id="to-menu"></i>
+    </div>
+    <div class="side-menu" id="mini-menu-list" style="display: none">
+        <% include ./list_sub_menu_list.ejs %>
+        <div class="side-fold"><a href="javascript: void(0);" data-toggle="tooltip" data-placement="top" data-original-title="展开侧栏" id="to-menu"><i class="fa fa-upload fa-rotate-90"></i></a></div>
+    </div>
+</div>
+<script>
+    new Vue({
+        el: '.side-menu',
+    });
+</script>

+ 6 - 6
app/view/schedule/modal.ejs

@@ -1,4 +1,4 @@
-<% if (scheduleLedgerList.length === 0 && ctx.url !== '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
+<% if (scheduleLedgerList.length === 0 && ctx.url !== '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/ledger') { %>
 <!--首次使用提示-->
 <div class="modal fade" id="first" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -18,7 +18,7 @@
                 <h5>首次使用投资进度需要进行进度台账初始化设置</h5>
             </div>
             <div class="modal-footer">
-                <a href="/tender/<%- ctx.tender.id %>/schedule/ledger" class="btn btn-sm btn-primary">开始设置</a>
+                <a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/ledger" class="btn btn-sm btn-primary">开始设置</a>
             </div>
             <% } %>
         </div>
@@ -53,7 +53,7 @@
                     <h5 class="modal-title">提示</h5>
                 </div>
                 <div class="modal-body">
-                    <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
+                    <% if (ctx.url === '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/ledger') { %>
                         <h5>正在更新台账,请等待...</h5>
                         <div class="progress">
                             <div id="schedule-progress" class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
@@ -63,9 +63,9 @@
                         <h5>台账已完成修订,进入进度台账并更新最新台账数据。</h5>
                     <% } %>
                 </div>
-                <% if (ctx.url !== '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
+                <% if (ctx.url !== '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/ledger') { %>
                 <div class="modal-footer">
-                    <a href="/tender/<%- ctx.tender.id %>/schedule/ledger" class="btn btn-primary btn-sm">进入进度台账</a>
+                    <a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/ledger" class="btn btn-primary btn-sm">进入进度台账</a>
                 </div>
                 <% } %>
             </div>
@@ -82,7 +82,7 @@
         if (selectedLedgerList.length === 0 && !revising) {
             $('#first').modal('show');
         }
-        <% if (!revising && schedule && schedule.revising === 1 && ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>
+        <% if (!revising && schedule && schedule.revising === 1 && ctx.url === '/sp/' + ctx.subProject.id + '/schedule/tender/' + ctx.tender.id + '/ledger') { %>
         let value = 0;
         setInterval(function(e){
             if (value < 100) {

+ 3 - 3
app/view/schedule/plan.ejs

@@ -1,12 +1,12 @@
-<% include ../tender/tender_sub_menu.ejs %>
+<% include ./list_sub_menu.ejs %>
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main d-flex">
-            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <% include ./list_sub_mini_menu.ejs %>
             <h2>
                 <% if (planMonth) { %>计划至 <%- planMonth.split('-')[0] %>年<%- parseInt(planMonth.split('-')[1]) %>月 <% } %>
             </h2>
-            <% if (!revising && ctx.tender.schedule_permission === scPermission.edit) { %>
+            <% if (!revising && ctx.tender.user_permission.schedule.edit) { %>
             <div class="ml-auto">
                 <a href="#mode" data-toggle="modal" data-target="#mode" class="btn btn-sm btn-outline-primary">计算方式</a>
                 <a href="#edit-plan" data-toggle="modal" data-target="#edit-plan" class="btn btn-sm btn-outline-primary">管理计划</a>

+ 4 - 4
app/view/schedule/stage_gcl.ejs

@@ -1,12 +1,12 @@
-<% include ../tender/tender_sub_menu.ejs %>
+<% include ./list_sub_menu.ejs %>
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main d-flex">
-            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <% include ./list_sub_mini_menu.ejs %>
             <div>
                 <div class="d-inline-block">
                     <div class="btn-group group-tab">
-                        <a class="btn btn-sm btn-light " href="/tender/<%- tender.id %>/schedule/stage">
+                        <a class="btn btn-sm btn-light " href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- tender.id %>/stage">
                             金额模式
                         </a>
                         <a class="btn btn-sm btn-light active" href="javascript:void(0);">
@@ -15,7 +15,7 @@
                     </div>
                 </div>
             </div>
-            <% if (!revising && ctx.tender.schedule_permission === scPermission.edit) { %>
+            <% if (!revising && ctx.tender.user_permission.schedule.edit) { %>
             <div class="ml-auto">
                 <a href="#edit-stage" data-toggle="modal" data-target="#edit-stage" class="btn btn-sm btn-outline-primary">管理计量</a>
                 <a href="#add" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#add">创建实际计量</a>

+ 1 - 1
app/view/schedule/stage_gcl_modal.ejs

@@ -61,7 +61,7 @@
                 <h5>使用计量进度需要进行计划进度设置</h5>
             </div>
             <div class="modal-footer">
-                <a href="/tender/<%- ctx.tender.id %>/schedule/plan" class="btn btn-sm btn-primary">开始设置</a>
+                <a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/plan" class="btn btn-sm btn-primary">开始设置</a>
             </div>
         </div>
     </div>

+ 6 - 6
app/view/schedule/stage_tp.ejs

@@ -1,15 +1,15 @@
-<% include ../tender/tender_sub_menu.ejs %>
+<% include ./list_sub_menu.ejs %>
 <div class="panel-content">
     <div class="panel-title">
         <div class="title-main d-flex">
-            <% include ../tender/tender_sub_mini_menu.ejs %>
+            <% include ./list_sub_mini_menu.ejs %>
             <div>
                 <div class="d-inline-block">
                     <div class="btn-group group-tab">
                         <a class="btn btn-sm btn-light active" href="javascript:void(0);">
                             金额模式
                         </a>
-                        <a class="btn btn-sm btn-light" href="/tender/<%- tender.id %>/schedule/stage/gcl">
+                        <a class="btn btn-sm btn-light" href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- tender.id %>/stage/gcl">
                             工程量模式
                         </a>
                     </div>
@@ -23,20 +23,20 @@
                         <div class="dropdown-menu" aria-labelledby="dropdownMenuButton" x-placement="bottom-start" style="position: absolute; transform: translate3d(0px, 26px, 0px); top: 0px; left: 0px; will-change: transform;">
                             <% for (const s of scheduleStage) { %>
                             <% if (s.id !== curScheduleStage.id) { %>
-                            <a class="dropdown-item" href="/tender/<%- tender.id %>/schedule/stage/order/<%- s.order %>"><%- s.yearmonth.split('-')[0] %>年<%- parseInt(s.yearmonth.split('-')[1]) %>月(第<%- s.order %>期)</a>
+                            <a class="dropdown-item" href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- tender.id %>/stage/order/<%- s.order %>"><%- s.yearmonth.split('-')[0] %>年<%- parseInt(s.yearmonth.split('-')[1]) %>月(第<%- s.order %>期)</a>
                             <% } %>
                             <% } %>
                         </div>
                     </div>
                 </div>
-                <% if (!revising && ctx.tender.schedule_permission === scPermission.edit) { %>
+                <% if (!revising && ctx.tender.user_permission.schedule.edit) { %>
                 <div class="d-inline-flex">
                     <a href="#delete" data-toggle="modal" data-target="#delete" class="btn btn-sm btn-outline-danger">删除本期进度</a>
                 </div>
                 <% } %>
                 <% } %>
             </div>
-            <% if (!revising && ctx.tender.schedule_permission === scPermission.edit) { %>
+            <% if (!revising && ctx.tender.user_permission.schedule.edit) { %>
             <div class="ml-auto">
                 <a href="" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#add">创建新计量进度</a>
                 <% if (scheduleStage.length > 0) { %>

+ 1 - 1
app/view/schedule/stage_tp_modal.ejs

@@ -97,7 +97,7 @@
                 <h5>使用计量进度需要进行计划进度设置</h5>
             </div>
             <div class="modal-footer">
-                <a href="/tender/<%- ctx.tender.id %>/schedule/plan" class="btn btn-sm btn-primary">开始设置</a>
+                <a href="/sp/<%- ctx.subProject.id %>/schedule/tender/<%- ctx.tender.id %>/plan" class="btn btn-sm btn-primary">开始设置</a>
             </div>
         </div>
     </div>

+ 24 - 0
app/view/schedule/tender.ejs

@@ -0,0 +1,24 @@
+<div class="panel-content">
+    <div class="panel-title fluid">
+        <div class="title-main  d-flex">
+            <div class="d-inline-block" id="show-level"></div>
+            <div class="ml-auto">
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="sjs-height-0" style="background-color: #fff">
+            <div class="c-body">
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenderList)) %>'));
+    const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const selfCategoryLevel = '<%- (selfCategoryLevel || '') %>';
+    const is_admin = <%- ctx.session.sessionUser.is_admin %>;
+
+    const pid = '<%- ctx.session.sessionProject.id %>';
+    const uphlname = 'user_<%- ctx.session.sessionUser.accountId %>_pro_<% ctx.session.sessionProject.id %>_category_hide_list';
+</script>

+ 1 - 0
app/view/schedule/tender_modal.ejs

@@ -0,0 +1 @@
+<% include ../shares/tender_permission_modal.ejs %>

+ 23 - 161
app/view/sp_setting/manage.ejs

@@ -25,7 +25,7 @@
                 <nav class="nav nav-tabs m-3" role="tablist">
                     <a class="nav-item nav-link active" data-toggle="tab" href="#splc" role="tab">审批流程</a>
                     <a class="nav-item nav-link" data-toggle="tab" href="#guest" role="tab">游客账号</a>
-                    <a class="nav-item nav-link" data-toggle="tab" href="#tzpro" role="tab">投资进度</a>
+                    <a class="nav-item nav-link" data-toggle="tab" href="#schedule" role="tab">标段进度</a>
                     <a class="nav-item nav-link" data-toggle="tab" href="#htgl" role="tab">标段合同</a>
                     <a class="nav-item nav-link" data-toggle="tab" href="#sgrz" role="tab">施工日志</a>
                     <a class="nav-item nav-link" data-toggle="tab" href="#quality" role="tab">质量管理</a>
@@ -103,77 +103,33 @@
                             </table>
                         </div>
                     </div>
-                    <!--投资进度 -->
-                    <div id="tzpro" class="tab-pane">
+                    <!--标段进度 -->
+                    <div id="schedule" class="tab-pane">
                         <div class="col-8" style="max-width: 800px">
                             <table class="table table-hover table-bordered table-sm">
-                                <thead>
-                                <tr>
-                                    <th class="text-center" width="100px">用户</th>
-                                    <th class="text-center" width="120px">职位</th>
-                                    <th class="text-center" width="60px">查看</th>
-                                    <th class="text-center" width="60px">修改</th>
-                                    <th class="text-center" >操作</th>
-                                </tr>
-                                </thead>
-                                <tbody id="schedule-users">
-                                <tr>
-                                    <td>陈特</td>
-                                    <td>业主</td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" id="customRadio301" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="customRadio301"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" id="customRadio302" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="customRadio302"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <a href="#remove-user1" data-toggle="modal" data-target="#remove-user" class="btn btn-sm btn-outline-danger">移除</a>
-                                    </td>
-                                </tr>
+                                <thead class="text-center">
                                 <tr>
-                                    <td>仁温书</td>
-                                    <td>项目经理</td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" id="customRadio311" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="customRadio311"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" id="customRadio312" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="customRadio312"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <a href="#remove-user1" data-toggle="modal" data-target="#remove-user" class="btn btn-sm btn-outline-danger">移除</a>
-                                    </td>
+                                    <th class="align-middle" rowspan="2">成员名称</th>
+                                    <th class="align-middle" rowspan="2">角色/职位</th>
+                                    <% for (const pb of permissionBlock) { %>
+                                        <% if (pb.key === 'schedule') { %>
+                                            <th colspan="<%- pb.permission.filter(x => { return !x.isDefault; }).length %>"><%- pb.name %></th>
+                                        <% } %>
+                                    <% } %>
+                                    <th class="align-middle" rowspan="2">操作</th>
                                 </tr>
                                 <tr>
-                                    <td>玉安然</td>
-                                    <td>集团经理</td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" id="customRadio321" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="customRadio321"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <div class="custom-control custom-checkbox mb-2">
-                                            <input type="checkbox" id="customRadio322" name="customCheckbox" class="custom-control-input">
-                                            <label class="custom-control-label" for="customRadio322"></label>
-                                        </div>
-                                    </td>
-                                    <td class="text-center">
-                                        <a href="#remove-user1" data-toggle="modal" data-target="#remove-user" class="btn btn-sm btn-outline-danger">移除</a>
-                                    </td>
+                                    <% for (const pb of permissionBlock) { %>
+                                        <% if (pb.key === 'schedule') { %>
+                                            <% for (const p of pb.permission) { %>
+                                                <% if (p.isDefault) continue; %>
+                                                <th><%- p.title %></th>
+                                            <% } %>
+                                        <% } %>
+                                    <% } %>
                                 </tr>
+                                </thead>
+                                <tbody id="schedule-users">
                                 </tbody>
                             </table>
                         </div>
@@ -263,6 +219,7 @@
                             </table>
                         </div>
                     </div>
+                    <!--安全管理 -->
                     <div id="safe" class="tab-pane">
                         <div class="col-8" style="max-width: 800px">
                             <table class="table table-hover table-bordered table-sm">
@@ -292,101 +249,6 @@
                             </table>
                         </div>
                     </div>
-<!--                    <div id="quality" class="tab-pane">-->
-<!--                        <div class="col-8" style="max-width: 800px">-->
-<!--                            <table class="table table-hover table-bordered table-sm">-->
-<!--                                <thead class="text-center">-->
-<!--                                <tr>-->
-<!--                                    <th class="align-middle" rowspan="2">成员名称</th>-->
-<!--                                    <th class="align-middle" rowspan="2">角色/职位</th>-->
-<!--                                    <% const pb = permissionBlock.find(item => item.key === 'quality'); %>-->
-<!--                                    <th colspan="<%- pb.permission.filter(x => { return !x.isDefault; }).length %>"><%- pb.name %></th>-->
-<!--                                    <th class="align-middle" rowspan="2">操作</th>-->
-<!--                                </tr>-->
-<!--                                <tr>-->
-<!--                                    <% for (const p of pb.permission) { %>-->
-<!--                                        <% if (p.isDefault) continue; %>-->
-<!--                                        <th><%- p.title %></th>-->
-<!--                                    <% } %>-->
-<!--                                </tr>-->
-<!--                                </thead>-->
-<!--                                <tbody id="quality-users">-->
-<!--                                </tbody>-->
-<!--                            </table>-->
-<!--                        </div>-->
-<!--                    </div>-->
-                    <!--质量巡检 -->
-<!--                    <div id="inspection" class="tab-pane">-->
-<!--                        <div class="col-8" style="max-width: 800px">-->
-<!--                            <table class="table table-hover table-bordered table-sm">-->
-<!--                                <thead class="text-center">-->
-<!--                                <tr>-->
-<!--                                    <th class="align-middle" rowspan="2">成员名称</th>-->
-<!--                                    <th class="align-middle" rowspan="2">角色/职位</th>-->
-<!--                                    <% const inspectionPb = permissionBlock.find(item => item.key === 'inspection'); %>-->
-<!--                                    <th colspan="<%- inspectionPb.permission.filter(x => { return !x.isDefault; }).length %>"><%- inspectionPb.name %></th>-->
-<!--                                    <th class="align-middle" rowspan="2">操作</th>-->
-<!--                                </tr>-->
-<!--                                <tr>-->
-<!--                                    <% for (const p of inspectionPb.permission) { %>-->
-<!--                                        <% if (p.isDefault) continue; %>-->
-<!--                                        <th><%- p.title %></th>-->
-<!--                                    <% } %>-->
-<!--                                </tr>-->
-<!--                                </thead>-->
-<!--                                <tbody id="inspection-users">-->
-<!--                                </tbody>-->
-<!--                            </table>-->
-<!--                        </div>-->
-<!--                    </div>-->
-                    <!--质量巡检 -->
-<!--                    <div id="safe_payment" class="tab-pane">-->
-<!--                        <div class="col-8" style="max-width: 800px">-->
-<!--                            <table class="table table-hover table-bordered table-sm">-->
-<!--                                <thead class="text-center">-->
-<!--                                <tr>-->
-<!--                                    <th class="align-middle" rowspan="2">成员名称</th>-->
-<!--                                    <th class="align-middle" rowspan="2">角色/职位</th>-->
-<!--                                    <% const safePaymentPb = permissionBlock.find(item => item.key === 'safe_payment'); %>-->
-<!--                                    <th colspan="<%- safePaymentPb.permission.filter(x => { return !x.isDefault; }).length %>"><%- safePaymentPb.name %></th>-->
-<!--                                    <th class="align-middle" rowspan="2">操作</th>-->
-<!--                                </tr>-->
-<!--                                <tr>-->
-<!--                                    <% for (const p of safePaymentPb.permission) { %>-->
-<!--                                        <% if (p.isDefault) continue; %>-->
-<!--                                        <th><%- p.title %></th>-->
-<!--                                    <% } %>-->
-<!--                                </tr>-->
-<!--                                </thead>-->
-<!--                                <tbody id="safe_payment-users">-->
-<!--                                </tbody>-->
-<!--                            </table>-->
-<!--                        </div>-->
-<!--                    </div>-->
-                    <!--安全巡检 -->
-<!--                    <div id="safe_inspection" class="tab-pane">-->
-<!--                        <div class="col-8" style="max-width: 800px">-->
-<!--                            <table class="table table-hover table-bordered table-sm">-->
-<!--                                <thead class="text-center">-->
-<!--                                <tr>-->
-<!--                                    <th class="align-middle" rowspan="2">成员名称</th>-->
-<!--                                    <th class="align-middle" rowspan="2">角色/职位</th>-->
-<!--                                    <% const safeInspectionPb = permissionBlock.find(item => item.key === 'safe_inspection'); %>-->
-<!--                                    <th colspan="<%- safeInspectionPb.permission.filter(x => { return !x.isDefault; }).length %>"><%- safeInspectionPb.name %></th>-->
-<!--                                    <th class="align-middle" rowspan="2">操作</th>-->
-<!--                                </tr>-->
-<!--                                <tr>-->
-<!--                                    <% for (const p of safeInspectionPb.permission) { %>-->
-<!--                                        <% if (p.isDefault) continue; %>-->
-<!--                                        <th><%- p.title %></th>-->
-<!--                                    <% } %>-->
-<!--                                </tr>-->
-<!--                                </thead>-->
-<!--                                <tbody id="safe_inspection-users">-->
-<!--                                </tbody>-->
-<!--                            </table>-->
-<!--                        </div>-->
-<!--                    </div>-->
                     <!--标段管理员 -->
                     <div id="subadmin" class="tab-pane">
                         <div class="col-6">

+ 1 - 1
app/view/sp_setting/manage_modal.ejs

@@ -39,7 +39,7 @@
                     <table class="table table-sm table-bordered table-hover">
                         <thead class="text-center">
                         <tr><th rowspan="2" width="80%">标段名称</th><th colspan="2" width="20%">过滤</th></tr>
-                        <tr><th>动态投资</th><th>资金监管</th></tr>
+                        <tr><th>项目进度</th><th>资金监管</th></tr>
                         </thead>
                         <tbody id="filter-tender-list">
                         </tbody>

+ 1 - 1
app/view/sp_setting/permission.ejs

@@ -33,7 +33,7 @@
                                     <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=info<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action <%- (ptype === 'info' ? 'active' : '') %>">项目概况</a>
                                     <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=contract<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action  <%- (ptype === 'contract' ? 'active' : '') %>">项目合同</a>
                                     <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=file<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action  <%- (ptype === 'file' ? 'active' : '') %>">资料管理</a>
-                                    <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=budget<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action  <%- (ptype === 'budget' ? 'active' : '') %>">动态投资</a>
+                                    <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=budget<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action  <%- (ptype === 'budget' ? 'active' : '') %>">项目进度</a>
                                     <dd class="list-group-item">资金监管</dd>
                                     <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=fund_trans<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action  <%- (ptype === 'fund_trans' ? 'active' : '') %>"><span class="ml-4"></span>资金划拨</a>
                                     <a href="/sp/<%- ctx.subProject.id %>/setting/user/permission?ptype=fund_pay<%- (keyword ? '&keyword=' + keyword : '')%>" class="list-group-item list-group-item-action  <%- (ptype === 'fund_pay' ? 'active' : '') %>"><span class="ml-4"></span>资金支付</a>

+ 2 - 2
app/view/sub_proj/modal.ejs

@@ -57,7 +57,7 @@
                 <h5 class="modal-title">确认删除项目</h5>
             </div>
             <div class="modal-body">
-                <h5>删除后,项目概况、动态投资等数据无法恢复,请谨慎操作。</h5>
+                <h5>删除后,项目概况、项目进度等数据无法恢复,请谨慎操作。</h5>
                 <h5 id="del-hint">确定删除「<strong style="word-break: break-word;" id="del-tender-name"></strong>」?</h5>
             </div>
             <div class="modal-footer">
@@ -153,7 +153,7 @@
                         <tr>
                             <th rowspan="2" class="align-middle">成员名称</th>
                             <th rowspan="2" class="align-middle">职位</th>
-                            <th colspan="2">动态投资</th>
+                            <th colspan="2">项目进度</th>
                             <th colspan="4">资料管理</th>
                             <th rowspan="2" class="align-middle">关联标段</th>
                             <th rowspan="2" class="align-middle">移除</th>

+ 0 - 10
app/view/tender/tender_sub_menu.ejs

@@ -61,16 +61,6 @@
             </ul>
         </div>
         <% } %>
-        <% if (ctx.subProject.page_show.xxjd && (ctx.tender.schedule_permission !== 0 || ctx.tender.isTourist)) { %>
-        <div class="nav-box">
-            <h3><i class="fa fa-bar-chart fa-fw"></i> 投资进度</h3>
-            <ul class="nav-list list-unstyled sub-list">
-                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>
-                <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>
-                <li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/schedule/stage') !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>
-            </ul>
-        </div>
-        <% } %>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/report') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/report" class="h3"><i class="fa fa-file-text-o fa-fw"></i> <span>输出报表</span></a></li>

+ 0 - 10
app/view/tender/tender_sub_mini_menu.ejs

@@ -55,16 +55,6 @@
             </ul>
         </div>
         <% } %>
-        <% if (ctx.subProject.page_show.xxjd && (ctx.tender.schedule_permission !== 0 || ctx.tender.isTourist)) { %>
-            <div class="nav-box">
-                <h3><i class="fa fa-bar-chart fa-fw"></i> 投资进度</h3>
-                <ul class="nav-list list-unstyled sub-list">
-                    <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule' || ctx.url === '/tender/' + ctx.tender.id + '/schedule/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule"><span>进度概况</span></a></li>
-                    <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/schedule/plan') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/plan"><span>计划进度</span></a></li>
-                    <li <% if (ctx.url.indexOf('/tender/' + ctx.tender.id + '/schedule/stage') !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/schedule/stage"><span>计量进度</span></a></li>
-                </ul>
-            </div>
-        <% } %>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/report') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/report" class="h3"><i class="fa fa-file-text-o fa-fw"></i> <span>输出报表</span></a></li>

+ 20 - 3
config/menu.js

@@ -195,11 +195,28 @@ const menu = {
         controllers: ['file', 'fm'],
     },
     budget: {
-        name: '动态投资',
+        name: '进度管理',
         icon: 'fa-pie-chart',
         display: true,
-        children: null,
-        caption: '动态投资',
+        children: [
+            {
+                msg: 'budget',
+                name: '项目进度',
+                caption: '项目进度',
+                controller: 'budget',
+                display: true,
+                // notIncludedUrl: ['/inspection'],
+            },
+            {
+                msg: 'schedule',
+                name: '标段进度',
+                caption: '标段进度',
+                controller: 'schedule',
+                display: true,
+                // includedUrl: { safe: ['/inspection'] },
+            },
+        ],
+        caption: '进度管理',
         controller: 'budget',
     },
     payment: {

+ 26 - 4
config/web.js

@@ -965,10 +965,32 @@ const JsFiles = {
             },
         },
         schedule: {
+            tender: {
+                files: ['/public/js/moment/moment.min.js'],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/PinYinOrder.bundle.js',
+                    '/public/js/shares/tender_list_order.js',
+                    '/public/js/shares/show_level.js',
+                    '/public/js/shares/tender_permission.js',
+                    '/public/js/tender_showhide.js',
+                    '/public/js/tender_list_base.js',
+                    '/public/js/schedule_tender.js',
+                ],
+                mergeFile: 'schedule_tender',
+            },
+            index: {
+                files: ['/public/js/echarts/echarts.min.js', '/public/js/decimal.min.js', '/public/js/moment/moment.min.js', '/public/js/component/menu.js'],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/zh_calc.js',
+                ],
+                mergeFile: 'schedule_index',
+            },
             ledger: {
                 files: [
                     '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
-                    '/public/js/decimal.min.js',
+                    '/public/js/decimal.min.js', '/public/js/moment/moment.min.js', '/public/js/component/menu.js',
                 ],
                 mergeFiles: [
                     '/public/js/sub_menu.js',
@@ -984,7 +1006,7 @@ const JsFiles = {
             plan: {
                 files: [
                     '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
-                    '/public/js/decimal.min.js',
+                    '/public/js/decimal.min.js', '/public/js/moment/moment.min.js', '/public/js/component/menu.js',
                 ],
                 mergeFiles: [
                     '/public/js/sub_menu.js',
@@ -1002,7 +1024,7 @@ const JsFiles = {
             stageTp: {
                 files: [
                     '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
-                    '/public/js/decimal.min.js',
+                    '/public/js/decimal.min.js', '/public/js/moment/moment.min.js', '/public/js/component/menu.js',
                 ],
                 mergeFiles: [
                     '/public/js/sub_menu.js',
@@ -1018,7 +1040,7 @@ const JsFiles = {
             stageGcl: {
                 files: [
                     '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
-                    '/public/js/decimal.min.js',
+                    '/public/js/decimal.min.js', '/public/js/moment/moment.min.js', '/public/js/component/menu.js',
                 ],
                 mergeFiles: [
                     '/public/js/sub_menu.js',

+ 65 - 0
db_script/tender_permission.js

@@ -0,0 +1,65 @@
+/*
+ 修改脚本,请现在指定spid测试
+ 例如: node db_script/sub_project local 3fcee213-92c9-41de-8f5a-b896c986311a
+ 没有意外再全部执行
+
+ 所有修改均应考虑脚本二次执行时的兼容,应检查是否已执行过,避免在生产环境运行时出现问题后需要二次执行,参见自定义分类脚本
+  */
+
+
+const BaseUtil = require('./baseUtils');
+const scheduleConst = require('../app/const/schedule');
+const querySql = BaseUtil.querySql;
+const uuid = require('node-uuid');
+
+const getInsertSql = function (tableName, data) {
+    const column = [], query = [], value = [];
+    for (const prop in data) {
+        column.push(prop);
+        query.push('?');
+        value.push(data[prop]);
+    }
+    return [`INSERT INTO ${tableName} (${column.join(',')}) VALUES (${query.join(',')})`, value];
+};
+console.log('Copy tender_permission properties: schedule');
+const doComplete = async function() {
+    try {
+        const audits = await querySql('Select * From zh_schedule_audit');
+        for (const a of audits) {
+            const existTender = await querySql('SELECT * FROM zh_tender where id = ?;', [a.tid]);
+            if (existTender.length === 0) {
+                continue;
+            } else {
+                const existTenderPermission = await querySql('SELECT * FROM zh_tender_permission WHERE tid = ? and uid = ?', [existTender[0].id, a.audit_id]);
+                let schedule_permission = '';
+                if (a.permission === scheduleConst.permission.show) {
+                    schedule_permission = '1';
+                } else if (a.permission === scheduleConst.permission.edit) {
+                    schedule_permission = '1,2';
+                }
+                const fund_pay_permission = [];
+                if (a.permission_pay_show) {
+                    fund_pay_permission.push(1);
+                }
+                if (a.permission_pay_file) {
+                    fund_pay_permission.push(3);
+                }
+                if (schedule_permission !== '') {
+                    console.log('Copy tender_permission_schedule: ' + a.audit_id + ' ' + a.tid + ' ');
+                    if (existTenderPermission.length === 0) {
+                        const tender_permission = { id: uuid.v4(), pid: existTender[0].project_id, spid: existTender[0].spid, tid: existTender[0].id, uid: a.audit_id, schedule: schedule_permission };
+                        const [spSql, spSqlParam] = getInsertSql('zh_tender_permission', tender_permission);
+                        await querySql(spSql, spSqlParam);
+                    } else {
+                        await querySql('Update zh_tender_permission SET schedule = ? WHERE id = ?; ', [schedule_permission, existTenderPermission[0].id]);
+                    }
+                }
+            }
+        }
+        console.log('END Update;');
+    } catch (err) {
+        console.log(err);
+    }
+    BaseUtil.closePool();
+};
+doComplete();

+ 2 - 1
sql/update.sql

@@ -49,7 +49,8 @@ ADD COLUMN `sgt_tp_unit` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci
 ADD COLUMN `pf_tp_unit` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '元' COMMENT '财评/造价站批复-金额单位' AFTER `pf_tp`,
 ADD COLUMN `zb_tp_unit` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '元' COMMENT '招标完成-金额单位' AFTER `zb_tp`;
 
-
+ALTER TABLE `zh_tender_permission`
+ADD COLUMN `schedule` varchar(255) NOT NULL DEFAULT '' COMMENT '标段进度权限(,分隔,具体见代码定义)' AFTER `safe_payment`;
 
 
 ------------------------------------