Browse Source

Merge branch 'master' of http://smartcost.f3322.net:3000/caiaolin/Calculation

MaiXinRong 6 years ago
parent
commit
8c0721f9b2

+ 26 - 0
app/const/account_group.js

@@ -0,0 +1,26 @@
+'use strict';
+
+/**
+ * 项目组和账号权限
+ *
+ * @author ELlisran
+ * @date 2019/3/20
+ * @version
+ */
+const accountGroup = {
+    JSDW: 1,
+    JLDW: 2,
+    SGDW: 3,
+    SJDW: 4,
+};
+
+const group = [];
+group[accountGroup.JSDW] = '建设单位';
+group[accountGroup.JLDW] = '监理单位';
+group[accountGroup.SGDW] = '施工单位';
+group[accountGroup.SJDW] = '设计单位';
+
+module.exports = {
+    type: accountGroup,
+    group,
+};

+ 48 - 0
app/const/account_permission.js

@@ -0,0 +1,48 @@
+'use strict';
+
+/**
+ * 用户权限相关常量
+ *
+ * @author Ellisran
+ * @date 2019/3/26
+ * @version
+ */
+const create_tender = {
+    tzfj: 0,
+    cjtzxd: 1,
+    cjjlq: 2,
+    cjgcbg: 3,
+};
+const create_tender_group = [];
+create_tender_group[create_tender.tzfj] = '台账分解';
+create_tender_group[create_tender.cjtzxd] = '创建台账修订';
+create_tender_group[create_tender.cjjlq] = '创建计量期';
+create_tender_group[create_tender.cjgcbg] = '创建工程变更';
+
+// 权限管理页
+const permission = {
+    tender: {
+        class: 'fa fa-list-ul',
+        title: '标段管理',
+        type: 'checkbox',
+        children: [
+            { title: '创建标段', value: 1 },
+            { title: '查阅所有标段', value: 2 },
+        ],
+    },
+    cooperation: {
+        class: '',
+        title: '协作办公',
+        type: 'radio',
+        children: [
+            { title: '启用', value: 1 },
+            { title: '关闭', value: 0 },
+        ],
+    },
+};
+
+module.exports = {
+    tenderPermission: create_tender,
+    tenderPermissionList: create_tender_group,
+    permission,
+};

+ 25 - 0
app/controller/change_controller.js

@@ -15,6 +15,7 @@ const path = require('path');
 const audit = require('../const/audit');
 const codeRuleConst = require('../const/code_rule');
 const changeConst = require('../const/change');
