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

2284

被折叠的 条评论
为什么被折叠?



