当前位置: 首页 > news >正文

尚好房 09_权限管理

尚好房:权限管理

一、业务介绍

1. 数据库表关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x9agv9ZW-1661871694240)(images/09/img_001.png)]

2. 权限表介绍

2.1 表结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-btEi4NNj-1661871694245)(images/09/img_002.png)]

2.2 表数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lu50aspt-1661871694247)(images/09/img_003.png)]

3. 页面效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LBjiiuU4-1661871694248)(images/09/img_004.png)]

二、权限管理模块

前面已经做了用户管理与角色管理,目前我们在此基础上完善权限管理功能

1. 给用户分配角色功能

1.1 显示分配角色页面

1.1.1 持久层
1.1.1.1 AdminRoleMapper接口

service-acl项目中创建com.atguigu.mapper.AdminRoleMapper接口

public interface AdminRoleMapper extends BaseMapper<AdminRole> {
    /**
     * 根据用户id查询其分配的角色id列表
     * @param adminId
     * @return
     */
    List<Long> findRoleIdListByAdminId(Long adminId);
}
1.1.1.1 AdminRoleMapper.xml映射配置文件

service-acl项目中创建resources/mappers/AdminRoleMapper.xml映射配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.AdminRoleMapper">
    <select id="findRoleIdListByAdminId" resultType="long">
        select role_id from acl_admin_role where admin_id=#{adminId} and is_deleted=0
    </select>
</mapper>
1.1.2 业务层
1.1.2.1 RoleService接口

service-api项目中的com.atguigu.service.RoleService接口中新增

/**
 * 查询用户的角色列表
 * @param adminId
 * @return
 */
Map<String,List<Role>> findRolesByAdminId(Long adminId);
1.1.2.2 RoleServiceImpl实现类

service-acl项目中的com.atguigu.service.impl.RoleServiceImpl实现类中新增

@Autowired
private AdminRoleMapper adminRoleMapper;
@Override
public Map<String, List<Role>> findRolesByAdminId(Long adminId) {
    //1. 查询所有角色
    List<Role> allRoleList = roleMapper.findAll();
    //2. 查询用户已分配的角色id列表
    List<Long> assignRoleIdList = adminRoleMapper.findRoleIdListByAdminId(adminId);
    //3. 创建俩List分别存储用户已分配和未分配的角色
    List<Role> unAssignRoleList = new ArrayList<>();
    List<Role> assignRoleList = new ArrayList<>();
    //4. 筛选用户已分配和未分配角色
    for (Role role : allRoleList) {
        if (assignRoleIdList.contains(role.getId())) {
            //已分配
            assignRoleList.add(role);
        }else {
            //未分配
            unAssignRoleList.add(role);
        }
    }
    Map<String,List<Role>> roleMap = new HashMap<>();
    roleMap.put("unAssignRoleList",unAssignRoleList);
    roleMap.put("assignRoleList",assignRoleList);
    return roleMap;
}
1.1.3 表现层

web-admin项目中的com.atguigu.controller.AdminController中新增

@GetMapping("/assignShow/{id}")
public String assignShow(@PathVariable("id") Long id,
                         Model model){
    //1. 调用业务层的方法获取用户已分配和未分配的角色列表
    Map<String, List<Role>> roleListMap = roleService.findRolesByAdminId(id);
    //2. 将查询到的数据存储到请求域,请求域中的key分别是assignRoleList和unAssignRoleList

    //3. 将id存储到请求域: 为了在分配角色页面中拿到adminId
    model.addAttribute("adminId",id);

    model.addAllAttributes(roleListMap);
    return PAGE_ASSIGN_SHOW;
}
1.1.4 前端页面

① 在web-admin项目中的templates/admin/index.html中新增

新增标签

<a class="assign" th:attr="data-id=${item.id}" >分配角色</a>

绑定点击事件

$(".assign").on("click",function () {
    var id = $(this).attr("data-id");
    opt.openWin('/admin/assignShow/'+id,'分配角色',550,450)
});

② 在web-admin项目中创建templates/admin/assignShow.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="common/head :: head"></head>

<style type="text/css">
    select option{
        width:260px;
        height:25px;
        line-height:25px;
        padding: 5px 5px;
    }
</style>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="ibox float-e-margins">
        <form id="ec" th:action="@{/admin/assignRole}" method="post" class="form-horizontal">
            <input type="hidden" name="adminId" th:value="${adminId}">
            <input type="hidden" name="roleIds" id="roleIds" value="">
            <div style="text-align: center;padding-left: 20px;">
                <div id="s1" style="float: left;">
                    <div style="font-weight:900;">未选择</div>
                    <select id="select1" multiple="multiple" style="width: 220px;height: 280px;overflow-y:auto;" ondblclick="funRight()">
                        <option th:each="item: ${unAssignRoleList}" th:value="${item.id}" th:text="${item.roleName}">11</option>
                    </select>
                </div>
                <div style="float: left;padding-top:120px;">
                    <br />
                    <button type="button" id="right"> &gt;&gt; </button><br /><br />

                    <button type="button" id="left">  &lt;&lt; </button>

                </div>
                <div id="s2" style="float: left;">
                    <div style="font-weight:900;">已选择</div>
                    <select id="select2" multiple="multiple" style="width: 220px;height: 280px;overflow-y:auto;" ondblclick="funLeft()">
                        <option th:each="item: ${assignRoleList}" th:value="${item.id}" th:text="${item.roleName}">11</option>
                    </select>
                </div>

                <div class="form-group" style="clear: left;padding-top: 20px;">
                    <button type="button" class="btn btn-sm btn-primary "  style="margin-left: 10px;"> 保存</button>
                    <button type="button" class="btn btn-sm btn-primary "  style="margin-left: 10px;"> 重置</button>
                    <button class="btn btn-sm btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消</button>
                </div>
                <br/>
            </div>
        </form>
    </div>
</div>
<script th:inline="javascript">
    $(function(){
        $("#right").on("click",function() {
            $("#select1 option").each(function(index, item){
                if(item.selected == true){
                    document.getElementById("select2").appendChild(item);
                }
            });
        });

        $("#left").on("click",function() {
            $("#select2 option").each(function(index, item){
                if(item.selected == true){
                    document.getElementById("select1").appendChild(item);
                }
            });
        });
    });

    function funRight() {
        $("#right").trigger("click");
    }

    function funLeft() {
        $("#left").trigger("click");
    }
</script>
</body>
</html>