+const accountGroup = require('../const/account_group').group;
 // const tenderMenu = require('../../config/menu').tenderMenu;
 
 module.exports = app => {
@@ -291,6 +292,30 @@ module.exports = app => {
 
                     renderData.dealBillList = dealBillList;
                     renderData.changeUnits = ctx.tender.info.precision;
+                    renderData.accountGroup = accountGroup;
+                    // 获取所有项目参与者
+                    const accountList = await ctx.service.projectAccount.getAllDataByCondition({
+                        where: { project_id: ctx.session.sessionProject.id, enable: 1 },
+                        columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group'],
+                    });
+                    renderData.accountList = accountList;
+                    // 重新上报获取审批流程
+                    if (auditStatus === 2) {
+                        const auditList2 = await ctx.service.changeAudit.getListByBack(change.cid, change.times);
+                        // 展示页右侧审批流程列表
+                        const auditList3 = [];
+                        for (let time = 1; time <= change.times; time++) {
+                            const auditTimeList = [];
+                            for (const al of auditList2) {
+                                if (al.times === time) {
+                                    auditTimeList.push(al);
+                                }
+                            }
+                            auditList3.push(auditTimeList);
+                        }
+                        renderData.auditList3 = auditList3;
+                    }
+
                     // 根据清单获取提交数据和计算总金额
                     const changeListData = [];
                     const changeWhiteListData = [];

+ 1 - 1
app/controller/ledger_audit_controller.js

@@ -96,7 +96,7 @@ module.exports = app => {
                 renderData.ledgerSpreadSetting = JSON.stringify(ledgerSpread);
                 renderData.posSpreadSetting = JSON.stringify(posSpread);
                 renderData.readOnly = true;
-                renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.ledger.audit),
+                renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.ledger.audit);
                 await this.layout('ledger/audit.ejs', renderData, 'ledger/audit_modal.ejs');
             } catch (err) {
                 this.log(err);

+ 207 - 0
app/controller/setting_controller.js

@@ -11,6 +11,8 @@
 const officeList = require('../const/cld_office').list;
 const settingConst = require('../const/setting.js');
 const settingMenu = require('../../config/menu').settingMenu;
+const accountGroup = require('../const/account_group').group;
+const permission = require('../const/account_permission').permission;
 
 module.exports = app => {
 
@@ -85,9 +87,26 @@ module.exports = app => {
                 if (projectData === null) {
                     throw '没有对应的项目数据';
                 }
+                if (ctx.session.sessionUser.is_admin === 0) {
+                    throw '没有访问权限';
+                }
+
+                // 获取数据规则
+                // const rule = ctx.service.projectAccount.rule('updateUser');
+                // const frontRule = ctx.helper.validateConvert(rule);
+
+                // 获取项目用户列表
+                const accountData = await ctx.service.projectAccount.getAllDataByCondition({
+                    where: { project_id: projectId },
+                    columns: ['id', 'account', 'name', 'company', 'role', 'mobile', 'telephone', 'enable', 'is_admin', 'account_group', 'permission', 'cooperation'],
+                });
 
                 const renderData = {
                     projectData,
+                    accountData,
+                    accountGroup,
+                    permission,
+                    // rule: JSON.stringify(frontRule),
                 };
                 await this.layout('setting/user.ejs', renderData, 'setting/user_modal.ejs');
             } catch (error) {
@@ -97,6 +116,167 @@ module.exports = app => {
         }
 
         /**
+         * 项目设置 -- 账号启用和停用设置(Post)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async userSwitch(ctx) {
+            const responseData = {
+                err: 0, msg: '', data: null,
+            };
+            try {
+                // 获取项目数据
+                const projectId = ctx.session.sessionProject.id;
+                const projectData = await ctx.service.project.getDataById(projectId);
+                if (projectData === null) {
+                    throw '没有对应的项目数据';
+                }
+                if (ctx.session.sessionUser.is_admin === 0) {
+                    throw '没有访问权限';
+                }
+                const data = JSON.parse(ctx.request.body.data);
+                const result = await ctx.service.projectAccount.update(data, { id: data.id });
+                if (!result) {
+                    throw '提交数据失败';
+                }
+            } catch (err) {
+                this.log(err);
+                responseData.err = 1;
+                responseData.msg = err;
+            }
+            ctx.body = responseData;
+        }
+
+        /**
+         * 项目设置 -- 账号添加(Post)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async addUser(ctx) {
+            const projectData = ctx.session.sessionProject;
+            try {
+                // 验证数据
+                if (projectData.id === undefined) {
+                    throw '不存在对应的项目数据';
+                }
+
+                // 获取验证规则
+                const rule = ctx.service.projectAccount.rule('add');
+                ctx.validate(rule);
+
+                const result = await ctx.service.projectAccount.save(ctx.request.body);
+                if (!result) {
+                    throw '保存账号数据失败';
+                }
+
+                this.setMessage('保存账号数据成功', this.messageType.SUCCESS);
+                ctx.redirect('/' + ctx.controllerName + '/user');
+            } catch (error) {
+                console.log(error);
+                this.setMessage(error.toString(), this.messageType.ERROR);
+                ctx.redirect(ctx.request.headers.referer);
+            }
+        }
+
+        /**
+         * 项目设置 -- 账号编辑(Post)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async updateUser(ctx) {
+            const projectData = ctx.session.sessionProject;
+            try {
+                // 验证数据
+                if (projectData.id === undefined) {
+                    throw '不存在对应的项目数据';
+                }
+
+                // 获取验证规则
+                const rule = ctx.service.projectAccount.rule('modify');
+                ctx.validate(rule);
+
+                const result = await ctx.service.projectAccount.save(ctx.request.body);
+                if (!result) {
+                    throw '保存账号数据失败';
+                }
+
+                this.setMessage('保存账号数据成功', this.messageType.SUCCESS);
+                ctx.redirect('/' + ctx.controllerName + '/user');
+            } catch (error) {
+                console.log(error);
+                this.setMessage(error.toString(), this.messageType.ERROR);
+                ctx.redirect(ctx.request.headers.referer);
+            }
+        }
+
+        async resetUserPassword(ctx) {
+            const response = {
+                err: 0,
+                msg: '',
+            };
+            try {
+                // 获取项目数据
+                const projectId = ctx.session.sessionProject.id;
+                const projectData = await ctx.service.project.getDataById(projectId);
+                if (projectData === null) {
+                    throw '没有对应的项目数据';
+                }
+                if (ctx.session.sessionUser.is_admin === 0) {
+                    throw '没有访问权限';
+                }
+
+                const accountId = parseInt(ctx.request.body.id);
+                let password = ctx.request.body.reset_password;
+                password = password.toString();
+                if (isNaN(accountId) || accountId <= 0 || password.length < 6) {
+                    throw '参数错误';
+                }
+                const result = await ctx.service.projectAccount.resetPassword(accountId, password);
+                if (!result) {
+                    throw '重置密码失败!';
+                }
+            } catch (error) {
+                response.err = 1;
+                response.msg = error;
+            }
+
+            ctx.body = response;
+        }
+
+        /**
+         * 项目设置 -- 账号权限编辑(Post)
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async permission(ctx) {
+            const projectData = ctx.session.sessionProject;
+            try {
+                // 验证数据
+                if (projectData.id === undefined) {
+                    throw '不存在对应的项目数据';
+                }
+
+                const accountId = parseInt(ctx.request.body.id);
+                const accountInfo = await ctx.service.projectAccount.getDataById(accountId);
+                if (accountInfo === null) {
+                    throw '不存在该客户';
+                }
+
+                const result = await ctx.service.projectAccount.permissionSave(accountId, ctx.request.body);
+                if (!result) {
+                    throw '修改权限失败!';
+                }
+
+                this.setMessage('保存账号数据成功', this.messageType.SUCCESS);
+                ctx.redirect('/' + ctx.controllerName + '/user');
+            } catch (error) {
+                console.log(error);
+                this.setMessage(error.toString(), this.messageType.ERROR);
+                ctx.redirect(ctx.request.headers.referer);
+            }
+        }
+
+        /**
          * 项目设置 -- 自定义标段分类(Get)
          *
          * @param ctx
@@ -110,6 +290,9 @@ module.exports = app => {
                 if (projectData === null) {
                     throw '没有对应的项目数据';
                 }
+                if (ctx.session.sessionUser.is_admin === 0) {
+                    throw '没有访问权限';
+                }
 
                 const categoryData = await ctx.service.category.getAllCategory(projectId);
                 const tenderData = await ctx.service.tender.getList();
@@ -285,6 +468,30 @@ module.exports = app => {
                 ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
+
+        /**
+         * 检测账户是否存在
+         *
+         * @param {Object} ctx -egg全局变量
+         * @return {void}
+         */
+        async accountExist(ctx) {
+            const projectData = ctx.session.sessionProject;
+            const responseData = {
+                err: 0, msg: '', data: null,
+            };
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const account = data.account;
+                if (projectData.id === undefined) {
+                    throw '不存在对应项目';
+                }
+                responseData.data = await ctx.service.projectAccount.isAccountExist(account, projectData.id);
+                ctx.body = responseData;
+            } catch (error) {
+                ctx.body = { err: 1, msg: error.toString(), data: null };
+            }
+        }
     }
 
     return SettingController;

+ 50 - 2
app/controller/tender_controller.js

@@ -13,6 +13,7 @@ const codeRuleConst = require('../const/code_rule');
 const settingConst = require('../const/setting.js');
 const tenderMenu = require('../../config/menu').tenderMenu;
 const auditConst = require('../const/audit').flow;
+const accountPermission = require('../const/account_permission');
 
 module.exports = app => {
 
@@ -34,7 +35,6 @@ module.exports = app => {
             try {
                 const tenderList = await this.ctx.service.tender.getList();
                 const categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
-
                 const renderData = {
                     tenderList,
                     tenderConst,
@@ -44,6 +44,7 @@ module.exports = app => {
                     measureType: tenderConst.measureType,
                     jsFiles: this.app.jsFiles.common.concat(this.jsFiles),
                     auditConst,
+                    userPermission: this.ctx.session.sessionUser.permission !== '' ? JSON.parse(this.ctx.session.sessionUser.permission) : null,
                 };
                 await this.layout(view, renderData, modal);
             } catch (err) {
@@ -96,7 +97,10 @@ module.exports = app => {
                 const responseData = {
                     err: 0, msg: '', data: null,
                 };
-
+                const userPermission = ctx.session.sessionUser.permission !== '' ? JSON.parse(ctx.session.sessionUser.permission) : null;
+                if (userPermission === null || userPermission.tender === undefined || userPermission.tender.indexOf('1') === -1) {
+                    throw '当前用户没有创建标段的权限';
+                }
                 const data = JSON.parse(ctx.request.body.data);
                 if (!data.name || data.name === '') {
                     throw '标段信息不完整';
@@ -176,6 +180,7 @@ module.exports = app => {
                     tenderInfo: ctx.tender.info,
                     tenderMenu: this.menu.tenderMenu,
                     preUrl: '/tender/' + ctx.tender.id,
+                    cooperation: ctx.session.sessionUser.cooperation,
                 };
                 await this.layout('tender/detail.ejs', renderData);
             } catch (error) {
@@ -232,6 +237,49 @@ module.exports = app => {
         }
 
         /**
+         * 标段协作办公
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async tenderCooperation(ctx) {
+            const tenderId = ctx.params.id;
+            try {
+                if (!ctx.session.sessionUser.cooperation) {
+                    throw '权限不足';
+                }
+                const tender = await ctx.service.tender.getDataById(tenderId);
+                const user = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                // 获取已参与协作用户列表
+                const cooperationArray = [];
+                if (tender.cooperation !== null && tender.cooperation !== '') {
+                    const cooperationList = JSON.parse(tender.cooperation);
+                    for (const cl in cooperationList) {
+                        const clArray = [];
+                        for (const audit of cooperationList[cl]) {
+                            const userInfo = await ctx.service.projectAccount.getDataById(audit);
+                            clArray.push(userInfo);
+                        }
+                        cooperationArray[cl] = clArray;
+                    }
+                }
+
+                const renderData = {
+                    user,
+                    tender,
+                    tenderMenu: this.menu.tenderMenu,
+                    preUrl: '/tender/' + tenderId,
+                    tenderPermissionList: accountPermission.tenderPermissionList,
+                    cooperationArray,
+                };
+                await this.layout('tender/cooperation.ejs', renderData, 'tender/cooperationModal.ejs');
+            } catch (error) {
+                this.log(error);
+                this.ctx.redirect('/tender/' + tenderId);
+            }
+        }
+
+        /**
          * 添加标段操作
          *
          * @param {Object} ctx - egg全局变量

+ 31 - 0
app/extend/helper.js

@@ -92,6 +92,37 @@ module.exports = {
         return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m);
     },
 
+    accAdd(arg1, arg2) {
+        let r1;
+        let r2;
+        try {
+            r1 = arg1.toString().split('.')[1].length;
+        } catch (e) {
+            r1 = 0;
+        }
+        try {
+            r2 = arg2.toString().split('.')[1].length;
+        } catch (e) {
+            r2 = 0;
+        }
+        const c = Math.abs(r1 - r2);
+        const m = Math.pow(10, Math.max(r1, r2));
+        if (c > 0) {
+            const cm = Math.pow(10, c);
+            if (r1 > r2) {
+                arg1 = Number(arg1.toString().replace('.', ''));
+                arg2 = Number(arg2.toString().replace('.', '')) * cm;
+            } else {
+                arg1 = Number(arg1.toString().replace('.', '')) * cm;
+                arg2 = Number(arg2.toString().replace('.', ''));
+            }
+        } else {
+            arg1 = Number(arg1.toString().replace('.', ''));
+            arg2 = Number(arg2.toString().replace('.', ''));
+        }
+        return (arg1 + arg2) / m;
+    },
+
     // 四舍五入或末尾加零,实现类似php的 sprintf("%.".decimal."f", val);
     roundNum(val, decimals) {
         if (val !== '') {

+ 2 - 2
app/public/css/toast.css

@@ -7,7 +7,7 @@
     margin: 0 auto;
     opacity: 0.8;
     box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
-    z-index: 999;
+    z-index: 9999 !important;
     padding: 15px;
     border-radius: 3px;
     color: #ffffff;
@@ -39,4 +39,4 @@
 .toast.info {
     background-color: rgba(53, 184, 224, 0.8);
     border: 2px solid #35b8e0;
-}
+}

+ 73 - 53
app/public/js/change_set.js

@@ -45,6 +45,20 @@ $(document).ready(() => {
 
     // 上报时按钮点击
     $('a[data-target="#sub-ap"]').on('click', function () {
+        let category = $(this).attr('data-category');
+        if (category === 'save_change') {
+            // 保存修改modal
+            $('.up-change').hide();
+            $('.save-change').show();
+        } else {
+            // 上报审批modal
+            $('.up-change').show();
+            $('.save-change').hide();
+        }
+    });
+
+    // 重新上报时按钮点击
+    $('a[data-target="#sub-sp2"]').on('click', function () {
         let category = $(this).data('category');
         if (category === 'save_change') {
             // 保存修改modal
@@ -55,6 +69,7 @@ $(document).ready(() => {
             $('.up-change').show();
             $('.save-change').hide();
         }
+        $('#hideSp').attr('data-category', category);
     });
 
     // 提交表单
@@ -126,70 +141,75 @@ $(document).ready(() => {
         }
     });
 
-    // 搜索用户
-    $('#search_audit_btn').click(function () {
-        const keyword = $('#search_audit_input').val();
-        if (keyword === '') {
-            toastr.error('请输入姓名进行检索!');
-        } else {
-            $('#search_audit_list').html('');
-            const data = { keyword: keyword, type: 'more' };
-            postData('/search/user', data, function (result) {
-                const searchList = result;
-                $('#search_audit_list').html('');
-                if (searchList.length === 0) {
-                    toastr.error('不存在该用户姓名!');
-                } else {
-                    let search_audit_html = '';
-                    for (const s of searchList) {
-                        search_audit_html += '<div class="card border-primary" style="margin-bottom: 5px;">' +
-                            '<div class="card-body">' +
-                            '<h5 class="card-title">' +
-                            '<a class="btn btn-primary btn-sm pull-right add_audit_btn" ' +
-                            'href="javascript:void(0);" data-user="' + s.id + '/%/' + s.name + '/%/' + s.role + '/%/' + s.company + '">添加</a>' + s.name +
-                            '</h5>' +
-                            '<h6 class="card-subtitle mb-2 text-muted">' + s.role + '</h6>' +
-                            '<p class="card-text">' + s.company + '</p>' +
-                            '</div>' +
-                            '</div>';
-                    }
-                    $('#search_audit_list').html(search_audit_html);
-                }
-            });
+    // 审批人分组选择
+    $('#account_group').change(function () {
+        let account_html = '<option value="0">选择审批人</option>';
+        for (const account of accountList) {
+            if (parseInt($(this).val()) === 0 || parseInt($(this).val()) === account.account_group) {
+                const role = account.role !== '' ? '(' + account.role + ')' : '';
+                const company = account.company !== '' ? ' -' + account.company : '';
+                account_html += '<option value="' + account.id + '">' + account.name + role + company + '</option>';
+            }
         }
+        $('#account_list').html(account_html);
+    });
+
+    $('#hideSp').click(function () {
+       $('#sub-sp2').modal('hide');
     });
 
     // 添加到审批流程中
-    $('body').on('click', '.add_audit_btn', function () {
-        const userData = $(this).data('user').split('/%/');
-        // 先判断是否已存在该审批流程的审批人,再添加(不包括上报)
-        let auditListIdData = [];
-        $('#auditList li').each(function () {
-           let aid = $(this).data('auditid');
-           auditListIdData.push(aid);
-        });
-        if (!in_array(auditListIdData, userData[0])) {
-            // 令其它的审批人流程图标转换
-            $('#auditList li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
-            // 添加新审批人
-            const addhtml = '<li class="list-group-item" data-auditmsg="' + $(this).data('user') + '"' +
-                'data-auditid="' + userData[0] + '" >' +
-                '<a href="javascript:void(0);" class="text-danger pull-right remove_audit_btn">移除</a>' +
-                '<i class="fa fa-stop-circle"></i>' +
-                userData[1] + '<small class="text-muted">' + userData[2] + '</small>' +
-                '</li>';
-            $('#auditList').append(addhtml);
-        } else {
-            toastr.error('审批流程中已存在该用户!');
+    $('body').on('change', '#account_list', function () {
+        let id = $(this).val();
+        id = parseInt(id);
+        if (id !== 0) {
+            let auditListIdData = [];
+            $('#auditList li').each(function () {
+                let aid = $(this).data('auditid');
+                auditListIdData.push(aid);
+            });
+            if (!in_array(auditListIdData, id)) {
+                const accountInfo = accountList.find(function (item) {
+                    return item.id === id;
+                });
+                const user = accountInfo.id + '/%/' + accountInfo.name + '/%/' + accountInfo.role + '/%/' + accountInfo.company;
+                const addhtml = '<li class="list-group-item" data-auditmsg="' + user + '"' +
+                    'data-auditid="' + accountInfo.id + '" >' +
+                    '<a href="javascript:void(0);" class="text-danger pull-right remove_audit_btn">移除</a>' +
+                    '<span>' + (auditListIdData.length+1) + '</span> ' + accountInfo.name + '  <small class="text-muted">' + accountInfo.role + '</small>' +
+                    '<p class="m-0 ml-2"><small class="text-muted">' + accountInfo.company + '</small></p>' +
+                    '</li>';
+                $('#auditList').append(addhtml);
+
+                // 重新上报时。令其它的审批人流程图标转换
+                $('#shenpi-audit-list li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
+                // 添加新审批人
+                const addhtml2 = '<li class="list-group-item" data-auditid="' + accountInfo.id + '" >' +
+                    '<i class="fa fa-stop-circle"></i>' +
+                    accountInfo.name + ' <small class="text-muted">' + accountInfo.role + '</small>' +
+                    '</li>';
+                $('#shenpi-audit-list').append(addhtml2);
+            } else {
+                toastr.error('审批流程中已存在该用户!');
+            }
         }
     });
 
     // 移除审批流程的审批人
     $('body').on('click', '.remove_audit_btn', function () {
+        const uid = $(this).parents('li').attr('data-auditid');
         $(this).parents('li').remove();
+        let index = 1;
+        $('#auditList li').each(function () {
+            $(this).children('span').text(index);
+            index++;
+        });
+
+        // 重新上报时。移除审批流程
         // 令最后一个图标转换
-        if ($('#auditList li').length !== 0 && !$('#auditList li i').hasClass('fa-stop-circle')) {
-            $('#auditList li').eq($('#auditList li').length-1).children('i')
+        $('#shenpi-audit-list li[data-auditid="' + uid + '"]').remove();
+        if ($('#shenpi-audit-list li').length !== 0 && !$('#shenpi-audit-list li i').hasClass('fa-stop-circle')) {
+            $('#shenpi-audit-list li').eq($('#shenpi-audit-list li').length-1).children('i')
                 .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
         }
     });

+ 211 - 0
app/public/js/setting.js

@@ -0,0 +1,211 @@
+'use strict';
+
+/**
+ * 项目信息js
+ *
+ * @author EllisRan.
+ * @date 2019/3/19
+ * @version
+ */
+
+$(document).ready(() => {
+    // 启用和停用账号
+    $('.account-switch-btn').on('click', function () {
+        const data = {
+            enable: $(this).hasClass('btn-outline-success') ? 1 : 0,
+            id: $(this).data('account'),
+        };
+        postData('/setting/user/switch', data, function () {
+            window.location.href = '/setting/user';
+        });
+    });
+
+    // 编辑账号
+    $('a[data-target="#edit-user"]').on('click', function () {
+        const account = $(this).data('account');
+        $('#edit-user input[name="account"]').val(account.account);
+        $('#edit-user input[name="name"]').val(account.name);
+        $('#edit-user input[name="company"]').val(account.company);
+        $('#edit-user input[name="role"]').val(account.role);
+        $('#edit-user input[name="mobile"]').val(account.mobile);
+        $('#edit-user input[name="telephone"]').val(account.telephone);
+        $('#edit-user input[name="id"]').val(account.id);
+        $('#edit-user select[name="account_group"]').val(account.account_group);
+        $('#edit-user input[class="account-check"]').val(account.account);
+    });
+
+    // 分配随机密码
+    $("#rand-password").click(function() {
+        const password = randPassword();
+        $(this).parent().parent().find('input').val(password);
+    });
+
+    // 重置密码
+    let isChange = false;
+    $("#reset-password-btn").click(function() {
+        try {
+            if (isChange) {
+                throw '稍后再操作';
+            }
+            const resetPassword = $("#reset-password").val();
+            const id = $("#user-id").val();
+            if (resetPassword.length < 6) {
+                throw '密码长度不能小于6';
+            }
+            if (!/^[0-9a-zA-Z*~!@&%$^\\(\\)#_\[\]\-\+={}|?'":,<>.`]+$/.test(resetPassword)) {
+                throw '密码只支持英文数字及符号';
+            }
+            const btn = $(this);
+            $.ajax({
+                url: '/setting/user/reset/password',
+                type: 'post',
+                data: { id: id, reset_password: resetPassword },
+                dataType: 'json',
+                error: function() {
+                    isChange = false;
+                    btn.html('重置密码');
+                    throw '网络错误!';
+                },
+                beforeSend: function(xhr) {
+                    let csrfToken = Cookies.get('csrfToken');
+                    xhr.setRequestHeader('x-csrf-token', csrfToken);
+                    isChange = true;
+                    btn.html('<i class="fa fa-spinner fa-pulse"></i>');
+                },
+                success: function(response) {
+                    isChange = false;
+                    btn.html('重置密码');
+                    if (response.err !== 0) {
+                        throw response.msg;
+                    }
+                    $("#reset-password").val('');
+                    toast('重置成功', 'success', 'check');
+                }
+            });
+        } catch (error) {
+            toast(error, 'error', 'exclamation-circle');
+            console.log(error);
+        }
+    });
+
+    // 账号查重
+    $('input[name="account"]').on('blur', function () {
+        const self = $(this);
+        if (self.val() !== self.siblings('input').val()) {
+            const data = {account: $(this).val()};
+            postData('/setting/user/exist', data, function (data) {
+                if (data === null) {
+                    self.removeClass('is-invalid');
+                } else {
+                    self.addClass('is-invalid');
+                }
+            })
+        } else {
+            self.removeClass('is-invalid');
+        }
+    });
+
+    // 选中创建标段才可以选择协作办公
+    $('a[data-target="#edit-user2"]').on('click', function () {
+        $('#edit-user2 input:radio').prop('checked', false);
+        $('#edit-user2 input:checkbox').prop('checked', false);
+        const account = $(this).data('account');
+        $('#edit-user2 input[name="id"]').val(account.id);
+        // 权限赋值
+        if (account.permission !== '') {
+            const permission = JSON.parse(account.permission);
+            for (const pm in permission) {
+                if (pm === 'tender' && permission[pm].indexOf('1') !== -1) {
+                    $('#edit-user2 input[name="cooperation"]').attr('disabled', false);
+                } else {
+                    $('#edit-user2 input[name="cooperation"]').attr('disabled', true);
+                }
+                for (const index of permission[pm]) {
+
+                    $('#edit-user2 input:checkbox[id="' + pm + '_' + index + '"]').prop('checked', true);
+                }
+            }
+        }
+        // 协作赋值
+        $('#edit-user2 input:radio[value="' + account.cooperation + '"]').prop('checked', true);
+    });
+});
+
+
+/**
+ * 表单检测
+ */
+function checkUserForm(status) {
+    try {
+        if (status === 'add') {
+            if ($('#add-user select[name="account_group"]').val() == 0) {
+                throw '请选择账号组';
+            }
+            if ($('#add-user input[name="account"]').val() == '' || $('#add-user input[name="account"]').hasClass('is-invalid')) {
+                throw '账号不能为空或已存在';
+            }
+            if ($('#add-user input[name="password"]').val() == '' || $('#add-user input[name="password"]').val().length < 6) {
+                throw '密码不能为空或不能小于6位';
+            }
+            if (!/^[0-9a-zA-Z*~!@&%$^\\(\\)#_\[\]\-\+={}|?'":,<>.`]+$/.test($('#add-user input[name="password"]').val())) {
+                throw '密码只支持英文数字及符号';
+            }
+            if ($('#add-user input[name="name"]').val() == '') {
+                throw '姓名不能为空';
+            }
+            if ($('#add-user input[name="company"]').val() == '') {
+                throw '单位名称不能为空';
+            }
+            if ($('#add-user input[name="role"]').val() == '') {
+                throw '职位名称不能为空';
+            }
+            if ($('#add-user input[name="mobile"]').val() == '') {
+                throw '手机号不能为空';
+            }
+        } else {
+            if ($('#edit-user select[name="account_group"]').val() == 0) {
+                throw '请选择账号组';
+            }
+            if ($('#edit-user input[name="account"]').val() == '' || $('#add-user input[name="account"]').hasClass('is-invalid')) {
+                throw '账号不能为空或已存在';
+            }
+            if ($('#edit-user input[name="name"]').val() == '') {
+                throw '姓名不能为空';
+            }
+            if ($('#edit-user input[name="company"]').val() == '') {
+                throw '单位名称不能为空';
+            }
+            if ($('#edit-user input[name="role"]').val() == '') {
+                throw '职位名称不能为空';
+            }
+            if ($('#edit-user input[name="mobile"]').val() == '') {
+                throw '手机号不能为空';
+            }
+        }
+    } catch (err) {
+        toast(err, 'error', 'exclamation-circle');
+        return false;
+    }
+}
+
+/**
+ * 随机密码
+ */
+function randPassword() {
+    let result = '';
+    // 随机6-10位
+    const length = Math.ceil(Math.random() * 2 + 8);
+    let numberSeed = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    let stringSeed = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+        'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+        'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
+
+    const randSeed = stringSeed.concat(numberSeed);
+    const seedLength = randSeed.length - 1;
+    for (let i = 0; i < length; i++) {
+        const index = Math.ceil(Math.random() * seedLength);
+        result += randSeed[index];
+    }
+
+    return result;
+}

+ 10 - 0
app/router.js

@@ -34,6 +34,14 @@ module.exports = app => {
     app.post('/setting/updateinfo/:id', sessionAuth, 'settingController.updateinfo');
     // 账号设置
     app.get('/setting/user', sessionAuth, 'settingController.user');
+    // 账号停用和启用
+    app.post('/setting/user/switch', sessionAuth, 'settingController.userSwitch');
+    app.post('/setting/user/add', sessionAuth, 'settingController.addUser');
+    app.post('/setting/user/update', sessionAuth, 'settingController.updateUser');
+    app.post('/setting/user/permission', sessionAuth, 'settingController.permission');
+    app.post('/setting/user/reset/password', sessionAuth, 'settingController.resetUserPassword');
+    app.post('/setting/user/exist', sessionAuth, 'settingController.accountExist');
+
     // 标段自定义类别
     app.get('/setting/category', sessionAuth, 'settingController.category');
     app.post('/setting/category/add', sessionAuth, 'settingController.addCategory');
@@ -68,6 +76,8 @@ module.exports = app => {
     app.get('/tender/:id/type', sessionAuth, 'tenderController.tenderType');
     app.post('/tender/:id/save', sessionAuth, tenderCheck, 'tenderController.saveTenderInfo');
     app.post('/tender/rule', sessionAuth, 'tenderController.rule');
+    // 标段协作办公
+    app.get('/tender/:id/cooperation', sessionAuth, tenderCheck, 'tenderController.tenderCooperation');
 
 
     // 台账管理相关

+ 20 - 19
app/service/change.js

@@ -333,26 +333,27 @@ module.exports = app => {
                 changeList.push.apply(changeList, changeWhiteList);
                 const insertCL = [];
                 let total_price = 0;
-                for (const cl of changeList) {
-                    const clInfo = cl.split(';');
-                    const clArray = {
-                        tid: tenderId,
-                        cid: changeInfo.cid,
-                        lid: clInfo[7],
-                        code: clInfo[0],
-                        name: clInfo[1],
-                        unit: clInfo[2],
-                        unit_price: clInfo[3],
-                        oamount: clInfo[4],
-                        camount: clInfo[5],
-                        samount: '',
-                        detail: clInfo[6],
-                    };
-                    insertCL.push(clArray);
-                    total_price += this.ctx.helper.accMul(clArray.unit_price, clArray.camount);
+                if (changeList.length > 0) {
+                    for (const cl of changeList) {
+                        const clInfo = cl.split(';');
+                        const clArray = {
+                            tid: tenderId,
+                            cid: changeInfo.cid,
+                            lid: clInfo[7],
+                            code: clInfo[0],
+                            name: clInfo[1],
+                            unit: clInfo[2],
+                            unit_price: clInfo[3],
+                            oamount: clInfo[4],
+                            camount: clInfo[5],
+                            samount: '',
+                            detail: clInfo[6],
+                        };
+                        insertCL.push(clArray);
+                        total_price = this.ctx.helper.accAdd(total_price, this.ctx.helper.accMul(clArray.unit_price, clArray.camount));
+                    }
+                    await this.transaction.insert(this.ctx.service.changeAuditList.tableName, insertCL);
                 }
-                await this.transaction.insert(this.ctx.service.changeAuditList.tableName, insertCL);
-
                 // 修改变更令基本数据
                 const cArray = {
                     code: postData.code,

+ 22 - 0
app/service/change_audit.js

@@ -223,6 +223,28 @@ module.exports = app => {
             const list = await this.db.query(sql, sqlParam);
             return list;
         }
+
+        /**
+         * 获取除当前次数的审批人列表
+         * @param {Object} cid - 变更令id
+         * @param {int} times - 次数
+         * @return {object} 返回结果
+         */
+        async getListByBack(cid, times) {
+            this.initSqlBuilder();
+            this.sqlBuilder.setAndWhere('cid', {
+                value: this.db.escape(cid),
+                operate: '=',
+            });
+            this.sqlBuilder.setAndWhere('times', {
+                value: times,
+                operate: '!=',
+            });
+            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
+            const result = await this.db.query(sql, sqlParam);
+
+            return result;
+        }
     }
 
     return ChangeAudit;

+ 140 - 23
app/service/project_account.js

@@ -71,6 +71,25 @@ module.exports = app => {
                         auth_mobile: { type: 'mobile', allowEmpty: false },
                     };
                     break;
+                case 'add':
+                    rule = {
+                        account: { type: 'string', required: true },
+                        password: { type: 'string', required: true, min: 6 },
+                        name: { type: 'string', required: true },
+                        company: { type: 'string', required: true },
+                        role: { type: 'string', required: true },
+                        mobile: { type: 'mobile', required: true },
+                    };
+                    break;
+                case 'modify':
+                    rule = {
+                        account: { type: 'string', required: true },
+                        name: { type: 'string', required: true },
+                        company: { type: 'string', required: true },
+                        role: { type: 'string', required: true },
+                        mobile: { type: 'mobile', required: true },
+                    };
+                    break;
                 default:
                     break;
             }
@@ -97,6 +116,7 @@ module.exports = app => {
                 let projectInfo = {};
                 let projectList = [];
                 let permission = '';
+                let cooperation = 0;
                 if (loginType === 2) {
                     // 查找项目数据
                     const projectData = await this.ctx.service.project.getProjectByCode(data.project.toString());
@@ -121,20 +141,20 @@ module.exports = app => {
                     }
 
                     projectList = await this.getProjectInfoByAccount(data.account);
+                    permission = accountData.permission;
+                    cooperation = accountData.cooperation;
 
                     // 判断密码
-                    if (accountData.is_admin === 1) {
-                        // 管理员则用sso通道判断
-                        const sso = new SSO(this.ctx);
-                        result = await sso.loginValid(data.account, data.project_password.toString());
-                        permission = 'all';
-                    } else {
-                        // 加密密码
-                        const encryptPassword = crypto.createHmac('sha1', data.account).update(data.project_password)
-                            .digest().toString('base64');
-                        result = encryptPassword === accountData.password;
-                        permission = accountData.permission;
-                    }
+                    // if (accountData.is_admin === 1) {
+                    //     // 管理员则用sso通道判断
+                    //     const sso = new SSO(this.ctx);
+                    //     result = await sso.loginValid(data.account, data.project_password.toString());
+                    // } else {
+                    // 加密密码
+                    const encryptPassword = crypto.createHmac('sha1', data.account).update(data.project_password)
+                        .digest().toString('base64');
+                    result = encryptPassword === accountData.password;
+                    // }
                 } else {
                     // sso登录(演示版)
                     const sso = new SSO(this.ctx);
@@ -162,9 +182,11 @@ module.exports = app => {
                         name: accountData.name,
                         accountId: accountData.id,
                         loginTime: currentTime,
+                        is_admin: accountData.is_admin,
                         sessionToken,
                         loginType,
                         permission,
+                        cooperation,
                     };
                     this.ctx.session.sessionProject = projectInfo;
                     this.ctx.session.sessionProjectList = projectList;
@@ -276,25 +298,38 @@ module.exports = app => {
          * 修改用户数据
          *
          * @param {Object} data - post过来的数据
-         * @param {Number} accountId - 账号id
          * @return {Boolean} - 返回修改结果
          */
-        async save(data, accountId) {
+        async save(data) {
             if (data._csrf !== undefined) {
                 delete data._csrf;
             }
-            accountId = parseInt(accountId);
-            accountId = isNaN(accountId) ? 0 : accountId;
-            let result = false;
+            const id = data.id !== undefined ? parseInt(data.id) : 0;
+            if (id > 0) {
+                // 修改操作时
+                delete data.create_time;
+                data.id = id;
+            } else {
+                // 重名检测
+                const accountData = await this.db.select(this.tableName, {
+                    where: {
+                        account: data.account,
+                        project_id: data.enterprise_id,
+                    },
+                });
+                if (accountData.length > 0) {
+                    throw '已存在对应的帐户名';
+                }
+
+                // 加密密码
+                data.password = crypto.createHmac('sha1', data.account).update(data.password)
+                    .digest().toString('base64');
 
-            if (accountId <= 0) {
-                return result;
             }
-            data.id = accountId;
+            const operate = id === 0 ? await this.db.insert(this.tableName, data) :
+                await this.db.update(this.tableName, data);
 
-            // 更新数据
-            const operate = await this.db.update(this.tableName, data);
-            result = operate.affectedRows > 0;
+            const result = operate.affectedRows > 0;
 
             return result;
         }
@@ -384,6 +419,88 @@ module.exports = app => {
 
             return this.save(updateData, accountId);
         }
+
+        /**
+         * 重置密码
+         *
+         * @param {Number} accountId - 账号id
+         * @param {String} password - 重置的密码
+         * @return {Boolean} - 重置结果
+         */
+        async resetPassword(accountId, password) {
+            // 初始化事务
+            this.transaction = await this.db.beginTransaction();
+            let result = false;
+            try {
+                // 查找对应账号数据
+                const accountData = await this.getDataByCondition({ id: accountId });
+                if (accountData.account === undefined) {
+                    throw '不存在对应账号';
+                }
+                // 加密密码
+                const encryptPassword = crypto.createHmac('sha1', accountData.account).update(password)
+                    .digest().toString('base64');
+                // 更新账号密码
+                const sql = 'UPDATE ?? SET password=? WHERE id=? AND password != ?;';
+                const sqlParam = [this.tableName, encryptPassword, accountId, 'SSO password'];
+                const operate = await this.transaction.query(sql, sqlParam);
+                result = operate.affectedRows > 0;
+
+                if (!result) {
+                    throw '更新密码失败';
+                }
+
+                // 发送短信
+                if (accountData.auth_mobile !== '') {
+                    const sms = new SMS(this.ctx);
+                    const content = '【纵横计量支付】账号:' + accountData.account + ',密码重置为:' + password;
+                    sms.send(accountData.auth_mobile, content);
+                }
+
+                this.transaction.commit();
+            } catch (error) {
+                this.transaction.rollback();
+            }
+
+            return result;
+        }
+
+        /**
+         * 判断是否存在对应的账号
+         *
+         * @param {String} account - 账号名称
+         * @param {Number} projectId - 项目id
+         * @return {Boolean} - 返回是否存在
+         */
+        async isAccountExist(account, projectId) {
+            const accountData = await this.db.get(this.tableName, { account, project_id: projectId });
+            return accountData;
+        }
+
+        /**
+         * 保存用户权限数据
+         *
+         * @param {Object} data - post过来的数据
+         * @return {Boolean} - 返回权限修改结果
+         */
+        async permissionSave(id, data) {
+            if (data._csrf !== undefined) {
+                delete data._csrf;
+            }
+            const updateData = {
+                id,
+                cooperation: data.cooperation,
+            };
+            delete data.cooperation;
+            delete data.id;
+            updateData.permission = JSON.stringify(data);
+
+            const operate = await this.db.update(this.tableName, updateData);
+
+            const result = operate.affectedRows > 0;
+
+            return result;
+        }
     }
 
     return ProjectAccount;

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

@@ -13,10 +13,12 @@
                     </select>
                 </div>
             </div>
+            <% if (tender.user_id === uid) { %>
             <div>
                 <a href="#add-bj" data-toggle="modal" data-target="#add-bj" class="btn btn-sm btn-primary pull-right">新建变更令</a>
                 <a href="#setting" data-toggle="modal" data-target="#setting" class="btn btn-sm btn-outline-primary pull-right"><i class="fa fa-cog"></i></a>
             </div>
+            <% } %>
         </div>
     </div>
     <div class="content-wrap">

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

@@ -1,6 +1,10 @@
 <link rel="stylesheet" type="text/css" href="/public/css/datatable/dataTables.bootstrap4.min.css">
 <link rel="stylesheet" type="text/css" href="/public/css/datatable/fixedColumns.bootstrap4.min.css">
 <style type="text/css" class="init">
+    #tablist li .active {
+        background: #e4e7ea;
+        font-weight: 600;
+    }
     .qd-table .input-sm{
         height:30px;
         padding:2px;
@@ -138,8 +142,8 @@
             </div>
             <% } else if (auditStatus === 2) { %>
             <div>
-                <a href="#sub-ap" data-category="save_change" data-toggle="modal" data-target="#sub-ap" class="btn btn-sm btn-success pull-right">保存修改</a>
-                <a href="#sub-ap" data-category="up_change" data-toggle="modal" data-target="#sub-ap" class="btn btn-primary btn-sm pull-right">重新上报</a>
+                <a href="#sub-sp2" data-category="save_change" data-toggle="modal" data-target="#sub-sp2" class="btn btn-sm btn-success pull-right">保存修改</a>
+                <a href="#sub-sp2" data-category="up_change" data-toggle="modal" data-target="#sub-sp2" class="btn btn-primary btn-sm pull-right">重新上报</a>
                 <!--<a href="#" class="btn btn-outline-danger btn-sm pull-right text-truncate" style="max-width: 100px;" title="删除 <%- change.code %>">删除 <%- change.code %></a>-->
             </div>
             <% } else if (auditStatus === 3) { %>
@@ -735,6 +739,7 @@
 <script>
     const whiteList = JSON.parse('<%- JSON.stringify(whiteList) %>');
     const changeUnits = JSON.parse('<%- JSON.stringify(changeUnits) %>');
+    const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');
     const billsTable = {
         columnDefs: [
             { className: 'allwidth1', width: 100, targets: 0 },

+ 132 - 33
app/view/change/info_modal.ejs

@@ -41,16 +41,23 @@
             </div>
             <form method="post" action="/tender/<%- tender.id %>/change/<%- change.cid %>/save">
                 <div class="modal-body">
-                    <!--如未创建清单-->
-                    <!--<h5>还没添加任何变更清单,无法提交。</h5>-->
-                    <!--可以提交审批 但需要设置审批流程-->
                     <div class="form-group">
-                        <label>搜索审批人</label>
+                        <label>选择审批人</label>
                         <div class="input-group">
-                            <input class="form-control" placeholder="请输入姓名进行检索" type="text" id="search_audit_input">
-                            <div class="input-group-append">
-                                <button class="btn btn-outline-secondary" type="button" id="search_audit_btn"><i class="fa fa-search"></i></button>
+                            <div class="input-group-prepend">
+                                <select class="form-control" id="account_group">
+                                    <option value="0">所有分组</option>
+                                    <% for (const dw in accountGroup) { %>
+                                        <option value="<%= dw %>"><%= accountGroup[dw] %></option>
+                                    <% } %>
+                                </select>
                             </div>
+                            <select class="form-control" id="account_list">
+                                <option value="0">选择审批人</option>
+                                <% for (const account of accountList) { %>
+                                    <option value="<%= account.id %>"><%= account.name %><% if (account.role !== '') { %>(<%= account.role %>)<% } %><% if (account.company !== '') { %> -<%= account.company %><% } %></option>
+                                <% } %>
+                            </select>
                         </div>
                     </div>
                     <div id="search_audit_list">
@@ -59,26 +66,14 @@
                         <div class="card-header">
                             审批流程
                         </div>
-                        <ul class="list-group list-group-flush">
-                            <% for (const audit of auditList) { %>
-                                <% if (audit.usite === 0) { %>
-                                <li class="list-group-item">
-                                    <i class="fa fa-play-circle fa-rotate-90"></i>
-                                    <%= audit.name %><small class="text-muted"><%= audit.jobs %></small>
-                                </li>
-                                <% } %>
-                            <% } %>
-                        </ul>
                         <ul class="list-group list-group-flush" id="auditList">
-                            <% for (const audit of auditList) { %>
+                            <% for (const [index, audit] of auditList.entries()) { %>
                                 <% if (audit.usite !== 0) { %>
                                 <li class="list-group-item" data-auditmsg="<%= audit.uid + '/%/' + audit.name + '/%/' + audit.jobs + '/%/' + audit.company %>"
                                     data-auditid="<%= audit.uid %>">
                                     <a href="javascript:void(0)" class="text-danger pull-right remove_audit_btn">移除</a>
-                                    <% if (audit.usite === auditList.length-1) { %><i class="fa fa-stop-circle"></i>
-                                    <% } else { %><i class="fa fa-chevron-circle-down"></i>
-                                    <% } %>
-                                    <%= audit.name %><small class="text-muted"><%= audit.jobs %></small>
+                                    <span><%= index %></span> <%= audit.name %>  <small class="text-muted"><%= audit.jobs %></small>
+                                    <p class="m-0 ml-2"><small class="text-muted"><%= audit.company %></small></p>
                                 </li>
                                 <% } %>
                             <% } %>
@@ -126,11 +121,6 @@
                                 <tr><th>项目节编号</th><th>名称</th><th>部位明细</th><th>选择</th></tr>
                                 </thead>
                                 <tbody id="code-list" data-index="">
-                                <!--<tr><td colspan="3">自行编辑变更详情</td><td><input type="checkbox"></td></tr>-->
-                                <!--<tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台1#桩</td><td><input type="checkbox"></td></tr>-->
-                                <!--<tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台2#桩</td><td><input type="checkbox"></td></tr>-->
-                                <!--<tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台3#桩</td><td><input type="checkbox"></td></tr>-->
-                                <!--<tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台4#桩</td><td><input type="checkbox"></td></tr>-->
                                 </tbody>
                             </table>
                         </div>
@@ -145,6 +135,106 @@
         </div>
     </div>
 </div>
+
+<% if (auditStatus === 2) { %>
+    <!--重新上报-->
+    <div class="modal fade" id="sub-sp2" data-backdrop="static">
+        <div class="modal-dialog modal-lg" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">重新上报</h5>
+                </div>
+                <div class="modal-body">
+                    <div class="row">
+                        <div class="col-4">
+                            <a href="#sub-ap" data-toggle="modal" data-category="" data-target="#sub-ap" id="hideSp">修改审批流程</a>
+                            <div class="card mt-3">
+                                <ul class="list-group list-group-flush">
+                                    <% for (const audit of auditList) { %>
+                                        <% if (audit.usite === 0) { %>
+                                            <li class="list-group-item">
+                                                <i class="fa fa-play-circle fa-rotate-90"></i>
+                                                <%= audit.name %>  <small class="text-muted"><%= audit.jobs %></small>
+                                            </li>
+                                        <% } %>
+                                    <% } %>
+                                </ul>
+                                <ul class="list-group list-group-flush" id="shenpi-audit-list">
+                                    <% for (const [index,a] of auditList.entries()) { %>
+                                        <% if (a.usite !== 0 ) { %>
+                                            <li class="list-group-item" data-auditid="<%= a.uid %>">
+                                                <% if (index+1 !== auditList.length) { %>
+                                                    <i class="fa fa-chevron-circle-down"></i>
+                                                <% } else if (index+1 === auditList.length) { %>
+                                                    <i class="fa fa-stop-circle"></i>
+                                                <% } %>
+                                                <%= a.name %>  <small class="text-muted"><%= a.jobs %></small>
+                                            </li>
+                                        <% }%>
+                                    <% } %>
+                                </ul>
+                            </div>
+                        </div>
+                        <div class="col-8 modal-height-500" style="overflow: auto">
+                            <% for (const time in auditList3) { %>
+                            <% if (auditList3[time].length > 0) { %>
+                                <div class="card mt-3">
+                                    <ul class="list-group list-group-flush">
+                                        <% for (const [aindex,al] of auditList3[time].entries()) { %>
+                                            <li class="list-group-item">
+                                                <% if (al.usite === 0 && al.status === 2) { %>
+                                                    <span class="pull-right">重新上报中</span>
+                                                <% } else if (al.usite === 0 && al.status === 3) { %>
+                                                    <span class="text-success pull-right">上报</span>
+                                                <% } else if (al.usite !== 0 && al.status === 2) { %>
+                                                    <span class="pull-right">审批中</span>
+                                                <% } else if (al.usite !== 0 && al.status === 3) { %>
+                                                    <span class="text-success pull-right">审批通过</span>
+                                                <% } else if (al.usite !== 0 && al.status === 4) { %>
+                                                    <span class="text-danger pull-right">审批终止</span>
+                                                <% } else if (al.usite !== 0 && (al.status === 5 || al.status === 6)) { %>
+                                                    <span class="text-warning pull-right">审批退回 </span>
+                                                <% } %>
+                                                <h5 class="card-title">
+                                                    <% if (al.usite === 0 && al.status === 2 ) { %>
+                                                        <i class="fa fa-play-circle fa-rotate-90"></i>
+                                                    <% } else if (al.usite === 0 && al.status === 3 ) { %>
+                                                        <i class="fa fa-play-circle fa-rotate-90 text-success"></i>
+                                                    <% } else if (al.status === 1 || al.status === 2) { %>
+                                                        <i class="fa <% if (aindex+1 === auditList3[time].length) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> "></i>
+                                                    <% } else if (al.status === 3) { %>
+                                                        <i class="fa <% if (aindex+1 === auditList3[time].length) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> text-success"></i>
+                                                    <% } else if (al.status === 4) { %>
+                                                        <i class="fa <% if (aindex+1 === auditList3[time].length) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> text-danger"></i>
+                                                    <% } else if (al.status === 5 || al.status === 6) { %>
+                                                        <i class="fa <% if (aindex+1 === auditList3[time].length) { %>fa-stop-circle<% } else { %>fa-chevron-circle-down<% } %> text-warning"></i>
+                                                    <% } %>
+                                                    <%= al.name %>&nbsp;<small class="text-muted"><%= al.jobs %></small>
+                                                </h5>
+                                                <% if (al.sdesc !== '' && al.sdesc !== null) { %>
+                                                    <p class="card-text mb-1"><%= al.sdesc %></p>
+                                                <% } %>
+                                                <% if (al.sin_time !== null) { %>
+                                                    <p class="card-text"><small class="text-muted"><%= moment(al.sin_time).format('YYYY-MM-DD') %></small></p>
+                                                <% } %>
+                                            </li>
+                                        <% } %>
+                                    </ul>
+                                </div>
+                            <% } %>
+                            <% } %>
+                        </div>
+                    </div>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" data-sumbit="sumbit_change" data-category="up_change" class="btn btn-primary up-change">确认上报</button>
+                    <button type="button" data-sumbit="sumbit_change" data-category="save_change" class="btn btn-success save-change">保存修改</button>
+                </div>
+            </div>
+        </div>
+    </div>
+<% } %>
 <% } %>
 
 <% if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7) { %>
@@ -183,8 +273,10 @@
                                 <li class="list-group-item">
                                     <% if (al.usite === 0 && al.status === 2) { %>
                                     <span class="pull-right">重新上报中</span>
-                                    <% } else if (al.usite === 0 && al.status === 3) { %>
+                                    <% } else if (al.usite === 0 && al.status === 3 && a.times === 1) { %>
                                     <span class="text-success pull-right">上报</span>
+                                    <% } else if (al.usite === 0 && al.status === 3 && a.times !== 1) { %>
+                                    <span class="text-success pull-right">重新上报</span>
                                     <% } else if (al.usite !== 0 && al.status === 2) { %>
                                     <span class="pull-right">审批中</span>
                                     <% } else if (al.usite !== 0 && al.status === 3) { %>
@@ -210,9 +302,12 @@
                                         <% } %>
                                         <%= al.name %>&nbsp;<small class="text-muted"><%= al.jobs %></small>
                                     </h5>
-                                    <% if (al.sin_time !== null || (al.sdesc !== '' && al.sdesc !== null)) { %>
-                                        <p class="card-text"><%= al.sdesc %>&nbsp;<%= moment(al.sin_time).format('YYYY-MM-DD') %></p>
-                                    <% } %>
+                                        <% if (al.sdesc !== '' && al.sdesc !== null) { %>
+                                            <p class="card-text mb-1"><%= al.sdesc %></p>
+                                        <% } %>
+                                        <% if (al.sin_time !== null) { %>
+                                            <p class="card-text"><small class="text-muted"><%= moment(al.sin_time).format('YYYY-MM-DD') %></small></p>
+                                        <% } %>
                                 </li>
                                 <% } %>
                             </ul>
@@ -243,8 +338,10 @@
                         <ul class="list-group list-group-flush">
                             <% for (const [index,a] of auditList.entries()) { %>
                             <li class="list-group-item">
-                                <% if (a.status === 3 && a.usort === 0) { %>
+                                <% if (a.status === 3 && a.usort === 0 && a.times === 1) { %>
                                 <span class="text-success pull-right">上报</span>
+                                <% } else if (a.status === 3 && a.usort === 0 && a.times !== 1) { %>
+                                <span class="text-success pull-right">重新上报</span>
                                 <% } else if (a.status === 3 && a.usort !== 0) { %>
                                 <span class="text-success pull-right">审批通过</span>
                                 <% } else if (a.status === 2) { %>
@@ -309,8 +406,10 @@
                         <ul class="list-group list-group-flush">
                             <% for (const [index,a] of auditList.entries()) { %>
                                 <li class="list-group-item">
-                                    <% if (a.status === 3 && a.usort === 0) { %>
+                                    <% if (a.status === 3 && a.usort === 0 && a.times === 1) { %>
                                         <span class="text-success pull-right">上报</span>
+                                    <% } else if (a.status === 3 && a.usort === 0 && a.times !== 1) { %>
+                                        <span class="text-success pull-right">重新上报</span>
                                     <% } else if (a.status === 3 && a.usort !== 0) { %>
                                         <span class="text-success pull-right">审批通过</span>
                                     <% } else if (a.status === 2) { %>

+ 3 - 0
app/view/change/modal.ejs

@@ -1,3 +1,4 @@
+<% if (tender.user_id === uid) { %>
 <!--首次使用-->
 <div class="modal" id="first">
     <div class="modal-dialog" role="document" >
@@ -171,6 +172,7 @@
         </div>
     </div>
 </div>
+<% } %>
 <script>
     const ruleType = <%- ruleType %>;
     const ruleConst = JSON.parse('<%- JSON.stringify(ruleConst) %>');
@@ -178,3 +180,4 @@
     let connectorRule = '<%- tender.c_connector %>';
 </script>
 <script src="/public/js/moment/moment.min.js"></script>
+

+ 3 - 3
app/view/layout/menu.ejs

@@ -4,7 +4,7 @@
         <ul class="nav nav-pills nav-stacked bg-nav">
             <% for (const index in ctx.menuList) { %>
             <% if (ctx.menuList[index].display === undefined || !ctx.menuList[index].display) { continue } %>
-            <li <% if(ctx.controllerName === index) { %>class="active"<% } %>>
+            <li <% if(ctx.controllerName === index || (ctx.controllerName === 'list' && index === 'tender')) { %>class="active"<% } %>>
                 <a href="<%- ctx.menuList[index].url %>" data-toggle="tooltip" data-placement="right" title="" data-original-title="<%- ctx.menuList[index].name %>">
                     <i class="fa <%- ctx.menuList[index].icon %>"></i>
                     <% if (ctx.menuList[index].caption) { %>
@@ -17,7 +17,7 @@
     </div>
     <div class="nav-bottom mt-auto">
         <ul class="nav nav-pills nav-stacked bg-nav">
-            <li><a href="/setting/info" data-toggle="tooltip" data-placement="right" title="" data-original-title="项目设置"><i class="fa fa-cogs"></i><span>项目设置</span></a></li>
+            <li <% if (ctx.controllerName === 'setting') { %>class="active"<% } %>><a href="/setting/info" data-toggle="tooltip" data-placement="right" title="" data-original-title="项目信息"><i class="fa fa-cogs"></i><span>项目信息</span></a></li>
         </ul>
         <div class="dropright mb-1 ml-1">
             <a href="" class="btn btn-sm btn-light" data-toggle="dropdown" aria-haspopup="false" aria-expanded="false">
@@ -32,4 +32,4 @@
             </div>
         </div>
     </div>
-</div>
+</div>

+ 1 - 1
app/view/layout/sub_menu.ejs

@@ -23,4 +23,4 @@
         </div>
         <% } %>
     </div>
-</div>
+</div>

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

@@ -112,7 +112,7 @@
                                         <li class="list-group-item">
                                             <span class="text-success pull-right"><% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
                                             <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                            <p class="card-text"><%- ah[iA].begin_time.toLocaleDateString() %></p>
+                                            <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
                                         </li>
                                         <li class="list-group-item">
                                             <% if (ah[iA].status !== auditConst.status.uncheck) { %>
@@ -120,7 +120,8 @@
                                             <% } %>
                                             <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
                                             <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                            <p class="card-text"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。<%- ah[iA].end_time.toLocaleDateString() %></p>
+                                            <p class="card-text mb-1"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。</p>
+                                            <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
                                             <% } %>
                                         </li>
                                     <% } else if (iA === ah.length - 1) { %>
@@ -130,7 +131,8 @@
                                             <% } %>
                                             <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
                                             <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                            <p class="card-text"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。<%- ah[iA].end_time.toLocaleDateString() %></p>
+                                            <p class="card-text mb-1"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。</p>
+                                            <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
                                             <% } %>
                                         </li>
                                     <% } else { %>
@@ -140,7 +142,8 @@
                                             <% } %>
                                             <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
                                             <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                            <p class="card-text"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。<%- ah[iA].end_time.toLocaleDateString() %></p>
+                                            <p class="card-text mb-1"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。</p>
+                                            <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
                                             <% } %>
                                         </li>
                                     <% } %>
@@ -156,7 +159,7 @@
                                     <li class="list-group-item">
                                         <span class="text-success pull-right"><% if (tender.ledger_times > 1) { %>重新<% } %>上报</span>
                                         <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                        <p class="card-text"><%- auditors[iA].begin_time.toLocaleDateString() %></p>
+                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].begin_time.toLocaleDateString() %></small></p>
                                     </li>
                                     <li class="list-group-item">
                                         <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
@@ -164,7 +167,8 @@
                                         <% } %>
                                         <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
                                         <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                        <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。<%- auditors[iA].end_time.toLocaleDateString() %></p>
+                                        <p class="card-text mb-1"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。</p>
+                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
                                         <% } %>
                                     </li>
                                     <% } else if (iA === auditors.length - 1) { %>
@@ -174,7 +178,8 @@
                                         <% } %>
                                         <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
                                         <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                        <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。<%- auditors[iA].end_time.toLocaleDateString() %></p>
+                                        <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。</p>
+                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
                                         <% } %>
                                     </li>
                                     <% } else { %>
@@ -184,7 +189,8 @@
                                         <% } %>
                                         <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
                                         <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                        <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。<%- auditors[iA].end_time.toLocaleDateString() %></p>
+                                        <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。</p>
+                                        <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
                                         <% } %>
                                     </li>
                                     <% } %>
@@ -201,4 +207,4 @@
         </div>
     </div>
 </div>
-<% } %>
+<% } %>

+ 19 - 10
app/view/ledger/explode_modal.ejs

@@ -153,7 +153,10 @@
                             <span class="<%- auditConst.statusClass[auditors[i].status] %> pull-right"><%- auditConst.statusString[auditors[i].status] %></span>
                             <% } %>
                             <h5 class="card-title"><%- auditors[i].audit_order %> <%- auditors[i].name %> <small class="text-muted"><%- auditors[i].role %></small></h5>
-                            <p class="card-text"><%- auditors[i].opinion %> <%- auditors[i].end_time ? auditors[i].end_time.toLocaleString() : '' %></p>
+                            <p class="card-text mb-1"><%- auditors[i].opinion %></p>
+                            <% if (auditors[i].end_time) { %>
+                            <p class="card-text"><small class="text-muted"><%- auditors[i].end_time.toLocaleString() %></small></p>
+                            <% } %>
                         </li>
                         <% } %>
                     </ul>
@@ -205,7 +208,7 @@
                                 <li class="list-group-item">
                                     <span class="text-success pull-right"><% if (auditHistory.indexOf(ah) > 0) { %>重新<% } %>上报</span>
                                     <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                    <p class="card-text"><%- ah[iA].begin_time.toLocaleDateString() %></p>
+                                    <p class="card-text"><small class="text-muted"><%- ah[iA].begin_time.toLocaleDateString() %></small></p>
                                 </li>
                                 <li class="list-group-item">
                                     <% if (ah[iA].status !== auditConst.status.uncheck) { %>
@@ -213,7 +216,8 @@
                                     <% } %>
                                     <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
                                     <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。<%- ah[iA].end_time.toLocaleDateString() %></p>
+                                    <p class="card-text mb-1"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。</p>
+                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
                                     <% } %>
                                 </li>
                                 <% } else if (iA === ah.length - 1) { %>
@@ -223,7 +227,8 @@
                                     <% } %>
                                     <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
                                     <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。<%- ah[iA].end_time.toLocaleDateString() %></p>
+                                    <p class="card-text mb-1"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。</p>
+                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
                                     <% } %>
                                 </li>
                                 <% } else { %>
@@ -233,7 +238,8 @@
                                     <% } %>
                                     <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[ah[iA].status] %>"></i> <%- ah[iA].name %> <small class="text-muted"><%- ah[iA].role %></small></h5>
                                     <% if (ah[iA].status === auditConst.status.checked || ah[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。<%- ah[iA].end_time.toLocaleDateString() %></p>
+                                    <p class="card-text mb-1"><%- auditConst.statusString[ah[iA].status]%>,<%- ah[iA].opinion %>。</p>
+                                    <p class="card-text"><small class="text-muted"><%- ah[iA].end_time.toLocaleDateString() %></small></p>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -249,7 +255,7 @@
                                 <li class="list-group-item">
                                     <span class="text-success pull-right"><% if (tender.ledger_times > 1) { %>重新<% } %>上报</span>
                                     <h5 class="card-title"><i class="fa fa-play-circle fa-rotate-90 text-success"></i> <%- user.name %> <small class="text-muted"><%- user.role %></small></h5>
-                                    <p class="card-text"><%- auditors[iA].begin_time.toLocaleDateString() %></p>
+                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].begin_time.toLocaleDateString() %></small></p>
                                 </li>
                                 <li class="list-group-item">
                                     <% if (auditors[iA].status !== auditConst.status.uncheck) { %>
@@ -257,7 +263,8 @@
                                     <% } %>
                                     <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
                                     <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。<%- auditors[iA].end_time.toLocaleDateString() %></p>
+                                    <p class="card-text mb-1"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。</p>
+                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
                                     <% } %>
                                 </li>
                                 <% } else if (iA === auditors.length - 1) { %>
@@ -267,7 +274,8 @@
                                     <% } %>
                                     <h5 class="card-title"><i class="fa fa-stop-circle <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
                                     <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。<%- auditors[iA].end_time.toLocaleDateString() %></p>
+                                    <p class="card-text mb-1"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。</p>
+                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
                                     <% } %>
                                 </li>
                                 <% } else { %>
@@ -277,7 +285,8 @@
                                     <% } %>
                                     <h5 class="card-title"><i class="fa fa-chevron-circle-down <%- auditConst.statusClass[auditors[iA].status] %>"></i> <%- auditors[iA].name %> <small class="text-muted"><%- auditors[iA].role %></small></h5>
                                     <% if (auditors[iA].status === auditConst.status.checked || auditors[iA].status === auditConst.status.checkNo) { %>
-                                    <p class="card-text"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。<%- auditors[iA].end_time.toLocaleDateString() %></p>
+                                    <p class="card-text mb-1"><%- auditConst.statusString[auditors[iA].status]%>,<%- auditors[iA].opinion %>。</p>
+                                    <p class="card-text"><small class="text-muted"><%- auditors[iA].end_time.toLocaleDateString() %></small></p>
                                     <% } %>
                                 </li>
                                 <% } %>
