动手实现一个企业级的权限分配demo
分析
之前分析过一波权限分配,这里动手实现的思路部分参考之前的文章 角色权限分配(没有比这讲的更细了),之前分析的权限是在一个小型的酒店系统总结的,它里面使用的权限树是easyUI
的Tree
插件,这里我实现的是原生js
操作的树,没有使用插件,所以js
部分很繁琐,但是也没关系,重要的是练习对吧?
我这个做的没有那么全,功能包含两个:
- 不同角色登录,展示菜单不同
- 超级管理员可以为其他非超级管理员分配权限,改变展示的菜单
开始表演
第一步,根据登录人不同来展示不同的菜单
ajax
请求的路径是/power/tree
,通过ajax拿权限树的数据,不同角色登录,不同权限数据。
<!DOCTYPE html>
<html xmlns:th="www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>U袋网卖家管理后台</title>
<script th:src="@{/js/jquery.1.12.4.min.js}" charset="UTF-8"></script>
<script>
$(function () {
//这个只是拿账号的,没用
$.post(
"/demo/getName",
function (data) {
//alert(JSON.stringify(data));
$("#span").html(data.name);
},
"json"
);
//通过ajax拿权限树的数据,不同角色登录,不同权限数据,构建权限菜单
$.post(
"/power/tree",
function (data) {
var str="";
//##################################
for(var i=0;i<data.length;i++){
if(data[i].parentId==0){
str+=' <li class="seconddd"><a onclick="shows('+i+')" href="#">'+data[i].name+'</a><ul class="ulObj"></ul></li>';
}
}
//##################################
$("#menu").append(str);
//##################################
for(var k=0;k<data.length;k++){
var strSe="";
if(data[k].children!=null){
// alert(data[i].children.length);
for (var j=0;j<data[k].children.length;j++){
strSe+='<li><a target="iframe" href="'+data[k].children[j].url+'">'+data[k].children[j].name+'</a></li>';
}
}else if(data[k].children==null){
}
$(".seconddd .ulObj").eq(k).append(strSe);
}
//###################################
},
"json"
);
});
function shows(i) {
$(".ulObj").eq(i).toggle();
}
</script>
</head>
<body>
<h3 id="h3">U袋网卖家管理后台</h3>
<div id="quit">
卖家:<span id="span"></span>
<a href="/demo/exit">退出</a>
</div>
<div id="main">
<div id="lianjie">
<div id="tree">
<ul id="menu">
</ul>
</div>
</div>
<iframe name="iframe" id="iframe" src="/demo/page" width="1015px" height="545px"></iframe>
</div>
</body>
</html>
controller方法
/**
* 权限树json数据,这个接口是index.html页面访问的,目的是渲染权限树
* 显示不同角色对应的不同权限
* @return
*/
@ResponseBody
@RequestMapping("/tree")
public List<TreeNode> getList(HttpSession session){
String phone = (String) session.getAttribute("phone");
return powerService.getPowerList(phone);
}
service方法
/**
* 查询对应权限的权限树的所有数据
* @param emptel
* @return
*/
@Override
public List<TreeNode> getPowerList(String emptel) {
//根据手机号查询对应的权限
List<TreeNode> powerList = powerMapper.getPowerList(emptel);
//临时集合
List<TreeNode> tempList=new ArrayList<TreeNode>();
if(powerList!=null&&powerList.size()>0){
//对角色对应的权限遍历
for(TreeNode treeNode:powerList){
//说明是一级节点
if(treeNode.getParentId()==0){
//添加到临时集合并返回
tempList.add(treeNode);
//递归绑定子节点,就是自己找自己的孩子
bindChildren(treeNode,powerList);
}
}
}
return tempList;
}
/**
* 递归绑定所有子节点(这个方法可以通用,就是自己找自己的孩子)
* @param treeNode
* @param powerList
*/
public void bindChildren(TreeNode treeNode,List<TreeNode> powerList){
for(TreeNode childrenTreeNode:powerList){
if(treeNode.getId()==childrenTreeNode.getParentId()){
List<TreeNode> children = treeNode.getChildren();
if(children==null){
List<TreeNode> childTempList=new ArrayList<TreeNode>();
childTempList.add(childrenTreeNode);
treeNode.setChildren(childTempList);
}else{
children.add(childrenTreeNode);
}
bindChildren(childrenTreeNode,powerList);
}
}
}
mapper方法
/**
* 根据手机号查询对应的所有权限
* @return
*/
@Select(value = "select id,name,parentid,state,iconcls,url from tb_power where id in (select powerid from tb_dept_power where deptno=(select deptno from emp where emptel=#{emptel}))")
List<TreeNode> getPowerList(String emptel);
效果展示
第二步,去给角色授权
首先需要写一个角色表页面,这里就不多说了,给你们个图。
然后跳转到授权页面,在授权页面也需要展示一棵树,这个是完整的权限树,但是要把该角色拥有的权限展示到复选框
里。
首先写授权页面,ajax
请求的路径是/power/checkedTree
<!DOCTYPE html>
<html xmlns:th="www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>授权页面</title>
<script th:src="@{/js/jquery.1.12.4.min.js}" charset="UTF-8"></script>
<script>
$(function () {
var id=parseInt(location.href.slice(-1));
//这个ajax只是去拿被赋权限的角色的详细信息放到页面上
$.post(
"/power/getEmpById",
{"id":id},
function (datas) {
// alert(JSON.stringify(data));
$("#name").val(datas[0].empname);
$("#deptno").val(datas[0].deptno);
$("#account").val(datas[0].emptel);
//这个ajax是在上面的ajax里面的,参数借用上面的datas[0].deptno
//展示全部菜单,并选择勾选对应的权限
$.post(
"/power/checkedTree",
{deptno:datas[0].deptno},
function (data) {
var str="";
//##################################
for(var i=0;i<data.length;i++){
if(data[i].parentId==0){
// console.log(JSON.stringify(data[i]));
if(data[i].checked=="checked"){
str+=' <li class="seconddd"><input type="checkbox" checked="checked" value="'+data[i].id+'"><a onclick="shows('+i+')" href="#">'+data[i].name+'</a><ul class="ulObj"></ul></li>';
}else{
str+=' <li class="seconddd"><input type="checkbox" value="'+data[i].id+'"><a onclick="shows('+i+')" href="#">'+data[i].name+'</a><ul class="ulObj"></ul></li>';
}
}
}
//##################################
$("#menu").append(str);
//##################################
for(var k=0;k<data.length;k++){
var strSe="";
if(data[k].children!=null){
// alert(data[i].children.length);
for (var j=0;j<data[k].children.length;j++){
if(data[k].children[j].checked=="checked"){
strSe+='<li><input type="checkbox" checked="checked" value="'+data[k].children[j].id+'"><a target="iframe" href="'+data[k].children[j].url+'">'+data[k].children[j].name+'</a></li>';
}else {
strSe+='<li><input type="checkbox" value="'+data[k].children[j].id+'"><a target="iframe" href="'+data[k].children[j].url+'">'+data[k].children[j].name+'</a></li>';
}
}
}else if(data[k].children==null){
}
$(".seconddd .ulObj").eq(k).append(strSe);
}
},
"json"
);
},
"json"
);
});
</script>
<style>
//只是控制ul、li树的显示隐藏的。
ul{
list-style: none;
}
</style>
</head>
<body>
<h4 style="text-align: center">请授权</h4>
姓名:<input style="margin-left: 32px;" type="text" id="name" disabled="disabled"><br>
部门编号:<input type="text" id="deptno" disabled="disabled"><br>
账号:<input style="margin-left: 32px;" type="text" id="account" disabled="disabled"><br>
<p style="color: red">请选择权限</p>
<div id="tree">
<ul id="menu"></ul><br>
<input type="button" id="commit" value="保存权限">
</div>
<script>
//点击保存按钮,收集被勾选的复选框的值,然后去保存
$("#commit").click(function () {
var tempArr="";
//所有被选中的复选框的值
$("input:checkbox:checked").each(function (i) {
tempArr+=($(this).val())+",";
});
var deptno=$("#deptno").val();
var temp="";
temp=tempArr.slice(0,-1);
console.log(temp);
$.ajax({
url:"/power/savePower",
data:{tempArr:temp,deptno:deptno},
dataType:"json",
type:"post",
sync:false,
success:function (data) {
alert(data.success);
}
});
});
</script>
</body>
</html>
controller方法
/**
* 授权,得到角色对应的权限(多选框加上勾勾)
* 这个也是去拿权限树列表
* 1,这个权限是整张权限表的权限
* 2,返回的权限json数据带有checked的属性被赋值了(因为页面多选框判断勾勾)
*/
@RequestMapping("/checkedTree")
@ResponseBody
public List<TreeNode> getCheckedList(String deptno){
return powerService.getCheckedList(deptno);
}
service方法
@Override
public List<TreeNode> getCheckedList(String deptno) {
//查询整张权限表所有的权限数据
List<TreeNode> powerList = powerMapper.powerList();
//去部门权限关联表中,根据deptno查询该角色拥有的对应的权限(就是roleId的集合)
List<Map> powerByRoleIdList = powerMapper.powerByRoleIdList(deptno);
if(powerList!=null&&powerList.size()>0){
//对所有权限进行遍历
for(TreeNode powers:powerList){
if(powerByRoleIdList!=null&&powerByRoleIdList.size()>0){
//再对roleId的集合进行遍历
for(Map map:powerByRoleIdList){
//如果权限表的一条数据的powerid等于roleId的值,则该权限表的这条数据的checked属性设为“checked”(这里是字符串格式)
if(map.get("powerid").equals(powers.getId())){
powers.setChecked("checked");
}
}
}
}
}
//建一个临时集合
List<TreeNode> tempList=new ArrayList<TreeNode>();
if(powerList.size()>0&&powerList!=null){
//上面已经把所有的权限数据都已经设置checked属性了
//然后对已经被设置checked属性的所有权限数据进行遍历
for(TreeNode treeNode:powerList){
//如果是一级节点,把该节点添加到临时集合
if(treeNode.getParentId() == 0){//说明是一级节点
tempList.add(treeNode);
//递归绑定子节点
bindChildren(treeNode,powerList);
}
}
}
//最后返回
return tempList;
}
mapper方法
/**
* 查询所有的权限表数据
*/
@Select(value = "select id,name,parentid,state,iconcls,url from tb_power")
List<TreeNode> powerList();
/**
* 查询角色拥有的权限
*/
@Select(value = "select powerid from tb_dept_power where deptno=#{deptno}")
List<Map> powerByRoleIdList(String deptno);
然后就完成了权限树复选框展示效果,如下图
第三步,保存授权
在上面的授权页面的写了保存的js
方法了,点击按钮触发方法,收集被勾选的复选框的值,然后通过ajax
传到后台进行处理,参数是当前页的deptno
部门编号和拼接好的字符串(对应的权限id)
参考数据库tb_dept-power
表
ajax
请求的保存方法
/**
* 点击保存授权,接收授权时勾选的权限对应id,并保存授权
*/
@RequestMapping("/savePower")
@ResponseBody
public JSONObject savePower(String tempArr, String deptno){//参数:页面的权限对应id(html页面拼接成了“12,5,7”格式的字符串),部门编号
int j=0;
//把拼接成了“12,5,7”格式的字符串转为数组的格式
String[] arr=tempArr.split(",");
//创建一个list集合,对arr数组进行遍历,把数组中的内容全部放到list集合里
List<String> ids=new ArrayList<String>(arr.length);
for(String s:arr){
ids.add(s);
}
//保存之前删除之前的所有权限
powerService.deletePower(deptno);
//对权限对应id的集合进行遍历,然后进行插入
for(String id:ids){
Integer intId=Integer.valueOf(id);
//在tb_dept_power表插入数据,给角色保存权限
int i = powerService.savePower(intId, deptno);
j+=1;
}
JSONObject jsonObject=new JSONObject();
if(j>0){
jsonObject.put("success","恭喜,保存权限成功!");
return jsonObject;
}else{
jsonObject.put("error","不好意思,您保存失败了!");
return jsonObject;
}
}
service方法和mapper方法
@Override
public int deletePower(String deptno) {
return powerMapper.deletePower(deptno);
}
@Override
public int savePower(Integer intId, String deptno) {
return powerMapper.savePower(intId,deptno);
}
/**
* 保存授权之前删除所有权限
*/
@Delete(value = "delete from tb_dept_power where deptno=#{deptno}")
int deletePower(String deptno);
/**
* 保存授权
*/
@Insert(value = "insert into tb_dept_power(deptno,powerid) values (#{deptno},#{intId})")
int savePower(@Param("intId") Integer intId,@Param("deptno") String deptno);
然后就保存成功了,效果图展示。
房间管理员本来拥有的权限菜单
超级管理员给房间管理员分配权限
添加权限
保存权限成功之后,房间管理员登录系统,展示菜单是这样式儿的。
如果谁想要研究源码的话,可以留言告诉我,我私发你!!!滴滴,开车啦!
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!