制作动态菜单

动态菜单的说明

什么叫做动态菜单?动态菜单就是根据用户属于不同的角色,每个角色还有不同的菜单,左侧菜单栏会有不同的显示

前端加载流程

menu.js

修改/src/api/menu.js中的请求地址,如下所示:

// 获取菜单
export const GetMenus = params => {
  return request({
    url: '/admin/system/index/menus',
    method: 'get',
    params,
  })
}

index.js

更改src/router/index.js固定参数和异步菜单的路由加载:

// 固定菜单
export const fixedRoutes = [...home]

// 动态菜单
export const asyncRoutes = [...system]

menu.js 

修改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)
    }
}

 后端接口

SysMenuVo

定义一个实体类,来封装前端所需要的菜单数据。如下所示:

// com.atguigu.spzx.model.vo.system
@Data
public class SysMenuVo {
    
    private String title;
    private String name;
    private List<SysMenuVo> children;

}

 

IndexController

表现层代码实现:

@GetMapping("/menus")
public Result menus() {
    List<SysMenuVo> sysMenuVoList =  sysMenuService.findUserMenuList() ;
    return Result.build(sysMenuVoList , ResultCodeEnum.SUCCESS) ;
}

SysMenuService

业务层代码实现:

@Override
public List<SysMenuVo> findUserMenuList() {

    SysUser sysUser = AuthContextUtil.get();
    Long userId = sysUser.getId();          // 获取当前登录用户的id

    List<SysMenu> sysMenuList = sysMenuMapper.selectListByUserId(userId) ;

    //构建树形数据
    List<SysMenu> sysMenuTreeList = MenuHelper.buildTree(sysMenuList);
    return this.buildMenus(sysMenuTreeList);
}

// 将List<SysMenu>对象转换成List<SysMenuVo>对象
private List<SysMenuVo> buildMenus(List<SysMenu> menus) {

    List<SysMenuVo> sysMenuVoList = new LinkedList<SysMenuVo>();
    for (SysMenu sysMenu : menus) {
        SysMenuVo sysMenuVo = new SysMenuVo();
        sysMenuVo.setTitle(sysMenu.getTitle());
        sysMenuVo.setName(sysMenu.getComponent());
        List<SysMenu> children = sysMenu.getChildren();
        if (!CollectionUtils.isEmpty(children)) {
            sysMenuVo.setChildren(buildMenus(children));
        }
        sysMenuVoList.add(sysMenuVo);
    }
    return sysMenuVoList;
}

 

SysMenuMapper

持久层代码实现:

@Mapper
public interface SysMenuMapper {
    public abstract List<SysMenu> selectListByUserId(Long userId);
}

 

SysMenuMapper.xml

在SysMenuMapper.xml文件中添加如下的sql语句

<select id="selectListByUserId" resultMap="sysMenuMap">
    select * from sys_menu sm where sm.id in (
    select DISTINCT srm.menu_id from sys_role_menu srm where srm.role_id in
    (
    	select sr.id from sys_role sr where sr.id in
    		(select sur.role_id from sys_user_role sur where sur.user_id = #{userId} and is_deleted = 0)
    	and sr.is_deleted = 0
    )
    	and srm.is_deleted = 0
    ) and sm.is_deleted = 0
</select>
        
👆上面的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;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大磊程序员(“hello world”)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值