@@ -294,4 +303,4 @@
         </div>
     </div>
 </div>
-<% } %>
+<% } %>

+ 7 - 5
app/view/setting/info.ejs

@@ -3,7 +3,7 @@
     <div class="panel-title">
         <div class="title-main">
             <h2>项目信息
-                <a href="#" class="btn btn-primary btn-sm pull-right" onclick="updateinfo()">保存修改</a>
+                <% if (projectData.user_account === ctx.session.sessionUser.account) { %><a href="#" class="btn btn-primary btn-sm pull-right" onclick="updateinfo()">保存修改</a><% } %>
             </h2>
         </div>
     </div>
@@ -11,14 +11,14 @@
         <div class="c-body">
             <div class="row">
                 <div class="col-5">
-                    <form id="info-form" action="/<%= ctx.controllerName %>/updateinfo/<%= projectData.id === undefined ? 0 : projectData.id %>?_csrf=<%= ctx.csrf %>" method="post">
+                    <% if (projectData.user_account === ctx.session.sessionUser.account) { %><form id="info-form" action="/<%= ctx.controllerName %>/updateinfo/<%= projectData.id === undefined ? 0 : projectData.id %>?_csrf=<%= ctx.csrf %>" method="post"><% } %>
                         <div class="form-group">
                             <label>项目编号</label>
                             <input class="form-control" value="<%= projectData.code%>" type="text" readonly>
                         </div>
                         <div class="form-group">
                             <label>项目名称</label>
