什么叫做动态菜单?动态菜单就是根据用户属于不同的角色,每个角色还有不同的菜单,左侧菜单栏会有不同的显示
修改/src/api/menu.js中的请求地址,如下所示:
// 获取菜单
export const GetMenus = params => {
return request({
url: '/admin/system/index/menus',
method: 'get',
params,
})
}
更改src/router/index.js固定参数和异步菜单的路由加载:
// 固定菜单
export const fixedRoutes = [...home]
// 动态菜单
export const asyncRoutes = [...system]
修改pinia/modules/menu.js中的generateMenus方法,注释掉方式一菜单加载,打开方式二菜单加载。
const generateMenus = async () => {
// // 方式一:只有固定菜单
// const menus = getFilterMenus(fixedRoutes)
// setMenus(menus)
// 方式二:有动态菜单
// 从后台获取菜单
const { code, data } = await GetMenus()
if (+code === 200) {
// 添加路由之前先删除所有动态路由
asyncRoutes.forEach(item => {
router.removeRoute(item.name)
})
// 过滤出需要添加的动态路由
const filterRoutes = getFilterRoutes(asyncRoutes, data)
filterRoutes.forEach(route => router.addRoute(route))
// 生成菜单
const menus = getFilterMenus([...fixedRoutes, ...filterRoutes])
setMenus(menus)
}
}
定义一个实体类,来封装前端所需要的菜单数据。如下所示:
// com.atguigu.spzx.model.vo.system
@Data
public class SysMenuVo {
private String title;
private String name;
private List children;
}
表现层代码实现:
@GetMapping("/menus")
public Result menus() {
List sysMenuVoList = sysMenuService.findUserMenuList() ;
return Result.build(sysMenuVoList , ResultCodeEnum.SUCCESS) ;
}
业务层代码实现:
@Override
public List findUserMenuList() {
SysUser sysUser = AuthContextUtil.get();
Long userId = sysUser.getId(); // 获取当前登录用户的id
List sysMenuList = sysMenuMapper.selectListByUserId(userId) ;
//构建树形数据
List sysMenuTreeList = MenuHelper.buildTree(sysMenuList);
return this.buildMenus(sysMenuTreeList);
}
// 将List对象转换成List对象
private List buildMenus(List menus) {
List sysMenuVoList = new LinkedList();
for (SysMenu sysMenu : menus) {
SysMenuVo sysMenuVo = new SysMenuVo();
sysMenuVo.setTitle(sysMenu.getTitle());
sysMenuVo.setName(sysMenu.getComponent());
List children = sysMenu.getChildren();
if (!CollectionUtils.isEmpty(children)) {
sysMenuVo.setChildren(buildMenus(children));
}
sysMenuVoList.add(sysMenuVo);
}
return sysMenuVoList;
}
持久层代码实现:
@Mapper
public interface SysMenuMapper {
public abstract List selectListByUserId(Long userId);
}
在SysMenuMapper.xml文件中添加如下的sql语句
上面的sql可以优化
SELECT DISTINCT
sm.*
FROM
sys_menu sm
JOIN
sys_role_menu srm ON sm.id = srm.menu_id
JOIN
sys_user_role sur ON srm.role_id = sur.role_id
WHERE
sur.user_id = 1
AND sm.is_deleted = 0
AND srm.is_deleted = 0
AND sur.is_deleted = 0;