基于easyUI实现权限管理系统(三)——角色管理

此文章是基于  EasyUI+Knockout实现经典表单的查看、编辑

 

一. 相关文件介绍

  1. role.jsp:角色管理界面

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>角色管理</title>
    <%@ include file="/common/head.jsp"%>
 </head>
 <body>
     <div class="toolbar">
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-arrow_refresh" title="刷新" data-bind="click:refreshClick">刷新</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-add" title="新增" data-bind="click:addClick">新增</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-edit" data-bind="click:editClick" title="编辑">编辑</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-cross" title="删除" data-bind="click:deleteClick">删除</a>
        <a href="#" plain="true" class="easyui-linkbutton" icon="icon-save" data-bind="click:saveClick" title="保存">保存</a>
    </div>
    
    <table id="gridlist" data-bind="datagrid:grid">
        <thead>  
            <tr>  
                <th field="id"  hidden="true"></th>  
                <th field="roleName"    align="left"    width="150" editor="{type:'validatebox',options:{required: true }}">角色名称</th>  
                <th field="roleSeq"     align="left"    width="100" editor="text" >排序   </th>
                <th field="description" align="left"    width="200" editor="text">描述     </th> 
                <th field="permit" align="center"    width="200" formatter="formatterPermit">操作     </th> 
             </tr>                            
        </thead>      
    </table>
    
    <script type="text/html" id="permission-template">
        <div class="container" style="margin:5px;height:525px;">
            <div>
                <span class="icon32 icon-group32" style="padding-left:48px;font-weight:bold; font-size:14px;color:#666;" data-bind="text:role.roleName">角色名称</span> 
                <span data-bind="text:role.description" style="margin-left:10px;"></span>
            </div>
 
            <div class="easyui-tabs" data-bind="easyuiTabs:tab">  
                <div title="菜单权限" >
                    <table id="gridlist" data-bind="treegrid:grid">
                        <thead>  
                            <tr>  
                                <th field="chk" checkbox="true"></th>
                                <th field="menuName"    align="left"    width="150">菜单   </th> 
                                <!-- 
                                <th field="id"    align="left"    width="80" >编码   </th>  
                                -->
                                <th field="description" align="left"    width="200" >备注说明   </th>  
                            </tr>                            
                        </thead>      
                    </table>   
                </div>

                <div title="按钮权限">
                    <table data-bind="treegrid:grid2"></table>   
                </div>
       
            </div> 
        </div>
         
        <div style="text-align:center;clear:both">
            <a class="easyui-linkbutton" data-options="iconCls:'icon-ok'" data-bind="click:confirmClick" href="javascript:void(0)"  >确定</a>  
            <a class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" data-bind="click:cancelClick" href="javascript:void(0)">取消</a> 
        </div>
    </script>
    
    <script type="text/html" id="members-template">
        <div style="margin:5px;">
            <div style="border-bottom:1px solid #CCC; margin-bottom:5px;">
                <span id="role_name" class="icon32 icon-group32" style="padding-left:48px;font-weight:bold; font-size:14px;color:#666;" data-bind="text:roleName">角色名称</span> 
            </div>
            <div style="margin-bottom:10px;height:20px;">
                <label>描述:</label><input data-bind="value:description" type="text" readonly=true class="z-txt" style="width:430px;color:#666;vertical-align:middle">
            </div>
            <div> 成员:</div>
            <select id="user_groups" data-bind="options:members,optionsText:memberText ,value:selectValue" size="10" style="width:475px; line-height:30px;height:195px;padding:5px"></select>
            <div style="margin-top:2px;">
                <a href="#" class="easyui-linkbutton" id="group_add" plain="true" iconCls="icon-group-add" data-bind="click:addClick">添加</a>
                <a href="#" class="easyui-linkbutton" id="group_delete" plain="true" iconcls="icon-group-delete" data-bind="click:deleteClick">删除</a>
                <a href="#" class="easyui-linkbutton" id="group_clear" plain="true" iconCls="icon-clear" data-bind="click:clearClick">清空</a>
            </div>
        </div>
        <div style="text-align:center;">
            <a class="easyui-linkbutton" data-options="iconCls:'icon-ok'" data-bind="click:confirmClick" href="javascript:void(0)"  >确定</a>  
            <a class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" data-bind="click:cancelClick" href="javascript:void(0)">取消</a> 
        </div>
    </script>
        
    <script type="text/html" id="choose-members-template">
        <div style="margin:5px;height:425px;overflow:auto;">
             <div style="border-bottom:1px solid #CCC; margin-bottom:5px;">
                <span class="icon32 icon-org32" style="padding-left:48px;font-weight:bold; font-size:14px;color:#666;">
                机构成员<input type="checkbox" style="vertical-align:middle;margin-left:5px;" data-bind="checked:checkAllOrganize"/>全选</span> 
            </div>

            <ul style="margin:0;padding:0;clear:both" data-bind="foreach:organizes">
                <li style="float:left;list-style:none;margin:3px;"><input type="checkbox" data-bind="value:id,checked:checked" style="vertical-align:middle" /><label data-bind="text:organizeName" ></label></li>
            </ul>

            <div style="border-bottom:1px solid #CCC; margin-bottom:5px;clear:both">
                   <span class="icon32 icon-user32" style="padding-left:48px;font-weight:bold; font-size:14px;color:#666;">
                用户成员<input type="checkbox" style="vertical-align:middle;margin-left:5px;" data-bind="checked:checkAllUser"/>全选</span> 
            </div>

            <ul style="margin:0;padding:0;clear:both" data-bind="foreach:users">
                <li style="float:left;list-style:none;margin:3px;"><input type="checkbox" data-bind="value:id,checked:checked" style="vertical-align:middle"/><label data-bind="text:userName"></label></li>
            </ul>
        </div>
        <div style="text-align:center;clear:both">
            <a class="easyui-linkbutton" data-options="iconCls:'icon-ok'" data-bind="click:confirmClick" href="javascript:void(0)"  >确定</a>  
            <a class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" data-bind="click:cancelClick" href="javascript:void(0)">取消</a> 
        </div>
    </script>
                
     <%@ include file="/common/foot.jsp"%>
    <script src="viewModel/sys/role.js"></script>
    <script type="text/javascript">
        using(['validatebox','messager','dialog']);
        var data = ${model};
        ko.bindingViewModel(new viewModel(data));
        var formatterPermit = function (value, row) {
            var html = '<a href="javascript:;" onclick=\'permissionTab(' + JSON.stringify(row) + ')\'><span class="icon icon-set1">&nbsp;</span>[编辑权限]</a>';
            html += '<a href="javascript:;" onclick=\'memberDialog(' + JSON.stringify(row) + ')\' style="margin-left:10px"><span class="icon icon-users ">&nbsp;</span>[管理成员]</a>';
            return html;
        };
    </script>
 </body>