-                            <input class="form-control" name="name" id="name" placeholder="请输入项目名称" value="<%= projectData.name%>" type="text">
+                            <input class="form-control" value="<%= projectData.name%>" type="text" <% if (projectData.user_account !== ctx.session.sessionUser.account) { %>readonly<% } else { %>name="name" id="name" placeholder="请输入项目名称"<% } %>>
                         </div>
                         <div class="form-group">
                             <label>管理员</label>
@@ -42,15 +42,17 @@
                             <label>创建时间</label>
                             <input class="form-control" value=<%= dateStr%> type="text" readonly>
                         </div>
-                    </form>
+                        <% if (projectData.user_account === ctx.session.sessionUser.account) { %></form><% } %>
                 </div>
             </div>
         </div>
     </div>
 </div>
+<% if (projectData.user_account === ctx.session.sessionUser.account) { %>
 <script type="text/javascript">
     function updateinfo()
     {
         $("#info-form").submit();
     }
-</script>
+</script>
+<% } %>

+ 10 - 2
app/view/setting/sub_menu.ejs

@@ -1,12 +1,13 @@
 <div class="panel-sidebar">
     <div class="panel-title">
         <div class="title-bar">
-            <h2>项目设置</h2>
+            <h2>项目信息</h2>
         </div>
     </div>
     <div class="scrollbar-auto">
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
+                <% if (projectData.user_account === ctx.session.sessionUser.account) { %>
                 <% for (const index in ctx.subMenu) { %>
                 <li <% if (ctx.url === ctx.subMenu[index].url) { %>class="active"<% } %>>
                     <a href="<%- ctx.subMenu[index].url %>">
@@ -14,7 +15,14 @@
                     </a>
                 </li>
                 <% } %>
+                <% } else { %>
+                <li <% if (ctx.url === ctx.subMenu.info.url) { %>class="active"<% } %>>
+                    <a href="<%- ctx.subMenu.info.url %>">
+                        <span><%- ctx.subMenu.info.caption %></span>
+                    </a>
+                </li>
+                <% } %>
             </ul>
         </div>
     </div>
