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上查看,此处就不再逐一粘贴了。