1.2 保存角色分配

1.2.1 持久层
1.2.1.1 AdminRoleMapper接口

service-acl项目的com.atguigu.mapper.AdminRoleMapper接口中新增

/**
 * 查询用户是否绑定过该角色
 * @param adminId
 * @param roleId
 * @return
 */
AdminRole findByAdminIdAndRoleId(@Param("adminId") Long adminId,@Param("roleId") Long roleId);

/**
 * 移除用户的角色
 * @param adminId
 * @param removeRoleIdList
 */
void removeAdminRole(@Param("adminId") Long adminId,@Param("roleIds") List<Long> removeRoleIdList);
1.2.1.2 AdminRoleMapper.xml映射配置文件

service-acl项目的resources/mappers/AdminRoleMapper.xml中新增

<sql id="columns">
    select id,role_id,admin_id,create_time,update_time,is_deleted
</sql>
<select id="findByAdminIdAndRoleId" resultType="AdminRole">
    <include refid="columns"></include>
    from acl_admin_role
    where admin_id=#{adminId} and role_id=#{roleId}
</select>
<update id="removeAdminRole">
    update acl_admin_role
    set is_deleted=1
    where admin_id=#{adminId}
    and role_id in (
    <foreach collection="roleIds" item="roleId" separator=",">
        #{roleId}
    </foreach>
    )
</update>
<insert id="insert">
    insert into acl_admin_role (
    id ,
    role_id ,
    admin_id
    ) values (
    #{id} ,
    #{roleId} ,
    #{adminId}
    )
</insert>
<update id="update">
    update acl_admin_role set is_deleted=#{isDeleted} where id=#{id}
</update>
1.2.2 业务层
1.2.2.1 RoleService接口

service-api项目中的com.atguigu.service.RoleService接口中新增

/**
 * 保存用户角色
 * @param adminId
 * @param roleIdList
 */
void saveAdminRole(Long adminId,List<Long> roleIdList);
1.2.2.2 RoleServiceImpl实现类

service-acl项目中的com.atguigu.service.impl.RoleServiceImpl实现类中新增

@Override
public void saveAdminRole(Long adminId, List<Long> roleIds) {
    //1. 查询当前用户已分配的id集合
    List<Long> assignRoleIds = adminRoleMapper.findRoleIdListByAdminId(adminId);
    //2. 找出需要移除的角色id
    //使用Stream流完成
    /*List<Long> removeRoleIds = assignRoleIds.stream()
                .filter(roleId -> !roleIds.contains(roleId)).collect(Collectors.toList());*/

    List<Long> removeRoleIds = new ArrayList<>();
    //不使用Stream流
    for (Long roleId : assignRoleIds) {
        if (!roleIds.contains(roleId)) {
            //要移除
            removeRoleIds.add(roleId);
        }
    }
    //3. 调用持久层的方法移除用户和这些角色的绑定
    if (removeRoleIds != null && removeRoleIds.size() > 0) {
        adminRoleMapper.removeAdminRole(adminId,removeRoleIds);
    }

    //4. 遍历出新传过来的每一个角色id
    for (Long roleId : roleIds) {
        //判断当前角色id是否已绑定(分配)
        AdminRole adminRole = adminRoleMapper.findByAdminIdAndRoleId(adminId, roleId);
        if (adminRole == null) {
            //说明之前从未绑定
            //新增数据
            adminRole = new AdminRole();
            adminRole.setAdminId(adminId);
            adminRole.setRoleId(roleId);
            adminRoleMapper.insert(adminRole);
        }else {
            //说明之前绑定过
            if (adminRole.getIsDeleted() == 1) {
                //但是已经移除绑定了
                //修改is_deleted为0
                adminRole.setIsDeleted(0);
                adminRoleMapper.update(adminRole);
            }
        }
    }
}
1.2.3 表现层

web-admin项目中的com.atguigu.controller.AdminController中新增

@PostMapping("/assignRole")
public String assignRole(@RequestParam("adminId") Long adminId,
                         @RequestParam("roleIds") List<Long> roleIds,
                         Model model){
    roleService.saveAdminRole(adminId,roleIds);
    return successPage(model,"保存角色成功");
}
1.2.4 前端页面

web-admin项目中的templates/admin/assignShow.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="common/head :: head"></head>

<style type="text/css">
    select option{
        width:260px;
        height:25px;
        line-height:25px;
        padding: 5px 5px;
    }
</style>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="ibox float-e-margins">
        <form id="ec" th:action="@{/admin/assignRole}" method="post" class="form-horizontal">
            <input type="hidden" name="adminId" th:value="${adminId}">
            <input type="hidden" name="roleIds" id="roleIds" value="">
            <div style="text-align: center;padding-left: 20px;">
                <div id="s1" style="float: left;">
                    <div style="font-weight:900;">未选择</div>
                    <select id="select1" multiple="multiple" style="width: 220px;height: 280px;overflow-y:auto;" ondblclick="funRight()">
                        <option th:each="item: ${unAssignRoleList}" th:value="${item.id}" th:text="${item.roleName}">11</option>
                    </select>
                </div>
                <div style="float: left;padding-top:120px;">
                    <br />
                    <button type="button" id="right"> &gt;&gt; </button><br /><br />

                    <button type="button" id="left">  &lt;&lt; </button>

                </div>
                <div id="s2" style="float: left;">
                    <div style="font-weight:900;">已选择</div>
                    <select id="select2" multiple="multiple" style="width: 220px;height: 280px;overflow-y:auto;" ondblclick="funLeft()">
                        <option th:each="item: ${assignRoleList}" th:value="${item.id}" th:text="${item.roleName}">11</option>
                    </select>
                </div>

                <div class="form-group" style="clear: left;padding-top: 20px;">
                    <button type="button" class="btn btn-sm btn-primary " onclick="add()" style="margin-left: 10px;"> 保存</button>
                    <button type="button" class="btn btn-sm btn-primary " onclick="cancel()" style="margin-left: 10px;"> 重置</button>
                    <button class="btn btn-sm btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消</button>
                </div>
                <br/>
            </div>
        </form>
    </div>
