ant design pro v5 动态菜单

本文档详细介绍了如何在Ant Design Pro V5中实现动态菜单的配置,包括添加获取菜单的API请求,修改app.tsx文件以处理菜单数据,登录流程中的用户信息和菜单获取,解决Icon显示问题,以及菜单JSON格式的要求和路由对应规则。

1.添加获取菜单请求(services/api.ts)

export async function currentUserMenus() {
 return request<MenuDataItem[]>('/api/org/getUserMenus', {
 method: 'GET',
  });
}

2.修改app.tsx文件

1)修改getInitialState方法

export async function getInitialState(): Promise<{
 settings?: Partial<LayoutSettings>;
 currentUser?: API.CurrentUser;
 menuData?: MenuDataItem[] | undefined;
 fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
 fetchUserMenus?: () => Promise<MenuDataItem[] | undefined>;
}> {
 const fetchUserInfo = async () => {
 try {
 const currentUser = await queryCurrentUser();
 return currentUser;
    } catch (error) {
 history.push(loginPath);
    }
 return undefined;
  };
 const fetchUserMenus = async () => {
 try {
 const menuData = await queryCurrentUserMenus();
 return menuData;
    } catch (error) {
 history.push(loginPath);
    }
 return undefined;
  };
 // 如果是登录页面,不执行
 if (history.location.pathname !== loginPath) {
 const token =  localStorage.getItem('userToken')
 if (!token) {
 history.push(loginPath);
 return {
 fetchUserInfo,
 fetchUserMenus,
 menuData: [],
 settings: {},
      };
    }

 const currentUser = await fetchUserInfo();
 const menuData = await fetchUserMenus();
 return {
 fetchUserInfo,
 fetchUserMenus,
 currentUser,
 menuData,
 settings: {},
    };
  }
 return {
 fetchUserInfo,
 fetchUserMenus,
 menuData: [],
 settings: {},
  };
}

2)修改layout方法

export const layout: RunTimeLayoutConfig = ({ initialState }) => {
 return {
 rightContentRender: () => <RightContent />,
 disableContentMargin: false,
 waterMarkProps: {
 content: initialState?.currentUser?.name,
    },
 footerRender: () => <Footer />,
 onPageChange: () => {
 console.log('onPageChange')
 const { location } = history;
 // 如果没有登录,重定向到 login
 const token =  localStorage.getItem('userToken')
 if (!token && location.pathname !== loginPath) {
 history.push(loginPath);
      }
    },
 links: isDev
      ? [
 <Link to="/umi/plugin/openapi" target="_blank">
 <LinkOutlined />
 <span>openAPI 文档</span>
 </Link>,
 <Link to="/~docs">
 <BookOutlined />
 <span>业务组件文档</span>
 </Link>,
        ]
      : [],
 menuHeaderRender: undefined,
 // menuDataRender: (menuData) => initialState?.menuData || menuData,
 menuDataRender: () =>{
 return fixMenuItemIcon(initialState?.menuData)
    },
 // menuDataRender: () => menuDataRender(),
 // 自定义 403 页面
 // unAccessible: <div>unAccessible</div>,
    ...initialState?.settings,
  };
};

3.登录模块分为三个步骤

  • 登录,登录成功后获取用户信息并保存token
const handleSubmit = async (values: API.LoginParams) => {
 setSubmitting(true);
 try {
 // 登录
 const msg = await login({ ...values });
 if (msg.data.state === 'ok') {
 message.success('登录成功!');
 localStorage.setItem('userToken',msg.data.token)
 await fetchUserInfo();
 goto();
 return;
      }
 // 如果失败去设置用户错误信息
 setUserLoginState(msg);
    } catch (error) {
 message.error('登录失败,请重试!');
    }
 setSubmitting(false);
  };
  • 获取用户信息和用户菜单
const fetchUserInfo = async () => {
 const userInfo = await initialState?.fetchUserInfo?.();
 // 有用户信息 设置初始参数
 if (userInfo) {
 const menus = await initialState?.fetchUserMenus?.();
 setInitialState({
        ...initialState,
 currentUser: userInfo,
 menuData : menus,
      });
    }
  };

4.解决Icon显示问题

创建fixMenuItemIcon.ts文件

import React from 'react';
import type {MenuDataItem} from '@ant-design/pro-layout';
import * as allIcons from '@ant-design/icons';

const fixMenuItemIcon = (menus: MenuDataItem[], iconType = 'Outlined'): MenuDataItem[] => {
 menus.forEach((item) => {
 const {icon, children} = item
 if (typeof icon === 'string') {
 const fixIconName = icon.slice(0, 1).toLocaleUpperCase() + icon.slice(1) + iconType
 // eslint-disable-next-line no-param-reassign
 item.icon = React.createElement(allIcons[fixIconName] || allIcons[icon])
    }
 // eslint-disable-next-line no-param-reassign,@typescript-eslint/no-unused-expressions
 children && children.length > 0 ? item.children = fixMenuItemIcon(children) : null
  });
 return menus
};

export default fixMenuItemIcon;

5.备注

菜单返回json格式。字段只需要有path和name就可以了。

path地址需要在路由里面有对应的地址

[
  {
    "icon": "smile",
    "path": "/system",
    "name": "system",
    "children": [
      {
        "icon": null,
        "path": "/system/empty",
        "name": "empty"
      },
      {
        "icon": "smile",
        "path": "/system/rolelist",
        "name": "rolemanage"
      }
    ]
  }
]

路由文件routes.tsx

export default [
  {
 path: '/user',
 layout: false,
 routes: [
      {
 path: '/user',
 routes: [
          {
 name: 'login',
 path: '/user/login',
 component: './user/Login',
          },
        ],
      },
    ],
  },
  {
 path: '/welcome',
 name: 'welcome',
 icon: 'smile',
 component: './welcome',
  },
  {
 path: '/system',
 routes: [
      {
 icon: 'smile',
 path: '/system/empty',
 component: './sysManage/Empty',
      },
      {
 icon: 'smile',
 path: '/system/rolelist',
 component: './sysManage/RoleManage',
      },
    ],
  },
  {
 path: '/',
 redirect: '/welcome',
  },
  {
 component: './404',
  },
];
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值