-</div>
+</div>

+ 41 - 52
app/view/setting/user.ejs

@@ -3,7 +3,11 @@
     <div class="panel-title">
         <div class="title-main">
             <h2>账号管理
+                <% if (projectData.max_user !== accountData.length) { %>
                 <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
+                <% } else { %>
+                <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
+                <% } %>
             </h2>
         </div>
     </div>
@@ -27,46 +31,25 @@
                             <th class="text-center">操作</th></tr>
                         </thead>
                         <tbody>
-                        <tr>
-                            <td>chente</td>
-                            <td>陈特</td>
-                            <td>珠海纵横创新软件有限公司</td>
-                            <td>产品经理</td>
-                            <td>15812644017</td>
-                            <td>0765-3850891</td>
-                            <td class="text-center"><a href="#edit-user" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
-                                <a href="" class="btn btn-sm btn-outline-danger">停用</a></td>
-                        </tr>
-                        <tr class="table-danger">
-                            <td>chente2</td>
-                            <td>陈特2</td>
-                            <td>珠海纵横创新软件有限公司</td>
-                            <td>产品经理</td>
-                            <td>15812644017</td>
-                            <td>0765-3850891</td>
-                            <td class="text-center"><a href="#edit-user" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
-                                <a href="" class="btn btn-sm btn-outline-success">启用</a></td>
-                        </tr>
-                        <tr>
-                            <td>chente3</td>
-                            <td>陈特3</td>
-                            <td>珠海纵横创新软件有限公司</td>
-                            <td>产品经理</td>
-                            <td>15812644017</td>
-                            <td>0765-3850891</td>
-                            <td class="text-center"><a href="#edit-user" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
-                                <a href="" class="btn btn-sm btn-outline-danger">停用</a></td>
-                        </tr>
-                        <tr>
-                            <td>chente4</td>
-                            <td>陈特4</td>
-                            <td>珠海纵横创新软件有限公司</td>
-                            <td>产品经理</td>
-                            <td>15812644017</td>
-                            <td>0765-3850891</td>
-                            <td class="text-center"><a href="#edit-user" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
-                                <a href="" class="btn btn-sm btn-outline-danger">停用</a></td>
+                        <% for (const account of accountData) { %>
+                        <tr <% if (account.enable !== 1) { %> class="table-danger"<% } %>>
+                            <td><%= account.account %><% if (account.is_admin === 1) { %> <span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="管理员"><i class="fa fa-user-circle-o"></i></span><% } %></td>
+                            <td><%= account.name %></td>
+                            <td><%= account.company %></td>
+                            <td><%= account.role %></td>
+                            <td><%= account.mobile %></td>
+                            <td><%= account.telephone %></td>
+                            <td class="text-center"><a href="#edit-user" data-account="<%= JSON.stringify(account) %>" data-toggle="modal" data-target="#edit-user" class="btn btn-sm btn-outline-primary">编辑</a>
+                                <% if (account.is_admin !== 1) { %>
+                                    <% if (account.enable !== 1) { %>
+                                        <a href="" class="btn btn-sm btn-outline-success account-switch-btn" data-account="<%= account.id %>">启用</a>
+                                    <% } else { %>
+                                        <a href="" class="btn btn-sm btn-outline-danger account-switch-btn" data-account="<%= account.id %>">停用</a>
+                                    <% } %>
+                                <% } %>
+                            </td>
                         </tr>
+                        <% } %>
                         </tbody>
                     </table>
                 </div>