</div>
<script th:inline="javascript">
    $(function(){
        $("#right").on("click",function() {
            $("#select1 option").each(function(index, item){
                if(item.selected == true){
                    document.getElementById("select2").appendChild(item);
                }
            });
        });

        $("#left").on("click",function() {
            $("#select2 option").each(function(index, item){
                if(item.selected == true){
                    document.getElementById("select1").appendChild(item);
                }
            });
        });
    });

    function funRight() {
        $("#right").trigger("click");
    }

    function funLeft() {
        $("#left").trigger("click");
    }

    function add() {
        var roleIds = "";
        for (let i = 0; i < $("#select2 option").length; i++) {
            if (i < $("#select2 option").length - 1){
                roleIds += $("#select2 option")[i].value + ",";
            }else {
                roleIds += $("#select2 option")[i].value
            }
        }
        $("#roleIds").val(roleIds);
        document.forms.ec.submit();
    }

    function cancel() {
        location.reload();
    }
</script>
</body>
</html>

2. 给角色分配权限

2.1 显示分配权限页面

2.1.1 持久层
2.1.1.1 PermissionMapper接口

service-acl项目中创建com.atguigu.mapper.PermissionMapper接口

public interface PermissionMapper extends BaseMapper<Permission> {
    /**
     * 查询所有权限列表
     * @return
     */
    List<Permission> findAll();
}
2.1.1.2 RolePermissionMapper接口

service-acl项目中创建com.atguigu.mapper.RolePermissionMapper接口

public interface RolePermissionMapper extends BaseMapper<RolePermission> {
    /**
    * 根据roleId查询permissionId集合
    * @param roleId
    * @return
    */
    List<Long> findPermissionIdListByRoleId(Long roleId);
}
2.1.1.3 PermissionMapper.xml映射配置文件

service-acl项目中创建resources/mappers/PermissionMapper.xml映射配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.PermissionMapper">
    <sql id="columns">
        select id,parent_id,name,url,code,type,sort,create_time,update_time,is_deleted
    </sql>
    <select id="findAll" resultType="Permission">
        <include refid="columns"></include>
        from acl_permission
        where is_deleted=0
        order by sort
    </select>
</mapper>
2.1.1.4 RolePermissionMapper.xml映射配置文件

service-acl项目中创建resources/mappers/RolePermissionMapper.xml映射配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.RolePermissionMapper">
    <select id="findPermissionIdListByRoleId" resultType="long">
        select permission_id from acl_role_permission
        where role_id=#{roleId} and is_deleted=0
    </select>
</mapper>
2.1.2 业务层
2.1.2.1 PermissionService接口

service-api项目中创建com.atguigu.service.PermissionService接口

public interface PermissionService extends BaseService<Permission> {
    /**
     * 根据角色获取权限数据
     * @param roleId
     * @return
     */
    List<Map<String,Object>> findPermissionByRoleId(Long roleId);
}
2.1.2.2 PermissionServiceImpl实现类

service-acl项目中创建com.atguigu.service.impl.PermissionServiceImpl实现类

@Service(interfaceClass = PermissionService.class)
public class PermissionServiceImpl extends BaseServiceImpl<Permission> implements PermissionService {
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    @Override
    protected BaseMapper<Permission> getEntityMapper() {
        return permissionMapper;
    }
	
    @Override
    public List<Map<String, Object>> findPermissionByRoleId(Long roleId) {
        //查询所有权限信息
        List<Permission> allPermissionList = permissionMapper.findAll();
        //查询出当前角色已分配的权限id
        List<Long> assignPermissionIdList = rolePermissionMapper.findPermissionIdListByRoleId(roleId);
        //创建一个List用于存储返回数据
        List<Map<String,Object>> permissionList = new ArrayList<>();
        //遍历出所有权限信息
        for (Permission permission : allPermissionList) {
            //创建一个Map用于存储返回数据
            Map<String,Object> map = new HashMap<>();
            //判断当前权限是否已分配
            if (assignPermissionIdList.contains(permission.getId())){
                //已分配
                map.put("checked",true);
            }else {
                //未分配
                map.put("checked",false);
            }
            //设置id
            map.put("id",permission.getId());
            //设置pId
            map.put("pId",permission.getParentId());
            //设置name
            map.put("name",permission.getName());
            //设置open
            map.put("open",true);
            //将map添加到List中
            permissionList.add(map);
        }
        return permissionList;
    }
}
2.1.3 表现层

web-admin项目的com.atguigu.controller.RoleController中新增

@Reference
private PermissionService permissionService;
private static final String PAGE_ASSIGN_SHOW = "role/assignShow";

@GetMapping("/assignShow/{roleId}")
public String assignShow(@PathVariable("roleId") Long roleId,Model model){
    List<Map<String, Object>> zNodes = permissionService.findPermissionByRoleId(roleId);
    model.addAttribute("zNodes", JSON.toJSONString(zNodes));
    model.addAttribute("roleId",roleId);
    return PAGE_ASSIGN_SHOW;
}
2.1.4 前端页面

① 在web-admin项目中的templates/role/index.html页面中新增

新增标签

<a class="assgin" th:attr="data-id=${item.id}">分配权限</a>

绑定点击事件

$(".assgin").on("click",function () {
    var id = $(this).attr("data-id");
    opt.openWin("/role/assignShow/"+id,'修改',580,430);
});

② 在web-admin项目中创建templates/role/assignShow.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head th:include="common/head :: head"></head>

    <link rel="stylesheet" th:href="@{/static/js/plugins/zTree_v3/zTreeStyle.css}" type="text/css">
    <script type="text/javascript" th:src="@{/static/js/plugins/zTree_v3/jquery.ztree.core.js}"></script>
    <script type="text/javascript" th:src="@{/static/js/plugins/zTree_v3/jquery.ztree.excheck.js}"></script>
    <body class="gray-bg">
        <div class="wrapper wrapper-content animated fadeInRight">
            <div class="ibox float-e-margins">
                <div class="ibox-content" style="width: 98%;">
                    <form id="ec" th:action="@{/role/assignPermission}" method="post" class="form-horizontal">
                        <input type="hidden" name="roleId" th:value="${roleId}">
                        <input type="hidden" name="permissionIds" id="permissionIds" value="">
                        <div class="zTreeDemoBackground left">
                            <ul id="treeDemo" class="ztree"></ul>
                        </div>
                        <div class="hr-line-dashed"></div>
                        <div class="form-group posf">
                            <div class="col-sm-4 col-sm-offset-2 text-right">
                                <button class="btn btn-primary" type="button" id="button">确定</button>
                                <button class="btn btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
        <script th:inline="javascript">
            $(function () {
                // 文档地址:http://www.treejs.cn/v3/demo.php#_201
                var setting = {
                    check: {
                        enable: true
                    },
                    data: {
                        simpleData: {
                            enable: true
                        }
                    }
                };

                var zNodes = JSON.parse([[${zNodes}]]);
                //var zNodes = [[${zNodes}]];
                // var zNodes =[
                //     { id:1, pId:0, name:"随意勾选 1", open:true},
                //     { id:11, pId:1, name:"随意勾选 1-1", open:true},
                //     { id:111, pId:11, name:"随意勾选 1-1-1"},
                //     { id:112, pId:11, name:"随意勾选 1-1-2"},
                //     { id:12, pId:1, name:"随意勾选 1-2", open:true},
                //     { id:121, pId:12, name:"随意勾选 1-2-1"},
                //     { id:122, pId:12, name:"随意勾选 1-2-2"},
                //     { id:2, pId:0, name:"随意勾选 2", checked:true, open:true},
                //     { id:21, pId:2, name:"随意勾选 2-1"},
                //     { id:22, pId:2, name:"随意勾选 2-2", open:true},
                //     { id:221, pId:22, name:"随意勾选 2-2-1", checked:true},
                //     { id:222, pId:22, name:"随意勾选 2-2-2"},
                //     { id:23, pId:2, name:"随意勾选 2-3"}
                // ];

                var zTree = $.fn.zTree.init($("#treeDemo"), setting, zNodes);
                zTree.expandAll(true);
            });
        </script>
    </body>
