1. 本章任务
之前已经实现了登录、项目管理、机构管理、用户管理,本篇来实现下权限管理的功能。
所谓权限管理,在本系统中还是比较简单的,就是某角色所能访问的菜单列表。注意角色与菜单是多对多的关系,即一个角色可以对应对个菜单,一个菜单也可以对应多个角色。
权限管理的对应关系保存在表rolemenu中。
本篇就来实现权限管理,通过下拉框选择一个角色,然后通过表格显示选中角色拥有的菜单信息,在表格中可以选择多个菜单,然后点击提交按钮可以保存角色-菜单对应。
效果图如下:
2. 页面布局
添加角色下拉框、提交按钮、菜单表格,其中菜单表格负责显示角色下拉框对应的菜单列表。
注意我们并未给数据表格设置url,这是因为需要在下拉框选项变化时,动态的为表格加载数据。另外表格中的复选框是根据返回数据中checked值决定是否选中的(true选中false不选中)。
<body> <div class="tool-box"> <select id="input-role" class="easyui-combobox" style="width: 200px;" data-options="onChange:onChangeRole"> <option value="-1">请选择角色</option> <option value="schoolmaster">学校管理员</option> <option value="collegemaster">学院管理员</option> <option value="classmaster">班主任</option> <option value="student">学生</option> </select> <a id="btn" onclick="btnSubmitClick()" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add'">提交</a> </div> <table id="mainTable" title="角色对应菜单列表" class="easyui-datagrid" fitColumns="true"> <thead> <tr> <th data-options="field:'checked',width:50" checkbox="true"></th><!-- 复选框 --> <th data-options="field:'id',width:50">序号</th> <th data-options="field:'name',width:50">名称</th> <th data-options="field:'path',width:100">访问路径</th> </tr> </thead> </table> </body> 3. 加载角色对应的菜单 当页面初始化,或者下拉框选择发生变化时,我们将角色id发送给后端,后端根据角色返回相应的菜单列表。 注意角色拥有的那些菜单项,其checked属性值应为true,这样在表格中就会显示选中效果。 首先为Menu类添加一个checked属性。 /** * 菜单 */ public class Menu { private String id; private String name; private String path; /** * 冗余字段,用于返回是否选中信息 */ private boolean checked; } 在页面初始化,以及下拉框选中变化时,触发加载表格数据方法。 // 初始化 $(function() { loadTableData(); }); // 选中项变化 function onChangeRole() { loadTableData(); } // 加载表格数据 function loadTableData() { var param = { role: $("#input-role").combobox("getValue") }; console.log("#param:", param); $.ajax({ url: "CoreServlet?method=getMenusByRole", type: "post", dataType: "json", data: param, success: function(res) { if (res.code == 0) { console.log("## res:", res); $("#mainTable").datagrid("loadData", res); //动态取数据 } else { //提示错误信息 alert(res.msg); } }, }); } 后端根据角色返回对应数据,修改RoleMenuDao: /** * 通过角色获取菜单 */ public List<Menu> getMenusByRole(String role) throws Exception { // 全部菜单 MenuDao menuDao = new MenuDao(); List<Menu> allMenus = menuDao.getAll(); // 角色对应的菜单(应选中的) Connection conn = ConnectionUtils.getConnection(); String sql = "select * from menu where id in (select menuId from rolemenu where role=?)"; QueryRunner runner = new QueryRunner(); Object[] params = { role }; List<Menu> selectedMenus = runner.query(conn, sql, new BeanListHandler<Menu>(Menu.class), params); ConnectionUtils.releaseConnection(conn); // 选中 for (Menu one : allMenus) { for (Menu selected : selectedMenus) { if (one.getId().equals(selected.getId())) { one.setChecked(true); break; } } } return allMenus; } 4. 提交角色菜单信息 当点击提交按钮时,将当前角色信息及选中的菜单列表提交到后端进行更新。 修改js代码: // 提交修改 function btnSubmitClick() { if ($("#input-role").combobox("getValue") == "-1") { alert("请先选择角色!"); return; } // 获取选中项 var checkedItems = $("#mainTable").datagrid("getChecked"); // 选中菜单的id数组 var ids = []; $.each(checkedItems, function(i, v) { ids.push(v.id); }); var param = { role: $("#input-role").combobox("getValue"), ids: ids.join(","), }; $.ajax({ url: "CoreServlet?method=submitMenusByRole", type: "post", dataType: "json", data: param, success: function(res) { if (res.code == 0) { alert("提交成功!"); } else { //提示错误信息 alert(res.msg); } }, }); } 后端进行相应处理: /** * 提交权限 */ public void submitMenusByRole(String role, String[] menuIds) throws Exception { // 先删除角色对应所有菜单 Connection conn = ConnectionUtils.getConnection(); String sql = "delete from rolemenu where role =?"; Object[] params = { role }; QueryRunner runner = new QueryRunner(); runner.update(conn, sql, params); // 然后逐一新增rolemenu for (String menuId : menuIds) { RoleMenu one = new RoleMenu(); one.setMenuId(menuId); one.setRole(role); this.insert(one); } ConnectionUtils.releaseConnection(conn); } 5. 小结 完整版的代码可以从GitHub上查看,此处就不再逐一粘贴了。