@@ -78,27 +61,33 @@
                             <th>姓名</th>
                             <th>单位</th>
                             <th>职位</th>
+                            <th>协作办公</th>
                             <th>权限</th>
                         </thead>
                         <tbody>
+                        <% for (const account of accountData) { %>
                         <tr>
-                            <td>chente</td>
-                            <td>陈特</td>
-                            <td>珠海纵横创新软件有限公司</td>
-                            <td>产品经理</td>
-                            <td>标段管理(创建标段)<a href="#edit-user2" data-toggle="modal" data-target="#edit-user2" class="btn btn-sm">编辑</a></td>
-                        </tr>
-                        <tr>
-                            <td>chente</td>
-                            <td>陈特</td>
-                            <td>珠海纵横创新软件有限公司</td>
-                            <td>产品经理</td>
-                            <td><a href="#edit-user2" data-toggle="modal" data-target="#edit-user2" class="btn btn-sm">编辑</a></td>
+                            <td><%= account.account %><% if (account.is_admin === 1) { %> <span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="管理员"><i class="fa fa-user-circle-o"></i></span><% } %></td>
+                            <td><%= account.name %></td>
+                            <td><%= account.company %></td>
+                            <td><%= account.role %></td>
+                            <td><% if (account.cooperation === 1) { %>启用<% } %></td>
+                            <td><% if (account.permission !== '' && account.permission !== null && JSON.parse(account.permission).tender !== undefined) { %>
+                                <% const tenderPermission = JSON.parse(account.permission).tender; %>
+                                    <% for (const tc in permission.tender.children) { %>
+                                        <% if (tenderPermission.indexOf(permission.tender.children[tc].value.toString()) !== -1) { %>
+                                            <%= permission.tender.children[tc].title %>
+                                        <% } %>
+                                    <% } %>
+                                <% } %>
+                                    <a href="#edit-user2" data-account="<%= JSON.stringify(account) %>" data-toggle="modal" data-target="#edit-user2" class="btn btn-sm">编辑</a></td>
                         </tr>
+                        <% } %>
                         </tbody>
                     </table>
                 </div>
             </div>
         </div>
     </div>
