众筹项目之后台管理系统-分配(八)

1. 权限控制

权限控制机制的本质就是“用钥匙开锁”。
在这里插入图片描述

2. 给 Admin 分配 Role

2.1 目标

通过页面操作把 Admin 和 Role 之间的关联关系保存到数据库。

2.2 思路

在这里插入图片描述

2.3 代码:前往分配页面

2.3.1 创建保存 Admin-Role 关联关系的数据库表

CREATE TABLE `project_crowd`.`inner_admin_role` ( 
`id` INT NOT NULL AUTO_INCREMENT,
`admin_id` INT, `role_id` INT, 
PRIMARY KEY (`id`) );

这个表并不对应现实生活中或项目业务功能中的一个具体实体,所以没有对应
的实体类,也不通过逆向工程做逆向生成。

2.3.2 修改“分配”按钮

在这里插入图片描述

<%--<button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>--%>
                                            <a href="assign/to/assign/role/page.html?adminId=${admin.id }&pageNum=${requestScope.pageInfo.pageNum }&keyword=${param.keyword }" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></a>

2.3.3 创建 AssignHandler

在这里插入图片描述

@Controller
public class AssignHandler {

    @Autowired
    private AdminService adminService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private AuthService authService;
	@RequestMapping("/assign/to/assign/role/page.html")
    public String toAssignRolePage(
            @RequestParam("adminId") Integer adminId,
            ModelMap modelMap
    ){

        // 1.查询已分配角色
       List<Role> assignedRoleList = roleService.getAssignedRole(adminId);

        // 2.查询未分配角色
        List<Role> unAssignedRoleList =roleService.getUnAssignedRole(adminId);

        // 3.存入模型(本质上其实是:request.setAttribute("attrName,attrValue);)
        modelMap.addAttribute("assignedRoleList", assignedRoleList);
        modelMap.addAttribute("unAssignedRoleList",unAssignedRoleList);

        return "assign-role";
    }
}

2.3.4 RoleService 中的方法

在这里插入图片描述

@Override
    public List<Role> getUnAssignedRole(Integer adminId) {
        return roleMapper.selectUnAssignedRole(adminId);
    }

2.3.5 SQL 语句

在这里插入图片描述

在这里插入图片描述