</html>
View Code

  

  2. role.js:实现角色管理功能、列表,编辑权限、管理成员功能

function viewModel() {
    var self = this;
    
    this.grid = {
        size: { w: 4, h: 40 },
        url: rootPath+'/sys/role!list.do',
        queryParams: ko.observable(),
        loadFilter: function (d) {
            return {rows:d,total:d.length};
        }
    };
    this.gridEdit = new com.editGridViewModel(self.grid);
    this.grid.onDblClickRow = self.gridEdit.begin;
    this.grid.onClickRow = self.gridEdit.ended;
    
    this.refreshClick = function () {
        window.location.reload();
    };
    
    this.addClick = function () {
        self.gridEdit.addnew({});
    };
    
    this.editClick = function () {
        var row = self.grid.datagrid('getSelected');
        var index = self.grid.datagrid('getRowIndex', row);
        self.gridEdit.begin(index, row);
    };
    
    this.deleteClick = self.gridEdit.deleterow;
    
    this.saveClick = function () {
        self.gridEdit.ended();
        var post = {};
        post.list = self.gridEdit.getChanges(['id', 'roleName', 'roleSeq', 'description']);
        if (self.gridEdit.ended() && post.list._changed) {
            com.ajax({
                url: rootPath+'/sys/role!edit.do',
                data: ko.toJSON(post),
                success: function (d) {
                    com.message('success', '保存成功!');
                    self.grid.queryParams({});
                }
            });
        }

    };
}


