瀏覽代碼

账号设置,账号列表

MaiXinRong 3 月之前
父節點
當前提交
ebfa9c9d78

+ 39 - 19
app/controller/sub_proj_setting_controller.js

@@ -217,50 +217,70 @@ module.exports = app => {
         async user(ctx) {
             try {
                 this.defaultCheck(ctx);
-                const accountList = await ctx.service.projectAccount.getAllDataByCondition({
-                    columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile', 'company_id'],
-                    where: { project_id: ctx.subProject.project_id },
-                });
                 const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
-                const accountGroup = unitList.map(item => {
-                    const groupList = accountList.filter(item1 => item1.company === item.name);
-                    return { groupName: item.name, groupList };
-                }).filter(x => { return x.groupList.length > 0; });
-
                 const filter = {
                     company: ctx.query.company || '',
                     keyword: ctx.query.keyword || '',
                 };
                 const total = await ctx.service.projectAccount.getSubProjectAccountCount(ctx.subProject, filter);
                 const subProjectAccountList = await ctx.service.projectAccount.getSubProjectAccountListWithPermission(ctx.subProject, filter);
-                const page = ctx.page;
-                const pageSize = ctx.pageSize;
-                // 过滤数据
-                ctx.service.projectAccount.searchFilter(ctx.request.query, projectId);
+                const subProjectAllAccountList = filter.company || filter.keyword ? await ctx.service.projectAccount.getSubProjectAccountListWithPermission(ctx.subProject) : subProjectAccountList;
+                const subProjectUnitList = unitList.map(item => {
+                    const users = subProjectAllAccountList.filter(item1 => item1.company === item.name);
+                    return { name: item.name, users };
+                }).filter(x => { return x.users.length > 0; });
                 const pageInfo = {
-                    page,
+                    page: ctx.page,
                     pageSizeSelect: 1,
-                    pageSize,
+                    pageSize: ctx.pageSize,
                     total_num: total,
-                    total: Math.ceil(total / pageSize),
+                    total: Math.ceil(total / ctx.pageSize),
                     queryData: JSON.stringify(ctx.urlInfo.query),
                 };
+
+                const accountList = await ctx.service.projectAccount.getAllDataByCondition({
+                    columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile', 'company_id'],
+                    where: { project_id: ctx.subProject.project_id },
+                });
+                accountList.forEach(x => {
+                    x.sp_exist = subProjectAllAccountList.findIndex(y => { return y.id === x.id; }) >= 0;
+                });
+                const accountGroup = unitList.map(item => {
+                    const groupList = accountList.filter(item1 => item1.company === item.name);
+                    return { id: item.id, name: item.name, groupList };
+                }).filter(x => { return x.groupList.length > 0; });
                 const renderData = {
                     pageInfo,
-                    accountList,
                     accountGroup,
                     subProjectAccountList,
+                    subProjectUnitList,
                     keyword: filter.keyword,
                     company: filter.company,
-                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.setting.user),
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.setting.sp_permission),
+                    permissionBlock: ctx.service.subProjPermission.PermissionBlock,
                 };
-                await this.layout('sp_setting/user.ejs', renderData);
+                await this.layout('sp_setting/user.ejs', renderData, 'sp_setting/user_modal.ejs');
             } catch (error) {
                 console.log(error);
                 ctx.redirect(`/sp/${ctx.subProject.id}/dashboard`);
             }
         }
 