<select id="selectAssignedRole" resultMap="BaseResultMap">
		select id,name from t_role where id in (select  role_id from inner_admin_role where admin_id=#{adminId})
	</select>
	<select id="selectUnAssignedRole" resultMap="BaseResultMap">
		select id,name from t_role where id not in (select  role_id from inner_admin_role where admin_id=#{adminId})
	</select>

在这里插入图片描述
在这里插入图片描述

2.3.6 在页面上显示角色数据

在这里插入图片描述
对 option 标签进行说明:

<option value="将来在提交表单时一起发送给 handler 的值">在浏览器上让用户看到的数据</option>

实际显示角色信息时:

<option value="角色的 id">角色的名称</option>

举例:

<option value="5">市场部经理</option>

页面具体代码:
在这里插入图片描述

						<div class="form-group" style="margin-left:40px;">
                            <label for="exampleInputPassword1">已分配角色列表</label><br>
                            <select name="roleIdList" class="form-control" multiple="multiple" size="10" style="width:100px;overflow-y:auto;">
                                    <c:forEach items="${requestScope.assignedRoleList }" var="role">
                                        <option  value="${role.id }">${role.name }</option>
                                    </c:forEach>
                            </select>
                        </div>

2.3.7 调整表单让表单能够提交数据

参考下面文件:
在这里插入图片描述

2.3.8 jQuery 代码

在这里插入图片描述

2.4 代码:执行分配

在这里插入图片描述

$(function () {
        $("#toRightBtn").click(function () {

            // select是标签选择器
            // :eq(0)表示选择页面上的第一个
            // :eq(1)表示选择页面上的第二个
            // ">"表示选择子元素
            // :selected表示选择"被选中的"option
            // appendTo()能够将jQuery对象追加到指定位置
            $("select:eq(0)>option:selected").appendTo("select:eq(1)");

        });
        
        $("#toLeftBtn").click(function () {
            $("select:eq(1)>option:selected").appendTo("select:eq(0)");
        });
    });

2.4.1 handler 方法

在这里插入图片描述

@RequestMapping("/assign/do/role/assign.html")
    public String saveAdminRoleRelationship(
            @RequestParam("adminId") Integer adminId,
            @RequestParam("pageNum") Integer pageNum,
            @RequestParam("keyword") String keyword,

            // 我们允许用户在页面上取消所有已分配角色再提交表单,所以可以不提供roleIdList请求参数
            // 设置required = false表示这个请求参数不是必须的
            @RequestParam(value = "roleIdList", required = false) List<Integer> roleIdList
    ){

        adminService.saveAdminRoleRelationship(adminId, roleIdList);

        return "redirect:/admin/get/page.html?pageNum="+pageNum+"&keyword="+keyword;
    }

2.4.2 Service 方法

在这里插入图片描述

 @Override
    public void saveAdminRoleRelationship(Integer adminId, List<Integer> roleIdList) {

        // 旧的数据如下:
        // adminId roleId
        // 1         1(要删除)
        // 1         2(要删除)
        // 1         3
        // 1         4
        // 1         5
        // 新数据如下:
        // adminId roleId
        // 1         3(本来就有)
        // 1         4(本来就有)
        // 1         5(本来就有)
        // 1         6(新)
        // 1         7(新)
        // 为了简化操作:先根据adminId删除旧的数据,再根据roleIdList保存全部新的数据

        // 1.根据adminId删除旧的关联关系数据
        adminMapper.deleteOLdRelationship(adminId);

        // 2.根据roleIdList和adminId保存新的关联关系
        if (roleIdList != null && roleIdList.size() > 0){
            adminMapper.insertNewRelationship(adminId,roleIdList);
        }
    }

2.4.3 SQL 语句

在这里插入图片描述
在这里插入图片描述

<delete id="deleteOLdRelationship">
    delete from inner_admin_role where admin_id=#{admin}
  </delete>

在这里插入图片描述

<insert id="insertNewRelationship">
    insert into inner_admin_role(admin_id,role_id) values
    <foreach collection="roleIdList" item="roleId" separator=",">(#{adminId},#{roleId})</foreach>
  </insert>

在这里插入图片描述
在这里插入图片描述

2.4.4 修正 Bug

在这里插入图片描述
在这里插入图片描述

$("#submitBtn").click(function () {
            // z爱提交表单前把"已分配"部分的option全部选中
            $("select:eq(1)>option").prop("selected","selected");

            /*// 为了看到上面代码的效果,暂时不让表单提交
            return false;*/
        });

3. 给 Role 分配 Auth

3.1 目标

把角色和权限的关联关系保存到数据库。

3.2 思路

在这里插入图片描述
在这里插入图片描述

3.3 代码:t_auth 建表

CREATE TABLE `t_auth` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL,
`title` varchar(200) DEFAULT NULL,
`category_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(1,'','用户模块',NULL);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(2,'user:delete','删除',1);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(3,'user:get','查询',1);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(4,'','角色模块',NULL);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(5,'role:delete','删除',4);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(6,'role:get','查询',4);
INSERT INTO t_auth(id,`name`,title,category_id) VALUES(7,'role:add','新增',4)

name 字段:给资源分配权限或给角色分配权限时使用的具体值,将来做权限验证
也是使用 name 字段的值来进行比对。建议使用英文。
title 字段:在页面上显示,让用户便于查看的值。建议使用中文。
category_id 字段:关联到当前权限所属的分类。这个关联不是到其他表关联,而是
就在当前表内部进行关联,关联其他记录。所以说,t_auth 表中是依靠 category_id 字
段建立了“节点”之间的父子关系。
在这里插入图片描述
name 字段中值的格式:中间的“:”没有任何特殊含义。不论是我们自己写的代码
还是将来使用的框架都不会解析“:”。如果不用“:”,用“%、@、&、*、-”等等这样
的符号也都是可以的。
模块:操作名
user:delete
user:get
role:delete
……

3.3.1 建表

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
+有(空)参+toString
归位

3.4 代码:打开模态框

3.4.1 准备模态框

在这里插入图片描述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div id="assignModal" class="modal fade" tabindex="-1" role="dialog">
	<div class="modal-dialog" role="document">
		<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal"
					aria-label="Close">
					<span aria-hidden="true">&times;</span>
				</button>
				<h4 class="modal-title">尚筹网系统弹窗</h4>
			</div>
			<div class="modal-body">
				<ul id="authTreeDemo" class="ztree"></ul>
			</div>
			<div class="modal-footer">
				<button id="assignBtn" type="button" class="btn btn-primary">好的,我设置好了!执行分配!</button>
			</div>
		</div>
	</div>
</div>

在这里插入图片描述

<%@include file="/WEB-INF/modal-role-assign-auth.jsp" %>

3.4.2 给“✔”按钮绑定单击响应函数

在这里插入图片描述

在 fillTableBody()函数中,修改 checkBtn
在这里插入图片描述

var checkBtn = "<button id='"+roleId+   "' type='button' class='btn btn-success btn-xs checkBtn'><i class=' glyphicon glyphicon-check'></i></button>";

在这里插入图片描述

// 13.给分配权限按钮绑定单击响应函数
        $("#rolePageBody").on("click",".checkBtn",function () {

            // 把当前角色id存入全局变量
            window.roleId = this.id;

            // 打开模态框
          $("#assignModal").modal("show");

            // 在模态框中装载树 Auth 的形结构数据
          fillAuthTree();
        });

3.4.3 加入 zTree 的环境

在这里插入图片描述
在这里插入图片描述

注意:引入的时候 zTree 的 JavaScript 库文件要放在 my-role.js 的前面

3.4.4 显示不正常分析

在这里插入图片描述

3.4.5 函数 fillAuthTree()

在这里插入图片描述

// 声明专门的函数用来在分配Auth的模态框中显示Auth的树形结构数据
function fillAuthTree() {

    // 1.发送Ajax请求查询Auth数据
   var ajaxReturn = $.ajax({
        "url": "assgin/get/all/auth.json",
        "type": "post",
        "dataType": "json",
        "async": false

    });
   
   if (ajaxReturn.status != 200){
       layer.msg("请求处理出错!响应状态码是:"+ajaxReturn.status+"说明是:"+ajaxReturn.statusText);
       return ;
   }
   
    // 2.从响应结果中获取Auth的JSON数据
    // 从服务器端查询到的list不需要组装成树形结构,这里我们交给zTree去组装
    var authList = ajaxReturn.responseJSON.data;

    // 3.准备队zTree进行设置的JSON对象
    var setting = {
        "data": {
            "simpleData":{
                // 开启简单JSON功能
                "enable": true,
                // 使用categoryId属性关联父节点,不用默认的pId
                "pIdKey": "categoryId"
            },
            "key": {
                // 使用title属性显示节点名称,不用默认的name作为属性名了
                "name": "title"
            }
        },
        "check": {
            "enable": true
        }

    };

    // 4.生成树形结构
    $.fn.zTree.init($("#authTreeDemo"),setting,authList);

    // 获取zTreeObj对象
    var zTreeObj = $.fn.zTree.getZTreeObj("authTreeDemo");

    // 调用zTreeObj对象的方法,把节点展开
    zTreeObj.expandAll(true);

    // 5.查询已分配的Auth的id组成的List
    ajaxReturn = $.ajax({
        "url": "assign/get/assigned/auth/id/bu/role/id.json",
        "type": "post",
        "data":{
            "roleId": window.roleId
        },
        "dataType":"json",
        "async": false
    });
    if (ajaxReturn.status != 200){
        layer.msg("请求处理出错!响应状态码是:"+ajaxReturn.status+"说明是:"+ajaxReturn.statusText);
        return ;
    }

    // 从响应结果中获取authIdArray
    var authIdArray = ajaxReturn.responseJSON.data;

    // 6.根据authIdArray把树形结构中对应的节点勾选上
    // 6.1 遍历authIdArray
    for (var i = 0; i < authIdArray.length ; i++) {
        var authId = authIdArray[i];

        // 6.2 根据id查询树形结构中对应的节点
        var treeNode =zTreeObj.getNodeByParam("id", authId);

        // 6.3 将treeNode设置位被勾选
        // checked设置为true表示节点勾选
        var checked = true;

        // checkTypeFlag设置为false,表示不"联动",不联动是为了避免把不该勾选的勾选上
        var checkTypeFlag = false;

        // 执行
        zTreeObj.checkNode(treeNode, checked, checkTypeFlag);
    }

}

3.4.6 创建角色到权限之间关联关系的中间表

CREATE TABLE `project_crowd`.`inner_role_auth` ( 
`id` INT NOT NULL AUTO_INCREMENT,
`role_id` INT, `auth_id` INT, 
PRIMARY KEY (`id`) );

3.4.7 根据 role_id 查询 auth_id

在这里插入图片描述

@ResponseBody
    @RequestMapping("/assign/get/assigned/auth/id/bu/role/id.json")
    public ResultEntity<List<Integer>> getAssignedAuthIdByRoleId(
            @RequestParam("roleId") Integer roleId
            ){

        List<Integer> authIdList = authService.getAssignedAuthIdByRoleId(roleId);

        return ResultEntity.successWithData(authIdList);
    }

在这里插入图片描述

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private AuthMapper authMapper;

    @Override
    public List<Auth> getAll() {
        return authMapper.selectByExample(new AuthExample());
    }

    @Override
    public List<Integer> getAssignedAuthIdByRoleId(Integer roleId) {
        return authMapper.selectAssignedAuthIdByRoleId(roleId);
    }
}

在这里插入图片描述

在这里插入图片描述

<select id="selectAssignedAuthIdByRoleId" resultType="int">
    select auth_id from inner_role_auth where role_id=#{roleId}
  </select>

在这里插入图片描述
在这里插入图片描述

3.5 代码:执行分配

3.5.1 给“分配”按钮绑定单击响应函数

在这里插入图片描述

  // 14.给分配全选模态框中的“分配”按钮绑定单击响应函数
        $("#assignBtn").click(function () {

            // 14.1 收集树形结构的各个几点中被勾选的节点
            // [1]声明一个专门的数组存放id
            var authIdArray = [];

            // [2]获取zTreeObj对象
            var zTreeObj = $.fn.zTree.getZTreeObj("authTreeDemo");

            // [3]获取全部被勾选的节点
            var checkedNodes = zTreeObj.getCheckedNodes();

            // [4]遍历checkedNodes
            for (var i = 0; i < checkedNodes.length; i++) {
                var checkedNode = checkedNodes[i];

                var authId = checkedNode.id;

                authIdArray.push(authId);
            }

            // 14.2发送请求执行分配
            var requestBody = {
                "authIdArray": authIdArray,

                // 为了服务器端handler方法能够统一使用List<Integer>方式接收数据,roleId也存入数组
                "roleId": [window.roleId]
            };

            requestBody = JSON.stringify(requestBody);

            $.ajax({
               "url": "assign/do/role/assign/auth.json",
               "type": "post",
               "data": requestBody,
               "contentType": "application/json;charset=UTF-8",
               "dataType": "json",
                "success":function (response) {
                    var result = response.result;
                    if (result == "SUCCESS"){
                        layer.msg("操作成功!");
                    }
                    if (result == "FAILED"){
                        layer.msg("操作失败!"+response.message);
                    }
                },
                "error":function (response) {
                    layer.msg(response.status+ " "+response.statusText);
                }
            });
            $("#assignModal").modal("hide");
        });

3.5.2 后端执行分配,保存关联关系

在这里插入图片描述

@ResponseBody
    @RequestMapping("/assign/do/role/assign/auth.json")
    public ResultEntity<String> saveRoleAuthRelathinship(
            @RequestBody Map<String, List<Integer>> map
            ){
        authService.saveRoleAuthRelathinship(map);
        return ResultEntity.successWithoutData();
    }

在这里插入图片描述

@Override
    public void saveRoleAuthRelathinship(Map<String, List<Integer>> map) {

        // 1.获取roleId的值
        List<Integer> roleIdList = map.get("roleId");
        Integer roleId = roleIdList.get(0);

        // 2.删除旧的关联关系数据
        authMapper.deleteOldRelathinship(roleId);

        // 3.获取authIdList
        List<Integer> authIdList = map.get("authIdArray");

        // 4.判断authIdList是否有效
        if (authIdList != null && authIdList.size() > 0){
            authMapper.insertNewRelathinship(roleId, authIdList);
        }
    }

在这里插入图片描述
在这里插入图片描述

 <select id="deleteOldRelathinship">
    delete from inner_role_auth where role_id=#{roleId}
  </select>

在这里插入图片描述

<insert id="insertNewRelathinship">
        insert into inner_role_auth(auth_id,role_id) values
        <foreach collection="authIdList" item="authId" separator=",">(#{authId},#{roleId})</foreach>
  </insert>

在这里插入图片描述
在这里插入图片描述

4. 给 Menu 分配 Auth

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值