var permissionTab = function (row) {
    com.dialog({
        title: "角色授限",
        width: 800,
        height: 600,
        html: "#permission-template",
        viewModel: function (win) {
            var self = this;
            this.role = ko.mapping.fromJS(row);
            this.tab = {
                onSelect: function (title, index) {
                    if (title == '按钮权限') {
                        //取得菜单权限中的选中行,并重新加开到按钮权限列表中
                        var temp = {},data = [],panel = self.grid2.treegrid('getPanel');
                        utils.eachTreeRow(self.grid.treegrid('getData'), function (node) {
                            if (node.checked) {
                                data.push(utils.filterProperties(node, ['children', 'description'], true));
                                temp[node.id] = node;
                            }
                        });
                        self.grid2.treegrid('loadData', data);

                       //checkbox点击处理函数
                       var checkHandler = function (obj,value) {
                           if (!obj.length) return;
                           var map = { "0": rootPath+"/content/images/checknomark.gif", "1": rootPath+"/content/images/checkmark.gif" };
                           obj.attr("src", map[value]).attr("value", value);
                           temp[obj.attr("menuId")]["btn_" + obj.attr("buttonId")] = parseInt(obj.attr("value"));
                       };

                        //注册checkbox点击事件
                        panel.find("td[field]").unbind("click").click(function () {
                            var img = $(this).find("img"), value = img.attr("value") == "1" ? "0" : "1";
                            checkHandler(img, value);
                        
                            if (img.attr("buttonId")== "_checkall") 
                                panel.find("img[menuId=" + img.attr("menuId") + "]").each(function () {
                                    checkHandler($(this), value);
                                });
                        });

                        //注册全选checkbox的事件
                        panel.find(".datagrid-header .icon-chk_unchecked").unbind("click").click(function () {
                            var chk = $(this),
                                value = chk.hasClass("icon-chk_checked") ? "0" : "1",
                                iconcls = chk.hasClass("icon-chk_checked") ? "icon-chk_unchecked" : "icon-chk_checked";
                            chk.removeClass("icon-chk_unchecked").removeClass("icon-chk_checked").addClass(iconcls);

                            panel.find("img").each(function () {
                                checkHandler($(this), value);
                            });
                        });
                    }
                }
            };
            
            this.grid = {
                height: 460,
                width: 774,
                url: rootPath+'/sys/menu!getEnabled.do?roleId='+row.id,
                idField: 'id',
                queryParams: ko.observable(),
                treeField: 'menuName',
                singleSelect: false,
                onCheck: function (node) {
                    node.checked = true;
                },
                onUncheck: function (node) {
                    node.checked = false;
                },
                onCheckAll:function(rows){
                    utils.eachTreeRow(rows, function (node) { node.checked = true; });
                },
                onUncheckAll: function (rows) {
                    utils.eachTreeRow(rows, function (node) { node.checked = false; });
                },
                loadFilter: function (d) {
                    var formatterChk = function (buttonId) {
                        return function (value, row) {
                            if (value >= 0)
                                return '<img menuId="' + row.id + '" buttonId="' + buttonId + '" value="' + value + '" src="' + rootPath + '/content/images/' + (value ? "checkmark.gif" : "checknomark.gif") + '"/>';
                        };
                    }
                    var cols = [[]];
                    for (var i in d.buttons)
                        cols[0].push({ field: 'btn_'+d.buttons[i].id, width: 50, align: 'center', title: utils.formatString('<span class="icon {1}">{0}</span>', d.buttons[i].buttonName, d.buttons[i].buttonIcon), formatter: formatterChk(d.buttons[i].id) });
                    self.grid2.columns(cols);

                    return utils.toTreeData(d.menus, 'id', 'parentId', "children");
                }
            };
            
            this.grid2 = {
                height: 460,
                width: 774,
                idField: 'id',
                treeField: 'menuName',
                frozenColumns: [[
                    { field: 'menuName', width: 150, title: '菜单' },
                    {
                        field: 'btn__checkall',
                        width: 50,
                        align: 'center',
                        title: '<span class="icon icon-chk_unchecked">全选</span>',
                        formatter: function (v, r) {
                            for (var i in r) {
                                if (i.indexOf("btn_") > -1 && r[i] > -1) {
                                    return '<img menuId="' + r.id + '" buttonId="_checkall" src="' + rootPath + '/content/images/' + (v ? "checkmark.gif" : "checknomark.gif") + '"/>';
                                }
                            }
                        }
                    }
                ]],
                columns: ko.observableArray(),
                loadFilter: function (d) {
                    return utils.toTreeData(d, 'id', 'parentId', "children");
                } 
            };
            
            this.confirmClick = function () {
                var post = {menus:[],buttons:[]};
                utils.eachTreeRow(self.grid.treegrid('getData'),function(node){
                    if (node.checked) {
                        //1 取得菜单权限数据  
                        post.menus.push({ menuId: node.id });
 
                        //2 取得按钮权限数据
                        for (var btn in node) 
                            if (btn.substr(0, 4) == 'btn_' && node[btn] == '1' && btn != 'btn__checkall')
                                post.buttons.push({ menuId: node.id, buttonId: btn.split('_')[1]});

                    }
                });
 
                com.ajax({
                    url: rootPath+'/sys/role!editPermission.do?roleId=' + row.id,
                    data: ko.toJSON(post),
                    success: function (d) {
                        self.cancelClick();
                        com.message('success', '保存成功!');
                    }
                });

            };
            
            this.cancelClick = function () {
                win.dialog('close');
            };
        }
    })
}