-</div>
+</div>
+<script src="/public/js/setting.js"></script>

+ 108 - 75
app/view/setting/user_modal.ejs

@@ -5,36 +5,60 @@
             <div class="modal-header">
                 <h5 class="modal-title">添加账号</h5>
             </div>
+            <form method="post" action="/setting/user/add?_csrf=<%= ctx.csrf %>" onsubmit="return checkUserForm('add');">
             <div class="modal-body">
                 <div class="form-group">
+                    <label><b class="text-danger">*</b>账号组</label>
+                    <select class="form-control" name="account_group">
+                        <option value="0">请选择</option>
+                        <% for (const dw in accountGroup) { %>
+                        <option value="<%= dw %>"><%= accountGroup[dw] %></option>
+                        <% } %>
+                    </select>
+                </div>
+                <div class="form-group">
                     <label>登录账号<b class="text-danger">*</b></label>
-                    <input class="form-control"  placeholder="支持英文数字组合" type="text">
+                    <input class="form-control" name="account" placeholder="支持英文数字组合" type="text">
+                    <input value="" class="account-check" type="hidden">
+                    <div class="invalid-feedback">
+                        该账号已存在。
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>登录密码<b class="text-danger">*</b></label>
+                    <div class="input-group">
+                        <input type="text" name="password" class="form-control" placeholder="密码支持英文数字及符号">
+                        <div class="input-group-append">
+                            <button id="rand-password" class="btn btn-outline-secondary" type="button">随机密码</button>
+                        </div>
+                    </div>
                 </div>
                 <div class="form-group">
                     <label>姓名<b class="text-danger">*</b></label>
-                    <input class="form-control" value="" type="text">
+                    <input class="form-control" name="name" value="" type="text">
                 </div>
                 <div class="form-group">
