Ant Design Pro 实现动态菜单

动态获取菜单

先看实现效果

hmgif2

官方提供的动态菜单实现方法:菜单的高级用法 - Ant Design Pro

前提说明:实现动态路由时,所有的路由都必须提前在 config/routes.ts 中注册好,如果动态返回了 routes.ts 中不存在的路由信息,页面将会无法访问,具体问题可参考(Issue #11137)。只能动态返回 routes.ts 内的数据

修改 app.tsx 的 layout 方法,在配置中添加 menu 属性即可实现动态菜单

// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
  return {
    // ... 省略其他代码
    menu: {
      // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request
      params: {
        userId: initialState?.currentUser?.userId,
        roleIds: initialState?.currentUser?.sysRoleList?.map((item) => item.roleId),
      },
      request: async (params, defaultMenuData) => {
        // 调用接口获取菜单数据
        let { data } = await getRoleMenuFun(params.roleIds);

        if (data.length > 0) {
          return data;
        }
        return defaultMenuData;
      },
    },
    // 手动映射icon
    menuDataRender: (menuData) => fixMenuItemIcon(menuData),
  };
};

接口返回的data菜单格式和 config/routes.ts 中配置的保持一致,更多配置可以参考:Pro 的 Layout 组件 - Ant Design Pro

返回内容示例:

{
  path: '/user/login',
  layout: false, // 页面是否在layout布局样式下显示,设置成false会单独显示
  hideInMenu: true, // 是否隐藏菜单,这里只是设置不在左侧菜单列表中显示,仍可以访问
  name: '登录',
  component: './Login',
},
{
  path: '/welcome',
  name: '欢迎',
  icon: 'smile',
  component: './Welcome',
},
{
  path: 'test',
  name: '一级菜单',
  routes: [
    {
      path: 'test1',
      name: '二级菜单1',
      routes: [
        {
          path: 'test1-1',
          name: '三级菜单1-1',
          component: './Test',
        },
        {
          path: 'test1-2',
          name: '三级菜单1-2',
          component: './Test',
        },
      ],
    },
    {
      path: 'test2',
      name: '二级菜单2',
      component: './Test',
    },
  ],
},

当我们使用了动态返回的菜单时,图标就不出现了,这时需要手动映射icon图标,可参考这里

添加 src/utils/fixMenuItemIcon.ts 文件

import React from 'react';
import * as allIcons from '@ant-design/icons';

// FIX从接口获取菜单时icon为string类型
const fixMenuItemIcon = (menus, iconType = 'Outlined') => {
  menus.forEach((item) => {
    const { icon, children } = item;
    if (typeof icon === 'string') {
      let fixIconName = icon.slice(0, 1).toLocaleUpperCase() + icon.slice(1) + iconType;
      console.log(fixIconName, 'fixIconName');
      item.icon = React.createElement(allIcons[fixIconName] || allIcons[icon]);
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions
    children && children.length > 0 ? (item.children = fixMenuItemIcon(children)) : null;
  });
  return menus;
};

export default fixMenuItemIcon;

这里二级菜单的图标没有,官方是这样解释的

最终实现的效果,先给管理员和普通和用户分配不同的菜单

image-20240521171759248

image-20240521171823525

切换登录不同角色的用户,会显示不同的菜单

hmgif2

实现过程中遇到的问题以及解决方法

实现源码

https://gitee.com/szxio/user-center

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值