</html>

2.2 保存分配权限

2.2.1 持久层
2.2.1.1 RolePermissionMapper接口

service-acl项目的com.atguigu.mapper.RolePermissionMapper接口中新增

/**
* 删除角色的权限
* @param roleId
* @param removePermissionIdList
*/
void removeRolePermission(@Param("roleId") Long roleId,@Param("removePermissionIdList") List<Long> removePermissionIdList);

/**
* 根据roleId和permissionId查询
* @param roleId
* @param permissionId
* @return
*/
RolePermission findByRoleIdAndPermissionId(@Param("roleId") Long roleId,@Param("permissionId") Long permissionId);
2.2.1.2 RolePermissionMapper.xml映射配置文件

service-acl项目的resources/mappers/RolePermissionMapper.xml映射配置文件中新增

<sql id="columns">
    select id,role_id,permission_id,create_time,update_time,is_deleted
</sql>
<select id="findByRoleIdAndPermissionId" resultType="RolePermission">
    <include refid="columns"></include>
    from acl_role_permission
    where role_id=#{roleId} and permission_id=#{permissionId}
</select>
<update id="removeRolePermission">
    update acl_role_permission
    set is_deleted=1
    where role_id=#{roleId}
    and permission_id in
    (
    <foreach collection="removePermissionIdList" item="permissionId" separator=",">
        #{permissionId}
    </foreach>
    )
</update>
<update id="update">
    update acl_role_permission
    <set>
        <if test="roleId != null and roleId != ''">
            role_id=#{roleId},
        </if>
        <if test="permissionId != null and permissionId != ''">
            permission_id=#{permissionId},
        </if>
        <if test="isDeleted != null and isDeleted != '' or isDeleted == 0">
            is_deleted=#{isDeleted},
        </if>
        update_time=now()
    </set>
    where id=#{id}