-                    <label>单位名称</label>
-                    <input class="form-control" value="" type="text">
+                    <label>单位名称<b class="text-danger">*</b></label>
+                    <input class="form-control" name="company" value="" type="text">
                 </div>
                 <div class="form-group">
-                    <label>职位名称</label>
-                    <input class="form-control" value="" type="text">
+                    <label>职位名称<b class="text-danger">*</b></label>
+                    <input class="form-control" name="role" value="" type="text">
                 </div>
                 <div class="form-group">
-                    <label>手机</label>
-                    <input class="form-control" value="" type="">
+                    <label>手机<b class="text-danger">*</b></label>
+                    <input class="form-control" name="mobile" value="" type="number">
                 </div>
                 <div class="form-group">
                     <label>电话</label>
-                    <input class="form-control" placeholder="格式000-0000000" type="">
+                    <input class="form-control" name="telephone" placeholder="格式000-0000000" type="text">
                 </div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">确定添加</button>
+                <button type="submit" class="btn btn-primary">确定添加</button>
             </div>
+            </form>
         </div>
     </div>
 </div>
@@ -45,38 +69,64 @@
             <div class="modal-header">
                 <h5 class="modal-title">编辑账号</h5>
             </div>
+            <form method="post" action="/setting/user/update?_csrf=<%= ctx.csrf %>" onsubmit="return checkUserForm('update');">
             <div class="modal-body">
                 <div class="form-group">
-                    <label>登录账号</label>
-                    <input class="form-control" value="chente"  placeholder="支持英文数字组合" type="text">
+                    <label>账号组<b class="text-danger">*</b></label>
+                    <select class="form-control" name="account_group">
+                        <option value="0">请选择</option>
+                        <% for (const dw in accountGroup) { %>
+                            <option value="<%= dw %>"><%= accountGroup[dw] %></option>
+                        <% } %>
+                    </select>
+                </div>
+                <div class="form-group">
+                    <label>登录账号<b class="text-danger">*</b></label>
+                    <input class="form-control" value="" name="account" placeholder="支持英文数字组合" type="text">
+                    <input value="" class="account-check" type="hidden">
+                    <div class="invalid-feedback">
+                        该账号已存在。
+                    </div>
+                </div>
+                <div class="form-group">
+                    <label>登录密码</label>
+                    <div class="input-group">
+                        <input type="text" id="reset-password" class="form-control" placeholder="密码支持英文数字及符号">
+                        <div class="input-group-append">
+                            <button id="reset-password-btn" class="btn btn-outline-secondary" type="button">修改密码</button>
+                        </div>
+                    </div>
+                    <span class="form-text text-success">如果账号已有认证手机,密码也将发送至该手机。</span>
                 </div>
                 <div class="form-group">
-                    <label>姓名</label>
-                    <input class="form-control" value="陈特" type="text">
+                    <label>姓名<b class="text-danger">*</b></label>
+                    <input class="form-control" value="" name="name" type="text">
                     <small class="form-text text-muted">修改姓名,将影响所有该账号参与数据</small>
                 </div>
                 <div class="form-group">
-                    <label>单位名称</label>
-                    <input class="form-control" value="珠海纵横创新软件有限公司" type="text">
+                    <label>单位名称<b class="text-danger">*</b></label>
+                    <input class="form-control" value="" name="company" type="text">
                 </div>
                 <div class="form-group">
-                    <label>职位名称</label>
-                    <input class="form-control" value="产品经理" type="text">
+                    <label>职位名称<b class="text-danger">*</b></label>
+                    <input class="form-control" value="" name="role" type="text">
                 </div>
                 <div class="form-group">
-                    <label>手机</label>
-                    <input class="form-control" value="1812644017" type="">
+                    <label>手机<b class="text-danger">*</b></label>
+                    <input class="form-control" value="" name="mobile" type="number">
                 </div>
                 <div class="form-group">
                     <label>电话</label>
-                    <input class="form-control" value="0756-3850891" placeholder="格式000-0000000" type="">
+                    <input class="form-control" value="" name="telephone" placeholder="格式000-0000000" type="text">
                 </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-outline-danger" data-dismiss="modal">删除账号</button>
+                <input type="hidden" name="id" id="user-id" value="">
+                <!--<button type="button" class="btn btn-outline-danger" data-dismiss="modal">删除账号</button>-->
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">提交修改</button>
+                <button type="submit" class="btn btn-primary">提交修改</button>
             </div>
+            </form>
         </div>
     </div>
 </div>
@@ -87,69 +137,52 @@
             <div class="modal-header">
                 <h5 class="modal-title">编辑权限</h5>
             </div>
+            <form method="post" action="/setting/user/permission?_csrf=<%= ctx.csrf %>">
             <div class="modal-body">
+                <% for (const pm in permission) { %>
                 <div class="form-group">
-                    <label><i class="fa fa-list-ul"></i> 标段管理</label>
-                    <div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox1">创建标段</label>
-                        </div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox2" value="option2">
-                            <label class="form-check-label" for="inlineCheckbox2">查看项目下所有标段</label>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group">
-                    <label><i class="fa fa-list-alt"></i> 0号台帐</label>
-                    <div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox4" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox4">编制台帐</label>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group">
-                    <label><i class="fa fa-list-alt"></i> 计量台帐(台帐管理)</label>
+                    <label><i <% if (permission[pm].class !== '') { %>class="<%= permission[pm].class %>"<% } %>></i> <%= permission[pm].title %></label>
                     <div>
+                        <% for (const ip of permission[pm].children) { %>
                         <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox8" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox8">查看</label>
+                            <input class="form-check-input" type="<%= permission[pm].type %>" id="<%= pm %>_<%= ip.value %>" name="<%= pm %><% if (permission[pm].type === 'checkbox') { %>[]<% } %>" value="<%= ip.value %>">
+                            <label class="form-check-label" for="<%= pm %>_<%= ip.value %>"><%= ip.title %></label>
                         </div>
+                        <% } %>
                     </div>
                 </div>
-                <div class="form-group">
-                    <label><i class="fa fa-calendar-check-o"></i> 计量台帐</label>
-                    <div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox9" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox9">编制计量台帐</label>
-                        </div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox11" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox11">查阅标段下所有中间计量</label>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group">
-                    <label><i class="fa fa-calendar-check-o"></i> 变更令</label>
-                    <div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox12" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox12">编制期计量</label>
-                        </div>
-                        <div class="form-check form-check-inline">
-                            <input class="form-check-input" type="checkbox" id="inlineCheckbox14" value="option1">
-                            <label class="form-check-label" for="inlineCheckbox14">查阅标段下所有期计量</label>
-                        </div>
-                    </div>
+                <% } %>
+                <!--需要勾选  创建标段 ,协作办公才能勾选-->
+                <div class="alert alert-secondary">
+                    “创建标段”用户默认具有标段下“创建标段”“台帐分解”“创建台帐修订”“创建计量期”“创建工程变更”的权限,如标段创建者需要把以上权限分配给其他用户,可启用 用户设置协作办公 。
                 </div>
             </div>
             <div class="modal-footer">
+                <input type="hidden" name="id" value="">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-primary">提交修改</button>
+            </div>
+            </form>
+        </div>
+    </div>
+</div>
+<!--弹出账号受限-->
+<div class="modal" tabindex="-1" role="dialog" id="add-unpass">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">无法添加账号</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <p>账号已超过最大账号数,无法添加新账号。</p>
+                <p>当前限制账号总数:<b><%= projectData.max_user %></b></p>
+            </div>
+            <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                <button type="button" class="btn btn-primary">提交修改</button>
             </div>
         </div>
     </div>
-</div>
+</div>

+ 23 - 0
app/view/tender/cooperation.ejs

@@ -0,0 +1,23 @@
+<% include ./tender_sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main  d-flex justify-content-between">
+            <h2>设置协作办公</h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <% for (const tp of tenderPermissionList) { %>
+            <div class="form-group">
+                <label><%= tp %></label>
+                <div class="form-group form-check">
+                    <h5 class="d-inline-block"><span class="badge badge-secondary"><%= user.name %>-<%= user.role %></span></h5>
+                    <h5 class="d-inline-block"><span class="badge badge-secondary">王五-监理 <a href="#" class="btn-danger px-1" title="移除"><i class="fa fa-remove"></i></a></span> </h5>
+                    <a href="#add" data-toggle="modal" data-target="#add" class="ml-3">添加协作人</a>
+                </div>
+            </div>
+            <% } %>
+        </div>
+    </div>
+</div>
+<script type="text/javascript" src="/public/js/tender.js"></script>

+ 34 - 0
app/view/tender/cooperationModal.ejs

@@ -0,0 +1,34 @@
+<!--上报审批-->
+<div class="modal fade" id="add" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">添加协作人</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>搜索</label>
+                    <div class="input-group">
+                        <input class="form-control" placeholder="请输入姓名进行检索" type="text">
+                        <div class="input-group-append">
+                            <button class="btn btn-outline-secondary" type="button"><i class="fa fa-search"></i></button>
+                        </div>
+                    </div>
+                </div>
+                <div class="card border-primary">
+                    <div class="card-body">
+                        <h5 class="card-title">
+                            <a href="#" class="btn btn-primary btn-sm pull-right">添加</a>张三
+                        </h5>
+                        <h6 class="card-subtitle mb-2 text-muted">监理</h6>
+                        <p class="card-text">XXXXX公司</p>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary">确认上报</button>
+            </div>
+        </div>
+    </div>
+</div>

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

@@ -3,9 +3,11 @@
     <div class="panel-title">
         <div class="title-main  d-flex justify-content-between">
             <h2>进行至 第7期<small class="text-warning">(审批中)</small></h2>
+            <% if (cooperation) { %>
             <div>
-                <a href="biaoduan-xiezuo.html" class="btn btn-sm btn-light" ><i class="fa fa-users"></i> 协作办公</a>
+                <a href="/tender/<%= tender.id %>/cooperation" class="btn btn-sm btn-light" ><i class="fa fa-users"></i> 协作办公</a>
             </div>
+            <% } %>
         </div>
     </div>
     <div class="content-wrap">
@@ -810,4 +812,4 @@
 <script>
     let property = JSON.parse('<%- JSON.stringify(tenderInfo) %>');
 </script>
-<script type="text/javascript" src="/public/js/tender.js"></script>
+<script type="text/javascript" src="/public/js/tender.js"></script>

+ 3 - 1
app/view/tender/sub_menu.ejs

@@ -23,8 +23,10 @@
                 </div>
             </div>
         </div>
+        <% if (userPermission !== null && userPermission.tender !== undefined && userPermission.tender.indexOf('1') !== -1) { %>
         <div>
             <a href="#add-bd" data-toggle="modal" data-target="#add-bd" class="btn btn-sm btn-primary pull-right">新建标段</a>
         </div>
+        <% } %>
     </div>
-</div>
+</div>

+ 1 - 1
config/menu.js

@@ -31,7 +31,7 @@ const menu = {
         display: true,
         url: '/sum',
         children: null,
-        caption: '',
+        caption: '总分包',
     },
 };