var memberDialog = function (row) {
    var users = data.users;
    var organizes = data.organizes;

    com.dialog({
        title: "管理成员",
        width: 500,
        height: 400,
        html: "#members-template",
        viewModel: function (win) {
            var self = this;
            this.members = ko.observableArray([]);
            this.memberText = function (item) {
                return utils.formatString('[{0}] {1}', item.memberType == 'user' ? '用户' : '机构', item.memberName);
            };
            com.ajax({
                type: 'GET',
                url: rootPath+'/sys/role!getRoleMembers.do?roleId=' + row.id,
                success: function (d) {
                    self.members(d);
                }
            });
            this.roleName = utils.formatString("{0}", row.roleName);
            this.description = row.description || " ";
            this.addClick = function () {
                com.dialog({
                    title: "选择成员",
                    width: 600,
                    height: 500,
                    html: "#choose-members-template",
                    viewModel: function (w) {
                        var that = this;
                        for (var i in users) users[i].checked = false;
                        for (var i in organizes) organizes[i].checked = false;
                        this.users = ko.mapping.fromJS(users);
                        this.organizes = ko.mapping.fromJS(organizes);
                        this.checkAllUser = ko.observable(false);
                        this.checkAllUser.subscribe(function (b) {
                            var list = that.users();
                            for (var i in list)
                                list[i].checked(b);
                        });
                        this.checkAllOrganize = ko.observable(false);
                        this.checkAllOrganize.subscribe(function (b) {
                            var list = that.organizes();
                            for (var i in list)
                                list[i].checked(b);
                        });
                        this.confirmClick = function () {
                            var userlist = this.users(),organizelist=this.organizes(),memberMap = {},members = ko.toJS(self.members);
                            for (var j in members)
                                memberMap[members[j].memberType + '|' + members[j].memberId] = true;

                            for (var i in userlist)
                                if (userlist[i].checked()) {
                                    var item = { memberName: userlist[i].userName(), memberId: userlist[i].id(), memberType: 'user' };
                                    if (!memberMap[item.memberType + '|' +item.memberId]) self.members.push(item);
                                }

                            for (var i in organizelist)
                                if (organizelist[i].checked()) {
                                    var item = { memberName: organizelist[i].organizeName(), memberId: organizelist[i].id(), memberType: 'organize' };
                                    if (!memberMap[item.memberType + '|' +item.memberId]) self.members.push(item);
                                }
                            this.cancelClick();
                        };
                        this.cancelClick = function () { w.dialog('close'); };
                    }
                });
            };

            this.selectValue = ko.observable();
            this.deleteClick = function () {
                if (this.selectValue()) {
                    self.members.remove(this.selectValue());
                }
            };
            this.clearClick = function () {
                self.members([]);
            };
            this.confirmClick = function () {
                com.ajax({
                    url: rootPath+'/sys/role!editRoleMembers.do?roleId=' + row.id,
                    data: ko.toJSON(self.members),
                    success: function (d) {
                        com.message('success', '保存成功!');
                        self.cancelClick();
                    }
                });
            };
            this.cancelClick = function () { win.dialog('close'); };
        }
    });

};
View Code

  

二. 效果图

  1. 访问:http://localhost:8080/ims/sys/role.do,角色管理界面

 

  2. 点击 编辑权限,菜单权限

 

  3. 按钮权限

 

  4. 点击 管理成员

 

posted on 2017-03-24 12:12  大饼酥  阅读(3949)  评论(1编辑  收藏  举报

导航