</update>
<insert id="insert">
    insert into acl_role_permission (id,role_id,permission_id)
    values (#{id},#{roleId},#{permissionId})
</insert>
2.2.2 业务层
2.2.2.1 PermissionService接口

service-api项目的com.atguigu.service.PermissionService接口中新增

/**
* 保存权限角色信息
* @param roleId
* @param permissionIdList
*/
void saveRolePermission(Long roleId,List<Long> permissionIdList);
2.2.2.2 PermissionServiceImpl实现类

service-acl项目中的com.atguigu.service.impl.PermissionServiceImpl实现类中新增

@Override
public void saveRolePermission(Long roleId, List<Long> permissionIdList) {
    //查询当前角色的所有permissionId
    List<Long> rolePermissionIdList = rolePermissionMapper.findPermissionIdListByRoleId(roleId);
    //找出要移除的permissionId
    List<Long> removePermissionIdList = rolePermissionIdList.stream()
        .filter(item -> !permissionIdList.contains(item))
        .collect(Collectors.toList());
    //删除角色权限
    if (removePermissionIdList != null && removePermissionIdList.size() > 0) {
        rolePermissionMapper.removeRolePermission(roleId,removePermissionIdList);
    }

    //给角色添加权限
    for (Long permissionId : permissionIdList) {
        //根据roleId和permissionId查询角色权限信息
        RolePermission rolePermission = rolePermissionMapper.findByRoleIdAndPermissionId(roleId,permissionId);
        //判断当前roleId和permissionId是否存在关联
        if (rolePermission == null) {
            rolePermission = new RolePermission();
            rolePermission.setPermissionId(permissionId);
            rolePermission.setRoleId(roleId);
            rolePermissionMapper.insert(rolePermission);
        }else {
            if (rolePermission.getIsDeleted() == 1){
                rolePermission.setIsDeleted(0);
                rolePermissionMapper.update(rolePermission);
            }
        }
    }
}
2.2.3 表现层

web-admin项目中的com.atguigu.controller.RoleController中新增

@PostMapping("/assignPermission")
public String assignPermission(@RequestParam("roleId") Long roleId,
                               @RequestParam("permissionIds") List<Long> permissionIds,
                               Model model){
    permissionService.saveRolePermission(roleId,permissionIds);
    return successPage(model,"设置角色权限成功");
}
2.2.4 前端页面

web-admin项目中的templates/role/assignShow.html页面中新增

$("#button").on("click", function () {
    var checkedNodes = zTree.getCheckedNodes();
    console.log(checkedNodes)
    var permissionIdList = [];
    for (var i = 0; i < checkedNodes.length; i++) {
        permissionIdList.push(checkedNodes[i].id)
    }
    $("#permissionIds").val(permissionIdList.join(","));
    document.forms.ec.submit();
});

三、左侧动态菜单

1. 需求和实现思路

1.1 需求

前面给用户分配了角色,给角色分配了权限,那么用户登录成功后就可以获取到左侧的动态菜单,分配了哪些菜单,那么左侧就显示哪些菜单。

当前菜单我们是直接写在frame/index.html页面的,现在我们要改成动态菜单。

权限处理过程中,系统会默认一个超级管理员,默认就有所以权限,当前默认admin账号为超级管理员。

1.2 实现思路

用户登录成功后(用户登录后续与spring security一起讲解,当前用默认用户admin),根据用户id获取角色列表,然后根据角色获取用户的菜单权限。

2. 持久层

2.1 PermissionMapper接口

service-acl项目中的com.atguigu.mapper.PermissionMapper接口中新增

/**
* 查询用户的菜单权限列表
* @param adminId
* @return
*/
List<Permission> findPermissionListByAdminId(Long adminId);
2.2 PermissionMapper.xml映射配置文件

service-acl项目中的resources/mappers/PermissionMapper.xml映射配置文件中新增

<select id="findPermissionListByAdminId" resultType="Permission">
    <include refid="columns"></include>
    from acl_permission where is_deleted=0
    and
    id in (select permission_id from acl_role_permission where is_deleted=0 and role_id in (
    select role_id from acl_admin_role where is_deleted=0 and admin_id=#{adminId}
    ))
</select>

3. 业务层

3.1 PermissionService接口

service-api项目的com.atguigu.service.PermissionService接口中新增

/**
* 查询用户的所有权限
* @param adminId
* @return
*/
List<Permission> findMenuPermissionByAdminId(Long adminId);
3.2 PermissionServiceImpl实现类

service-acl项目的com.atguigu.service.impl.PermissionServiceImpl实现类中新增

@Override
public List<Permission> findMenuPermissionByAdminId(Long adminId) {
    List<Permission> permissionList = null;
    //判断是否是超级管理员
    if (adminId == 1) {
        //超级管理员
        permissionList = permissionMapper.findAll();
    }else {
        //根据adminId查询权限列表
        permissionList = permissionMapper.findPermissionListByAdminId(adminId);
    }
    //构建树形菜单
    return PermissionHelper.build(permissionList);
}

从资源文件引入helper/PermissionHelper帮助类(可以不自己写),放到service-acl项目的com.atguigu.helper包中

public class PermissionHelper {
    public static List<Permission> build(List<Permission> originalPermissionList){
        List<Permission> treeNodes = new ArrayList<>();
        for (Permission treeNode : originalPermissionList) {
            if (treeNode.getParentId() == 0) {
                //一级菜单
                treeNode.setLevel(1);
                treeNode.setChildren(getChildren(treeNode,originalPermissionList));
                treeNodes.add(treeNode);
            }
        }

        return treeNodes;
    }

    /**
     * 获取子菜单列表
     * @return
     */
    private static List<Permission> getChildren(Permission treeNode,List<Permission> originalPermissionList) {

        List<Permission> children = new ArrayList<>();
        for (Permission childTreeNode : originalPermissionList) {
            //找出子节点
            if (treeNode.getId().longValue() == childTreeNode.getParentId().longValue()) {
                //设置子节菜单级别
                childTreeNode.setLevel(treeNode.getLevel() + 1);
                //设置子菜单的父菜单名
                childTreeNode.setParentName(treeNode.getName());
                //给子菜单设置子菜单
                childTreeNode.setChildren(getChildren(childTreeNode,originalPermissionList));

                children.add(childTreeNode);
            }
        }
        return children;
    }
}

4. 表现层

web-admin项目中修改com.atguigu.controller.IndexController类的index()方法

@Reference
private AdminService adminService;
@Reference
private PermissionService permissionService;
private static final String PAGE_INDEX = "frame/index";
@GetMapping("/")
public String index(Model model){
    //因为现在还未引入权限认证框架,没有登录,所以现在先将用户的id写死,等集成了权限认证框架之后,再获取当前登录的用户
    Long adminId = 1L;
    Admin admin = adminService.getById(adminId);
    //查询用户的权限列表
    List<Permission> permissionList = permissionService.findMenuPermissionByAdminId(adminId);
    model.addAttribute("admin",admin);
    model.addAttribute("permissionList",permissionList);
    return PAGE_INDEX;
}

5. 前端页面

修改web-admin项目的templates/frame/index.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta name="renderer" content="webkit"/>

    <title>尚好房平台管理系统</title>

    <meta name="keywords" content="尚好房平台管理系统,后台HTML,响应式后台"/>
    <meta name="description" content="尚好房平台管理系统,后台HTML,响应式后台"/>

    <!--[if lt IE 9]>
    <meta http-equiv="refresh" content="0;ie.html"/>
    <![endif]-->

    <link rel="shortcut icon" th:href="@{/static/favicon.ico}"/>
    <link th:href="@{/static/css/bootstrap.min.css(v=3.3.7)}" rel="stylesheet"/>
    <link th:href="@{/static/css/font-awesome.min.css(v=4.4.0)}" rel="stylesheet"/>
    <link th:href="@{/static/css/animate.css}" rel="stylesheet"/>
    <link th:href="@{/static/css/style.css(v=4.1.0)}" rel="stylesheet"/>
    <link th:href="@{/static/css/jquery.contextMenu.min.css}" rel="stylesheet"/>
</head>

<body class="fixed-sidebar full-height-layout gray-bg" style="overflow: hidden;">
<div id="wrapper">
    <!--左侧导航开始-->
    <nav class="navbar-default navbar-static-side" role="navigation">
        <div class="nav-close"><i class="fa fa-times-circle"></i></div>
        <div class="sidebar-collapse">
            <ul class="nav" id="side-menu">
                <li class="nav-header">
                    <div class="dropdown profile-element">
                        <span><img alt="image" class="img-circle" th:src="${admin.headUrl}"/></span>
                        <a data-toggle="dropdown" class="dropdown-toggle" href="#">
                           <span class="clear">
                              <span class="block m-t-xs"><strong class="font-bold" th:text="${admin.name}">Beaut-zihan</strong></span>
                              <span class="text-muted text-xs block">超级管理员<b class="caret"></b></span>
                           </span>
                        </a>
                        <ul class="dropdown-menu animated fadeInRight m-t-xs">
                            <li><a class="J_menuItem" href="javascript:">修改头像</a></li>
                            <li><a class="J_menuItem" href="javascript:">个人资料</a></li>
                            <li><a class="J_menuItem" href="javascript:">联系我们</a></li>
                            <li><a class="J_menuItem" href="javascript:">信箱</a></li>
                            <li class="divider"></li>
                            <li><a href="/logout">安全退出</a></li>
                        </ul>
                    </div>
                    <div class="logo-element">H+</div>
                </li>
                <li th:each="one: ${permissionList}">
                    <a href="#">
                        <i class="fa fa-home"></i>
                        <span class="nav-label" th:text="${one.name}">系统管理</span>
                        <span class="fa arrow"></span>
                    </a>
                    <ul class="nav nav-second-level collapse">
                        <li th:each="two,it: ${one.children}">
                            <a class="J_menuItem" th:href="${two.url}"
                               th:data-index="${it.count}"
                               th:text="${two.name}">用户管理</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </nav>
    <!--左侧导航结束-->
    <!--右侧部分开始-->
    <div id="page-wrapper" class="gray-bg dashbard-1">
        <div class="row border-bottom">
            <nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0;">
                <div class="navbar-header">
                    <a class="navbar-minimalize minimalize-styl-2 btn btn-primary" href="#"><i class="fa fa-bars"></i>
                    </a>
                    <form role="search" class="navbar-form-custom" method="post" action="search_results.html">
                        <div class="form-group">
                            <input type="text" placeholder="请输入您需要查找的内容 …" class="form-control" name="top-search"
                                   id="top-search"/>
                        </div>
                    </form>
                </div>
            </nav>
        </div>
        <div class="row content-tabs">
            <button class="roll-nav roll-left J_tabLeft"><i class="fa fa-backward"></i></button>
            <nav class="page-tabs J_menuTabs">
                <div class="page-tabs-content">
                    <a href="javascript:;" class="active J_menuTab" data-id="index_v1.html">首页</a>
                </div>
            </nav>
            <button class="roll-nav roll-right J_tabRight"><i class="fa fa-forward"></i></button>
            <div class="btn-group roll-nav roll-right">
                <button class="dropdown" data-toggle="dropdown">页签操作<span class="caret"></span></button>
                <ul role="menu" class="dropdown-menu dropdown-menu-right">
                    <li class="tabCloseCurrent"><a>关闭当前</a></li>
                    <li class="J_tabCloseOther"><a>关闭其他</a></li>
                    <li class="J_tabCloseAll"><a>全部关闭</a></li>
                </ul>
            </div>
            <a href="#" class="roll-nav roll-right tabReload"><i class="fa fa-refresh"></i> 刷新</a>
        </div>
        <div class="row J_mainContent" id="content-main">
        <!--指示首页右侧显示main.html的内容-->
        <iframe class="J_iframe" name="iframe0" width="100%" height="100%" th:src="@{/main}" frameborder="0"
                data-id="index_v1.html" seamless></iframe>
    </div>
        <div class="footer">
            <div class="pull-right">&copy; 2014-2015 <a href="http://www.zi-han.net/" target="_blank">zihan's blog</a>
            </div>
        </div>
    </div>
    <!--右侧部分结束-->
    <!--右侧边栏开始-->
    <!--mini聊天窗口结束-->
</div>

<!-- 全局js -->
<script th:src="@{/static/js/jquery.min.js(v=2.1.4)}"></script>
<script th:src="@{/static/js/bootstrap.min.js(v=3.3.7)}"></script>
<script th:src="@{/static/js/plugins/metisMenu/jquery.metisMenu.js}"></script>
<script th:src="@{/static/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>
<script th:src="@{/static/js/plugins/contextMenu/jquery.contextMenu.min.js}"></script>
<script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>

<!-- 自定义js -->
<script th:src="@{/static/js/hplus.js(v=4.1.0)}"></script>
<script type="text/javascript" th:src="@{/static/js/contabs.js}"></script>
</body>
</html>

6. 测试

使用当前用户adminId=1分配好角色与权限,更改当前用户adminId测试菜单

四、菜单管理(自己参考代码完成)

1. 显示菜单管理列表功能

1.1 业务层
1.1.1 PermissionService接口

service-api项目的com.atguigu.service.PermissionService接口中新增

/**
* 查询所有菜单
* @return
*/
List<Permission> findAllMenu();
1.1.2 PermissionServiceImpl实现类

service-acl项目的com.atguigu.service.impl.PermissionServiceImpl实现类中新增

@Override
public List<Permission> findAllMenu() {
    List<Permission> permissionList = permissionMapper.findAll();
    return PermissionHelper.build(permissionList);
}
1.2 表现层

web-admin项目中创建com.atguigu.controller.PermissionController

@Controller
@RequestMapping("/permission")
public class PermissionController extends BaseController {
    private final static String PAGE_INDEX = "permission/index";
    @Reference
    private PermissionService permissionService;
    
    @GetMapping
    public String index(Model model){
        List<Permission> permissionList = permissionService.findAllMenu();
        model.addAttribute("list",permissionList);

        return PAGE_INDEX;
    }
}
1.3 前端页面

web-admin项目中创建templates/permission/index.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

<head th:include="common/head :: head"></head>

<body class="gray-bg">
<form id="ec" action="#" method="post">
    <div class="wrapper wrapper-content animated fadeInRight">

        <div class="row">
            <div class="col-sm-12">
                <div class="ibox float-e-margins">
                    <div class="ibox-content">
                        <div>
                            <button type="button" class="btn btn-sm btn-primary create"
                                    th:attr="data-id=0,data-type=1,data-name='一级菜单'">新增一级菜单
                            </button>
                            <button type="button" id="loading-example-btn"
                                    onclick="javascript:window.location.reload();" class="btn btn-white btn-sm">刷新
                            </button>
                        </div>
                        <table class="table table-striped table-bordered table-hover dataTables-example">
                            <thead>
                            <tr>
                                <th>权限名称</th>
                                <th>菜单url</th>
                                <th>权限标识</th>
                                <th>类型</th>
                                <th>排序</th>
                                <th>创建时间</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody>
                            <div th:each="one: ${list}">
                                <tr class="gradeX">
                                    <td th:text="${one.name}">22</td>
                                    <td th:text="${one.url}">33</td>
                                    <td th:text="${one.code}">22</td>
                                    <td>
                                        <strong><span th:if="${one.type } eq 1" style="color: blue">菜单</span></strong>
                                        <strong><span th:if="${one.type } eq 2">按钮</span></strong>
                                    </td>
                                    <td th:text="${one.sort}">22</td>
                                    <td th:text="${#dates.format(one.createTime,'yyyy-MM-dd HH:mm:ss')}">33</td>
                                    <td class="text-center">
                                        <a class="create" th:attr="data-id=${one.id},data-type=1,data-name=${one.name}">新增二级菜单</a>
                                        <a class="edit"
                                           th:attr="data-id=${one.id}">修改</a>
                                        <a class="delete"
                                           th:attr="data-id=${one.id}">删除</a>
                                    </td>
                                </tr>
                                <div th:each="two: ${one.children}">
                                    <tr class="gradeX">
                                        <td th:text="'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' + ${two.name}">22</td>
                                        <td th:text="${two.url}">33</td>
                                        <td th:text="${two.code}">22</td>
                                        <td>
                                            <strong><span th:if="${two.type } eq 1"
                                                          style="color: blue">菜单</span></strong>
                                            <strong><span th:if="${two.type } eq 2">按钮</span></strong>
                                        </td>
                                        <td th:text="${two.sort}">22</td>
                                        <td th:text="${#dates.format(two.createTime,'yyyy-MM-dd HH:mm:ss')}">33</td>
                                        <td class="text-center">
                                            <a class="create"
                                               th:attr="data-id=${two.id},data-type=2,data-name=${two.name}">新增功能按钮</a>
                                            <a class="edit"
                                               th:attr="data-id=${two.id}">修改</a>
                                            <a class="delete"
                                               th:attr="data-id=${two.id}">删除</a>
                                        </td>
                                    </tr>
                                    <div th:each="three: ${two.children}">
                                        <tr class="gradeX">
                                            <td th:text="'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' + ${three.name}">
                                                22
                                            </td>
                                            <td th:text="${three.url}">33</td>
                                            <td th:text="${three.code}">22</td>
                                            <td>
                                                <strong><span th:if="${three.type } eq 1" style="color: blue">菜单</span></strong>
                                                <strong><span th:if="${three.type } eq 2">按钮</span></strong>
                                            </td>
                                            <td th:text="${three.sort}">22</td>
                                            <td th:text="${#dates.format(three.createTime,'yyyy-MM-dd HH:mm:ss')}">33
                                            </td>
                                            <td class="text-center">
                                                <a class="edit"
                                                   th:attr="data-id=${three.id}">修改</a>
                                                <a class="delete"
                                                   th:attr="data-id=${three.id}">删除</a>
                                            </td>
                                        </tr>
                                    </div>
                                </div>
                            </div>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>
</body>
</html>

2. 显示新增菜单页面功能

2.1 表现层

web-admin项目中的com.atguigu.controller.PermissionController类中新增

private static final String PAGE_CREATE = "permission/create";
@GetMapping("/create")
public String create(Permission permission,Model model){
    model.addAttribute("permission",permission);
    return PAGE_CREATE;
}
2.2 前端页面

web-admin项目中的templates/permission/index.html页面绑定点击事件

<script th:inline="javascript">
    $(function () {
        $(".create").on("click", function () {
            var parentId = $(this).attr("data-id");
            var type = $(this).attr("data-type");
            var parentName = $(this).attr("data-name");
            opt.openWin('/permission/create?parentId=' + parentId + '&type=' + type + '&parentName=' + parentName, '新增', 630, 430)
        });
    });
</script>

web-admin项目中创建templates/permission/create.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head th:include="common/head :: head"></head>
    <script type="text/javascript">
        $(function () {
            $('#ec').validate({
                rules: {
                    name: "required"
                },
                messages: {
                    name: "权限名称必须输入"
                },
                submitHandler: function (form) {
                    $(form).find(":submit").attr("disabled", true).text("正在提交...");
                    form.submit();
                }
            });
        });
    </script>
    <body class="gray-bg">
        <div class="wrapper wrapper-content animated fadeInRight">
            <div class="ibox float-e-margins">
                <div class="ibox-content" style="width: 98%;">
                    <form id="ec" th:action="@{/permission/save}" method="post" class="form-horizontal">
                        <input type="hidden" name="parentId" th:value="${permission.parentId}"/>
                        <input type="hidden" name="type" th:value="${permission.type}"/>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">上级权限:</label>
                            <div class="col-sm-10">
                                <input type="text" name="parentName" id="parentName" th:value="${permission.parentName}"
                                       disabled="disabled" class="form-control"/>
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">权限名称:</label>
                            <div class="col-sm-10">
                                <input type="text" name="name" id="name" value="" class="form-control"/>
                            </div>
                        </div>
                        <div class="hr-line-dashed"></div>
                        <div class="form-group" th:if="${permission.type == 1}">
                            <label class="col-sm-2 control-label">菜单url:</label>
                            <div class="col-sm-10">
                                <input type="text" name="url" id="url" class="form-control"
                                       style="width:100%;height: 50px;"></input>
                        </div>
                        </div>
                    <div class="hr-line-dashed" th:if="${permission.type == 1}"></div>
                    <div class="form-group" th:if="${permission.type == 2}">
                        <label class="col-sm-2 control-label">权限值:</label>
                        <div class="col-sm-10">
                            <input type="text" name="code" id="code" class="form-control"
                                   style="width:100%;height: 50px;"></input>
                    </div>
                </div>
                <div class="hr-line-dashed" th:if="${permission.type == 2}"></div>
                <div class="form-group">
                    <label class="col-sm-2 control-label">排序:</label>
                    <div class="col-sm-10">
                        <input type="text" name="sort" id="sort" value="1" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group posf">
                    <div class="col-sm-4 col-sm-offset-2 text-right">
                        <button class="btn btn-primary" type="submit">确定</button>
                        <button class="btn btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消
                        </button>
                    </div>
                </div>
                </form>
        </div>
        </div>
    </div>
</body>
</html>

3. 新增菜单功能

2.1 持久层
2.1.1 PermissionMapper.xml映射配置文件

service-acl项目的resources/mappers/PermissionMapper.xml映射配置文件中新增

<insert id="insert">
    insert into acl_permission (id,parent_id,name,url,code,type,sort,is_deleted)
    values (#{id},#{parentId},#{name},#{url},#{code},#{type},#{sort},0)
</insert>
2.2 表现层

web-admin项目中的com.atguigu.controller.PermissionController类中新增

@PostMapping("/save")
public String save(Permission permission,Model model){
    permissionService.insert(permission);
    return successPage(model,"添加菜单成功");
}

4. 删除菜单功能

4.1 持久层
4.1.1 PermissionMapper.xml映射配置文件

service-acl项目的resources/mappers/PermissionMapper.xml映射配置文件中新增

<update id="delete">
    update acl_permission
    set is_deleted=1
    where id=#{id}
</update>
4.2表现层

web-admin项目中的com.atguigu.controller.PermissionController类中新增

private static final String LIST_ACTION = "redirect:/permission";
@GetMapping("/delete/{id}")
public String delete(@PathVariable("id") Long id,Model model){
    permissionService.delete(id);
    return LIST_ACTION;
}
4.3 前端页面

web-admin项目中的templates/permission/index.html页面绑定点击事件

$(".delete").on("click", function () {
    var id = $(this).attr("data-id");
    opt.confirm('/permission/delete/' + id);
});

5. 显示修改菜单页面功能

5.1 持久层
5.1.1 PermissionMapper.xml映射配置文件

service-acl项目的resources/mappers/PermissionMapper.xml映射配置文件中新增

<select id="getById" resultType="Permission">
    <include refid="columns"></include>
    from acl_permission
    where id=#{id} and is_deleted=0
</select>
5.2表现层

web-admin项目中的com.atguigu.controller.PermissionController类中新增

private static final String PAGE_EDIT = "permission/edit";
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id,Model model){
    Permission permission = permissionService.getById(id);
    model.addAttribute("permission",permission);
    return PAGE_EDIT;
}
5.3 前端页面

web-admin项目中的templates/permission/index.html页面绑定点击事件

$(".edit").on("click", function () {
    var id = $(this).attr("data-id");
    opt.openWin('/permission/edit/' + id, '修改', 580, 430);
});

web-admin项目中创建templates/permission/edit.html页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="common/head :: head"></head>
<script type="text/javascript">
    $(function () {
        $('#ec').validate({
            rules: {
                name: "required"
            },
            messages: {
                name: "权限名称必须输入"
            },
            submitHandler: function (form) {
                $(form).find(":submit").attr("disabled", true).text("正在提交...");
                form.submit();
            }
        });
    });
</script>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="ibox float-e-margins">
        <div class="ibox-content" style="width: 98%;">
            <form id="ec" th:action="@{/permission/update}" method="post"
                  class="form-horizontal">
                <input type="hidden" name="id" th:value="${permission.id}"/>
                <div class="form-group">
                    <label class="col-sm-2 control-label">权限名称:</label>
                    <div class="col-sm-10">
                        <input type="text" name="name" id="name" th:value="${permission.name}" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group" th:if="${permission.type == 1}">
                    <label class="col-sm-2 control-label">菜单url:</label>
                    <div class="col-sm-10">
                        <input type="text" name="url" id="url" th:value="${permission.url}" class="form-control"
                               style="width:100%;height: 50px;"></input>
                    </div>
                </div>
                <div class="hr-line-dashed" th:if="${permission.type == 1}"></div>
                <div class="form-group" th:if="${permission.type == 2}">
                    <label class="col-sm-2 control-label">权限值:</label>
                    <div class="col-sm-10">
                        <input type="text" name="code" id="code" th:value="${permission.code}" class="form-control"
                               style="width:100%;height: 50px;"></input>
                    </div>
                </div>
                <div class="hr-line-dashed" th:if="${permission.type == 2}"></div>
                <div class="form-group">
                    <label class="col-sm-2 control-label">排序:</label>
                    <div class="col-sm-10">
                        <input type="text" name="sort" id="sort" th:value="${permission.sort}" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group posf">
                    <div class="col-sm-4 col-sm-offset-2 text-right">
                        <button class="btn btn-primary" type="submit">确定</button>
                        <button class="btn btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消
                        </button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

6. 保存修改菜单功能

6.1 持久层
6.1.1 PermissionMapper.xml映射配置文件

service-acl项目的resources/mappers/PermissionMapper.xml映射配置文件中新增

<update id="update">
    update acl_permission
    <set>
        <if test="parentId != null and perentId != ''">
            parent_id=#{parentId},
        </if>
        <if test="name != null and name != ''">
            name=#{name},
        </if>
        <if test="url != null and url != ''">
            url=#{url},
        </if>
        <if test="code != null and code != ''">
            code=#{code},
        </if>
        <if test="type != null and type != ''">
            type=#{type},
        </if>
        <if test="sort != null and sort != ''">
            sort=#{sort},
        </if>
        <if test="type != null and type != ''">
            type=#{type},
        </if>
        <if test="type != null and type != ''">
            type=#{type},
        </if>
    </set>
    where id=#{id}
</update>
6.2表现层

web-admin项目中的com.atguigu.controller.PermissionController类中新增

@PostMapping("/update")
public String update(Permission permission,Model model){
    permissionService.update(permission);
    return successPage(model,"修改菜单成功");
}

相关文章:

  • java面向对象(一)
  • Allegro Design Entry HDL(OrCAD Capture HDL)工具菜单详细介绍
  • Java 线程及线程池的创建方式
  • 分布式ID生成服务
  • Vue中的条件渲染v-if、v-show
  • 【Spring Boot】响应JSON实现原理
  • 基于51单片机交通信号灯仿真_东西管制+南北管制
  • 2022“杭电杯”中国大学生算法设计超级联赛(4)
  • AngelScript -- C++程序最好的脚本语言
  • 如何编写整洁的代码
  • leetcode: 122. 买卖股票的最佳时机II
  • 字符串习题总结3
  • Java 操作RestHighLevelClient查询详解
  • 有效 TCP RST
  • 46.全排列 | 51.N皇后
  • 时间复杂度分析经典问题——最大子序列和
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • Consul Config 使用Git做版本控制的实现
  • C学习-枚举(九)
  • Flannel解读
  • java 多线程基础, 我觉得还是有必要看看的
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • Java 网络编程(2):UDP 的使用
  • JavaScript 一些 DOM 的知识点
  • nodejs实现webservice问题总结
  • Odoo domain写法及运用
  • overflow: hidden IE7无效
  • React-生命周期杂记
  • Redis的resp协议
  • vue--为什么data属性必须是一个函数
  • 大数据与云计算学习:数据分析(二)
  • 分享一份非常强势的Android面试题
  • 解析带emoji和链接的聊天系统消息
  • 实现简单的正则表达式引擎
  • 世界上最简单的无等待算法(getAndIncrement)
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 终端用户监控:真实用户监控还是模拟监控?
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​人工智能书单(数学基础篇)
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • # 数论-逆元
  • #传输# #传输数据判断#
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • $.each()与$(selector).each()
  • (Matlab)使用竞争神经网络实现数据聚类
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (篇九)MySQL常用内置函数
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (一)认识微服务
  • .NET Reactor简单使用教程
  • .NET 简介:跨平台、开源、高性能的开发平台