+        async permission(ctx) {
+
+        }
+
+        async permissionUpdate(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const result = await ctx.service.subProjPermission.updatePermission(ctx.subProject, data);
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (err) {
+                ctx.log(err);
+                ctx.ajaxErrorBody(err, '更新账号权限失败');
+            }
+        }
+
         async logs(ctx) {
             try {
                 this.defaultCheck(ctx);

+ 93 - 0
app/public/js/sp_setting_permission.js

@@ -0,0 +1,93 @@
+$(document).ready(() => {
+    autoFlashHeight();
+    // 选择账号
+    const refreshUnitUsersHtml = function () {
+        const select = $('#sel-batch-unit').val();
+        const selectGroup = accountGroup.find(x => { return x.name === select; });
+        const html = [];
+        if (selectGroup) {
+            for (const u of selectGroup.groupList) {
+                html.push(`<tr class="text-center">`);
+                html.push(`<td><input type="checkbox" name="sel-batch-check" id="${u.id}" unit="${selectGroup.name}" ${(u.select ? 'checked' : '')} ${u.sp_exist ? 'disabled' : ''}></td>`);
+                html.push(`<td>${u.name}</td>`);
+                html.push(`<td>${u.role}</td>`);
+                html.push('<tr>');
+            }
+        }
+        $('#sel-batch-users').html(html.join(''));
+    };
+    $('#sel-batch').on('show.bs.modal', function() {
+        accountGroup.forEach(ag => {
+            ag.groupList.forEach(u => { u.select = false; });
+        });
+        refreshUnitUsersHtml();
+    });
+    $('#sel-batch-unit').change(function() {
+        refreshUnitUsersHtml();
+    });
+    $('body').on('click', '[name=sel-batch-check]', function() {
+        const select = $('#sel-batch-unit').val();
+        const selectGroup = accountGroup.find(x => { return x.name === select; });
+        const user = selectGroup.groupList.find(x => { return x.id === parseInt(this.getAttribute('id')); });
+        user.select = this.checked;
+    });
+    $('#sel-batch-all').change(function() {
+        const select = $('#sel-batch-unit').val();
+        const selectGroup = accountGroup.find(x => { return x.name === select; });
+        selectGroup.groupList.forEach(x => {
+            x.select = x.sp_exist ? false : this.checked;
+        });
+        refreshUnitUsersHtml();
+    });
+    $('#sel-batch-ok').click(() => {
+        const select = [];
+        for (const ag of accountGroup) {
+            for (const u of ag.groupList) {
+                if (u.select && !u.sp_exist) select.push(u.id);
+            }
+        }
+        postData(`user/permission/update`, { add: select }, function() {
+            window.location.reload();
+        });
+    });
+    // 移除账号
+    $('[name=remove-user]').click(function() {
+        const id = this.getAttribute('data-id');
+        postData(`user/permission/update`, { del: id }, function() {
+            window.location.reload();
+        });
+    });
+    $('[name=set-permission]').click(function() {
+        const data = JSON.parse(this.getAttribute('data-account'));
+        const permissionCheck = $('[name="permission-check"]');
+        for (const pc of permissionCheck) {
+            const ptype = pc.getAttribute('ptype');
+            const pvalue = pc.getAttribute('pvalue');
+            const typePermission = (data[ptype + '_permission'] || '').split(',');
+            pc.checked = typePermission.indexOf(pvalue) >= 0;
+        }
+        $('#permission-uid').val(data.permission_id);
+        $('#permission').modal('show');
+    });
+    $('#permission-ok').click(function() {
+        const data = { id: $('#permission-uid').val() };
+        const updatePermission = [];
+        const permissionCheck = $('[name="permission-check"]');
+        for (const pc of permissionCheck) {
+            const ptype = pc.getAttribute('ptype');
+            const pvalue = pc.getAttribute('pvalue');
+            let up = updatePermission.find(x => { return x.key === ptype; });
+            if (!up) {
+                up = { key: ptype, value: [] };
+                updatePermission.push(up);
+            }
+            if (pc.checked) up.value.push(pvalue);
+        }
+        updatePermission.forEach(x => {
+            data[x.key + '_permission'] = x.value.join(',');
+        });
+        postData(`user/permission/update`, { update: data }, function() {
+            window.location.reload();
+        });
+    });
+});

+ 3 - 0
app/router.js

@@ -203,6 +203,9 @@ module.exports = app => {
     app.post('/sp/:id/setting/category/value', sessionAuth, subProjectCheck, 'subProjSettingController.setCategoryValue');
     app.post('/sp/:id/setting/category/level', sessionAuth, subProjectCheck, 'subProjSettingController.resetCategoryLevel');
     app.post('/sp/:id/setting/category/self-level', sessionAuth, subProjectCheck, 'subProjSettingController.selfCategoryLevel');
+    // 账号设置
+    app.get('/sp/:id/setting/user', sessionAuth, subProjectCheck, 'subProjSettingController.user');
+    app.post('/sp/:id/setting/user/permission/update', sessionAuth, subProjectCheck, 'subProjSettingController.permissionUpdate');
     // 操作日志
     app.get('/sp/:id/setting/logs', sessionAuth, subProjectCheck, 'subProjSettingController.logs');
     app.get('/sp/:id/setting/logs/type/:type', sessionAuth, subProjectCheck, 'subProjSettingController.logs');

+ 18 - 12
app/service/project_account.js

@@ -1045,30 +1045,36 @@ module.exports = app => {
             return await this.db.query(sql, [subProject.id]);
         }
 
-        _getFilterSql(filter, tableName) {
+        _getFilterSql(filter) {
             const rstFilter = [];
-            for (const prop in filter) {
-                if (!filter[prop]) continue;
-                rstFilter.push(this.db.format(`${tableName}.${prop} = ?`, [filter[prop]]));
+            for (const f of filter) {
+                for (const prop in f.filter) {
+                    if (!f.filter[prop]) continue;
+                    rstFilter.push(this.db.format(`${f.tableName}.${prop} = ?`, [f.filter[prop]]));
+                }
             }
             return rstFilter.join(' AND ');
         }
 
         async getSubProjectAccountCount(subProject, filter) {
-            filter.spid = subProject.id;
-            const filterSql = this._getFilterSql(filter, 'pa');
-            const sql = `SELECT count(pa.id) as count FROM FROM ${this.ctx.service.subProjPermission.tableName} spp LEFT JOIN ${this.tableName} pa ON spp.uid = pa.id WHERE ` + filterSql;
+            const filterInfo = [{ filter: {spid: subProject.id}, tableName: 'spp' }];
+            if (filter) filterInfo.push({ filter, tableName: 'pa'});
+            const filterSql = this._getFilterSql(filterInfo);
+            const sql = `SELECT count(pa.id) as count FROM ${this.ctx.service.subProjPermission.tableName} spp LEFT JOIN ${this.tableName} pa ON spp.uid = pa.id WHERE ` + filterSql;
             const result = await this.db.queryOne(sql);
             return result.count;
         }
 
         async getSubProjectAccountListWithPermission(subProject, filter) {
-            filter.spid = subProject.id;
-            const filterSql = this._getFilterSql(filter, 'pa');
+            const filterInfo = [{ filter: {spid: subProject.id}, tableName: 'spp' }];
+            if (filter) filterInfo.push({ filter, tableName: 'pa'});
+            const filterSql = this._getFilterSql(filterInfo);
             const limit = this.ctx.pageSize ? this.ctx.pageSize : this.app.config.pageSize;
-            const offset = this.sqlBuilder.limit * (this.ctx.page - 1);
-            const sql = `SELECT pa.*, spp.file_permission, budget_permission as count FROM FROM ${this.ctx.service.subProjPermission.tableName} spp LEFT JOIN ${this.tableName} pa ON spp.uid = pa.id WHERE ` + filterSql + ' ORDER BY pa.id ASC LIMIT ?, ?';
-            const result = await this.db.query(sql, [limit, offset]);
+            const offset = limit * (this.ctx.page - 1);
+            const sql = `SELECT pa.*, spp.id AS permission_id, 
+                    spp.file_permission, spp.budget_permission, spp.info_permission, spp.datacollect_permission, spp.fund_trans_permission, spp.fund_pay_permission, spp.contract_permission 
+                FROM ${this.ctx.service.subProjPermission.tableName} spp LEFT JOIN ${this.tableName} pa ON spp.uid = pa.id WHERE ` + filterSql + ' ORDER BY spp.create_time DESC LIMIT ?, ?';
+            const result = await this.db.query(sql, [offset, limit]);
             return result;
         }
     }

+ 107 - 1
app/service/sub_proj_permission.js

@@ -21,6 +21,10 @@ module.exports = app => {
         constructor(ctx) {
             super(ctx);
             this.tableName = 'sub_project_permission';
+            this._definePermission();
+        }
+
+        _definePermission() {
             this.PermissionConst = {
                 budget: {
                     view: { title: '查看', value: 1 },
@@ -34,8 +38,63 @@ module.exports = app => {
                 },
                 manage: {
                     rela: { title: '关联标段', value: 1 },
-                }
+                },
+                info: {
+                    view: { title: '查看', value: 1},
+                    edit: { title: '编辑', value: 2 },
+                },
+                datacollect: {
+                    view: { title: '查看', value: 1},
+                },
+                contract: {
+                    edit: { title: '编辑节点', value: 1 },
+                    add: { title: '添加合同', value: 2 },
+                    node: { title: '授权查看本节点合同', value: 3 },
+                    unit: { title: '授权查看本单位合同', value: 4 },
+
+                },
+                fund_trans: {
+                    view: { title: '查看', value: 1 },
+                    add: { title: '新建划拨', value: 2 },
+                    att: { title: '上传附件', value: 3 },
+                },
+                fund_pay: {
+                    view: { title: '查看', value: 1 },
+                    att: { title: '上传附件', value: 3 },
+                },
             };
+            this.PermissionBlock = [
+                { key: 'datacollect', name: '决策大屏', field: 'datacollect_permission' },
+                { key: 'info', name: '项目概况', field: 'info_permission' },
+                { key: 'contract', name: '合同管理', field: 'contract_permission', hint: ['1、编辑节点:编辑合同管理内页树结构', '2、添加合同:允许添加合同', '3、授权查看本节点合同:授权节点下查看所有人上传的合同', '4、授权查看本单位合同:授权节点下查看本单位人员添加的所有合同'] },
+                { key: 'file', name: '资料归集', field: 'file_permission' },
+                { key: 'budget', name: '动态投资', field: 'budget_permission' },
+                {
+                    key: 'financial', name: '资金监管', children: [
+                        { key: 'fund_trans', name: '资金划拨', field: 'fund_trans_permission' },
+                        { key: 'fund_pay', name: '资金支付', field: 'fund_pay_permission' },
+                    ]
+                },
+            ];
+            for (const p of this.PermissionBlock) {
+                if (p.children) {
+                    for (const c of p.children) {
+                        c.permission = [];
+                        const pConst = this.PermissionConst[c.key];
+                        if (!pConst) continue;
+                        for (const prop in pConst) {
+                            c.permission.push({ key: prop, ...pConst[prop]});
+                        }
+                    }
+                } else {
+                    p.permission = [];
+                    const pConst = this.PermissionConst[p.key];
+                    if (!pConst) continue;
+                    for (const prop in pConst) {
+                        p.permission.push({ key: prop, ...pConst[prop]});
+                    }
+                }
+            }
         }
 
         get adminPermission () {
@@ -144,6 +203,53 @@ module.exports = app => {
             }
         }
 
+        async _addUser(subProject, data) {
+            const ids = data instanceof Array ? data : [data];
+            const exists = await this.getAllDataByCondition({ where: { spid: subProject.id, uid: ids } });
+            if (exists.length > 0) throw '请勿重复选择账号';
+
+            const insertData = ids.map(x => {
+                return { id: this.uuid.v4(), spid: subProject.id, pid: subProject.project_id, uid: x };
+            });
+            await this.db.insert(this.tableName, insertData);
+            return insertData;
+        }
+
+        async _delUser(subProject, data) {
+            const ids = data instanceof Array ? data : [data];
+            const permissions = await this.getAllDataByCondition({ where: { spid: subProject.id, uid: ids } });
+            await this.db.delete(this.tableName, { id: permissions.map(x => { return x.id; }) });
+            return data;
+        }
+
+        async _updateUserPermission(data) {
+            const datas = data instanceof Array ? data : [data];
+            const updateData = [];
+            datas.forEach(x => {
+                const ud = { id: x.id };
+                for (const p of this.PermissionBlock) {
+                    if (p.children) {
+                        for (const c of p.children) {
+                            if (data[c.field] !== undefined) ud[c.field] = x[c.field] || '';
+                        }
+                    } else {
+                        if (data[p.field] !== undefined) ud[p.field] = x[p.field] || '';
+                    }
+                }
+                updateData.push(ud);
+            });
+            await this.db.updateRows(this.tableName, updateData);
+            return updateData;
+        }
+
+        async updatePermission(subProject, data) {
+            const result = {};
+            if (data.add) result.add = await this._addUser(subProject, data.add);
+            if (data.del) result.del = await this._delUser(subProject, data.del);
+            if (data.update) result.update = await this._updateUserPermission(data.update);
+            return result;
+        }
+
         async getFilingType(subProjectId) {
             const permissionConst = {}, prefix = 'f';
             for (const p in this.PermissionConst.file) {

+ 67 - 0
app/view/sp_setting/user.ejs

@@ -0,0 +1,67 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main">
+            <h2>账号管理
+                <a href="#sel-batch" data-toggle="modal" data-target="#sel-batch" class="btn btn-primary btn-sm pull-right mr-1">选择账号</a>
+            </h2>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <div class="sjs-height-0">
+                <nav class="nav nav-tabs m-3" role="tablist">
+                    <a class="nav-item nav-link active" data-toggle="tab" data-target="#user-list" href="/sp/<%- ctx.subProject.id %>/setting/user" role="tab" aria-selected="false">账号列表</a>
+                    <a class="nav-item nav-link" data-toggle="tab" data-target="#user-purview" href="/sp/<%- ctx.subProject.id %>/setting/permission" role="tab" aria-selected="true">模块权限</a>
+                    <div class="ml-auto">
+                        <div class="input-group input-group-sm">
+                            <input type="text" class="form-control" placeholder="账号/姓名/单位/手机 搜索" aria-label="账号/姓名/单位/手机 搜索" value="<%- keyword %>" aria-describedby="button-addon2">
+                            <div class="input-group-append">
+                                <button class="btn btn-outline-primary" type="button" id="button-addon2"><i class="fa fa-search"></i></button>
+                            </div>
+                        </div>
+                    </div>
+                </nav>
+                <div class="tab-content m-3">
+                    <div id="user-purview" class="tab-pane active">
+                        <div class="row">
+                            <div class="col-3">
+                                <dl class="list-group">
+                                    <a href="/sp/<%- ctx.subProject.id %>/setting/user<%- (keyword ? '?keyword=' + keyword : '') %>" class="list-group-item list-group-item-action <% if (!company) { %>active<% } %>">全部</a>
+                                    <% for (const u of subProjectUnitList) { %>
+                                    <a href="/sp/<%- ctx.subProject.id %>/setting/user?company=<%- u.name %><%- (keyword ? '&keyword=' + keyword : '') %>" class="list-group-item list-group-item-action <% if (company === u.name) { %>active<% } %>"><%- u.name %></a>
+                                    <% } %>
+                                </dl>
+                            </div>
+                            <div class="col-9">
+                                <table class="table table-hover table-bordered table-sm">
+                                    <thead><tr class="text-center"><th>账号</th><th>姓名</th><th>单位</th><th>职位</th><th>手机</th><th>电话</th><th>操作</th></tr></thead>
+                                    <tbody>
+                                    <% for (const account of subProjectAccountList) { %>
+                                    <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 %><% if (account.bind === 1) { %>(已绑定第三方平台)<% } %></td>
+                                        <td><%= account.telephone %></td>
+                                        <td class="text-center">
+                                            <a href="javascript: void(0)" data-account="<%= JSON.stringify(account) %>" name="set-permission" class="btn btn-sm btn-outline-primary">权限</a>
+                                            <a href="javascript: void(0)" data-id="<%- account.id %>" name="remove-user" class="btn btn-sm btn-danger">移除</a>
+                                        </td>
+                                    </tr>
+                                    <% } %>
+                                    </tbody>
+                                </table>
+                                <% include ../layout/page.ejs %>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const accountGroup = JSON.parse(unescape('<%- escape(JSON.stringify(accountGroup)) %>'));
+</script>

+ 100 - 0
app/view/sp_setting/user_modal.ejs

@@ -0,0 +1,100 @@
+<div class="modal fade" id="sel-batch" 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-inline mb-2">
+                    <label for="inputPassword2" class="">单位:</label>
+                    <select class="form-control form-control-sm" style="width:300px" id="sel-batch-unit">
+                        <% for (const g of accountGroup) { %>
+                        <option value="<%- g.name %>"><%- g.name %></option>
+                        <% } %>
+                    </select>
+                </div>
+                <div class="modal-height-500-scroll">
+                    <table class="table table-bordered">
+                        <thead><tr class="text-center"><th width="15%"><input type="checkbox" id="sel-batch-all"></th><th width="30%">用户</th><th width="40%">职位</th></tr></thead>
+                        <tbody id="sel-batch-users"></tbody>
+                    </table>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-sm btn-sm btn-primary" id="sel-batch-ok">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="modal fade" id="permission" data-backdrop="static" style="display: none;" aria-hidden="true">
+    <div class="modal-dialog modal-xl" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">编辑权限</h5>
+            </div>
+            <div class="modal-body">
+                <% for (const pb of permissionBlock) { %>
+                <div class="card mb-2">
+                    <h6 class="card-header">
+                        <%- pb.name %>
+                        <% if (pb.hint) { %>
+                        <div class="btn-group">
+                            <a href="" data-toggle="dropdown" title="权限说明" aria-expanded="false"><i class="fa fa-question-circle"></i></a>
+                            <div class="dropdown-menu bg-dark" style="will-change: transform;">
+                                <% for (const i of pb.hint) { %>
+                                <a class="dropdown-item text-light" href="javascript: void(0)"><%- i %></a>
+                                <% } %>
+                            </div>
+                        </div>
+                        <% } %>
+                    </h6>
+                    <div class="card-body">
+                        <% if (pb.children) { %>
+                        <% for (const [i, c] of pb.children.entries()) { %>
+                        <% if (i !== 0) { %><hr/><% } %>
+                        <div class="d-flex">
+                            <div class="vertical-align ml-3" style="width:100px"><%- c.name %></div>
+                            <div class="container ml-0">
+                                <div class="row">
+                                    <% for (const cp of c.permission) { %>
+                                    <div class="col-md-3">
+                                        <div class="form-check">
+                                            <input class="form-check-input" type="checkbox" name="permission-check" id="icb-<%- c.key %>-<%- cp.value %>" ptype="<%- c.key %>" pvalue="<%- cp.value %>">
+                                            <label class="form-check-label" for="icb-<%- c.key %>-<%- cp.value %>"><%- cp.title %></label>
+                                        </div>
+                                    </div>
+                                    <% } %>
+                                </div>
+                            </div>
+                        </div>
+                        <% } %>
+                        <% } else { %>
+                        <div class="d-flex">
+                            <div class="vertical-align ml-3" style="width:100px"><%- pb.name %></div>
+                            <div class="container ml-0">
+                                <div class="row">
+                                    <% for (const p of pb.permission) { %>
+                                    <div class="col-md-3">
+                                        <div class="form-check">
+                                            <input class="form-check-input" type="checkbox" name="permission-check" id="icb-<%- pb.key %>-<%p.value%>" ptype="<%- pb.key %>" pvalue="<%- p.value %>">
+                                            <label class="form-check-label" for="icb-<%- pb.key %>-<%- p.value %>"><%- p.title %></label>
+                                        </div>
+                                    </div>
+                                    <% } %>
+                                </div>
+                            </div>
+                        </div>
+                        <% } %>
+                    </div>
+                </div>
+                <% } %>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" id="permission-uid">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-sm btn-primary" id="permission-ok">提交修改</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 7 - 0
config/web.js

@@ -1582,6 +1582,13 @@ const JsFiles = {
                 mergeFiles: [],
                 mergeFile: 'setting_user',
             },
+            sp_permission: {
+                files: [],
+                mergeFiles: [
+                    '/public/js/sp_setting_permission.js',
+                ],
+                mergeFile: 'sp_setting_permission',
+            }
         },
         profile: {
             cert: {

+ 7 - 0
sql/update.sql

@@ -32,6 +32,13 @@ MODIFY COLUMN `rela_tender` varchar(5000) CHARACTER SET ascii COLLATE ascii_gene
 ALTER TABLE `zh_budget`
 MODIFY COLUMN `rela_tender` varchar(5000) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '' COMMENT '关联标段id(\',\'分隔)' AFTER `std_id`;
 
+ALTER TABLE `calculation`.`zh_sub_project_permission`
+ADD COLUMN `info_permission` varchar(255) NOT NULL COMMENT '项目概况,权限id列表(\',\'分隔)' AFTER `self_category_level`,
+ADD COLUMN `fund_trans_permission` varchar(255) NOT NULL COMMENT '资金划拨,权限id列表(\',\'分隔)' AFTER `info_permission`,
+ADD COLUMN `fund_pay_permission` varchar(255) NOT NULL COMMENT '资金支付,权限id列表(\',\'分隔)' AFTER `fund_trans_permission`,
+ADD COLUMN `contract_permission` varchar(255) NOT NULL COMMENT '合同管理,权限id列表(\',\'分隔)' AFTER `fund_pay_permission`,
+ADD COLUMN `datacollect_permission` varchar(255) NOT NULL COMMENT '决策大屏,权限id列表(\',\'分隔)' AFTER `contract_permission`;
+
 ------------------------------------
 -- 表数据
 ------------------------------------