这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战
前言
本节介绍RuoYi-Vue的ruoyi-admin模块中的菜单信息模块SysMenuController 部分的代码,
今天我们讲解一下菜单这里的逻辑,RuoYi-Vue使用的菜单接口比较简单,其中比较有意思的是加载对应角色菜单列表树的接口
对应代码
/**
* 加载对应角色菜单列表树
*/
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
List<SysMenu> menus = menuService.selectMenuList(getUserId());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
ajax.put("menus", menuService.buildMenuTreeSelect(menus));
return ajax;
}
checkedKeys的获取
这个checkedKeys是用来向前端返回对应角色的所有已经选择的菜单项的Id的数据,为了和前端的树形列表相匹配,可以看到在返回的checkedKeys的数组中并没有对应的parentId的(比如我们返回的Menu是有123的,但是checkedKeys里面并没有对应的父Id)这是因为若依默认选中了父子联动的缘故,如果我们返回了父Id,那么对应的所有的子Id都会被选中,其结果就是会导致本来没有被选中的子菜单也会被选中,这时候如果我们保存,那么对应的权限肯定就有了问题。
数据库接口层中我们可以看到这里是有一个参数为
menuCheckStrictly,代表菜单树选择项是否关联显示,当然前端传不进来,但是我们可以参考一下。
/**
* 根据角色ID查询菜单树信息
*
* @param roleId 角色ID
* @param menuCheckStrictly 菜单树选择项是否关联显示
* @return 选中菜单列表
*/
public List<Integer> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
对应的数据库代码为
<select id="selectMenuListByRoleId" resultType="Integer">
select m.menu_id
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
where rm.role_id = #{roleId}
<if test="menuCheckStrictly">
and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
</if>
order by m.parent_id, m.order_num
</select>
通过是否传入了menuCheckStrictly参数,我们可以控制是否展示所有的父Id
menus参数的获取
要构建前端所需要下拉树结构,需要我们使用递归来进行父级和子级的整合。
/**
* 构建前端所需要树结构
*
* @param menus 菜单列表
* @return 树结构列表
*/
@Override
public List<SysMenu> buildMenuTree(List<SysMenu> menus)
{
List<SysMenu> returnList = new ArrayList<SysMenu>();
List<Long> tempList = new ArrayList<Long>();
for (SysMenu dept : menus)
{
tempList.add(dept.getMenuId());
}
for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
{
SysMenu menu = (SysMenu) iterator.next();
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(menu.getParentId()))
{
recursionFn(menus, menu);
returnList.add(menu);
}
}
if (returnList.isEmpty())
{
returnList = menus;
}
return returnList;
}
这里的hasChild判断是否有子节点,总感觉不是很优雅。
在想是否能提个push,哈哈