1.添加模拟数据
//路径
//mock/menu.ts
export default {
'/api/getMenuData': [
{
path: '/user',
routes: [
{
path: '/user',
routes: [
{
name: 'login',
path: '/user/login',
component: './user/Login',
},
],
},
],
},
{
path: '/welcome',
name: 'welcome',
icon: 'smile',
component: './Welcome',
},
{
path: '/admin',
name: 'admin',
icon: 'crown',
access: 'canAdmin',
component: './Admin',
routes: [
{
path: '/admin/sub-page',
name: 'sub-page',
icon: 'smile',
component: './Welcome',
},
],
},
{
name: 'list.table-list',
icon: 'table',
path: '/list',
component: './TableList',
},
{
path: '/',
redirect: '/welcome',
},
{
component: './404',
}
]
};
2.添加request请求
//路径
//services/getMenu.ts
export async function getMenuData() {
return request('/api/getMenuData',{
method:'GET',
});
}
3.修改app.tsx文件
a.第一步修改getInitialState
export async function getInitialState(): Promise<{
settings?: Partial<LayoutSettings>;
currentUser?: API.CurrentUser;
menuData?: MenuDataItem[] | undefined;
fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
}> {
const fetchUserInfo = async () => {
try {
const currentUser = await queryCurrentUser();
return currentUser;
} catch (error) {
history.push(loginPath);
}
return undefined;
};
// 如果是登录页面,不执行
if (history.location.pathname !== loginPath) {
const currentUser = await fetchUserInfo();
const menuData = await getMenuData();
return {
fetchUserInfo,
currentUser,
menuData,
settings: {},
};
}
return {
fetchUserInfo,
menuData: [],
settings: {},
};
}
b.第二步修改layout
export const layout = ({initialState}: {
initialState: { settings?: LayoutSettings; currentUser?: API.CurrentUser, menuData: MenuDataItem[]; };
}): BasicLayoutProps => {
console.log(initialState)
return {
menuDataRender: (menuData) => initialState.menuData || menuData,
rightContentRender: () => <RightContent/>,
disableContentMargin: false,
footerRender: () => <Footer/>,
onPageChange: () => {
// 如果没有登录,重定向到 login
if (!initialState?.currentUser?.userid && history.location.pathname !== '/user/login') {
history.push('/user/login');
}
},
menuHeaderRender: undefined,
...initialState?.settings,
};
};
4.app.tsx 完整代码
import type {Settings as LayoutSettings, BasicLayoutProps} from '@ant-design/pro-layout';
import type {MenuDataItem} from '@ant-design/pro-layout';
import {PageLoading} from '@ant-design/pro-layout';
import {notification} from 'antd';
import type {RequestConfig} from 'umi';
import {history} from 'umi';
import RightContent from '@/components/RightContent';
import Footer from '@/components/Footer';
import type {ResponseError} from 'umi-request';
import {currentUser as queryCurrentUser, getMenuData} from './services/ant-design-pro/api';
const loginPath = '/user/login';
/** 获取用户信息比较慢的时候会展示一个 loading */
export const initialStateConfig = {
loading: <PageLoading/>,
};
/**
* @see https://umijs.org/zh-CN/plugins/plugin-initial-state
* */
export async function getInitialState(): Promise<{
settings?: Partial<LayoutSettings>;
currentUser?: API.CurrentUser;
menuData?: MenuDataItem[] | undefined;
fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
}> {
const fetchUserInfo = async () => {
try {
const currentUser = await queryCurrentUser();
return currentUser;
} catch (error) {
history.push(loginPath);
}
return undefined;
};
// 如果是登录页面,不执行
if (history.location.pathname !== loginPath) {
const currentUser = await fetchUserInfo();
const menuData = await getMenuData();
return {
fetchUserInfo,
currentUser,
menuData,
settings: {},
};
}
return {
fetchUserInfo,
menuData: [],
settings: {},
};
}
export const layout = ({initialState}: {
initialState: { settings?: LayoutSettings; currentUser?: API.CurrentUser, menuData: MenuDataItem[]; };
}): BasicLayoutProps => {
console.log(initialState)
return {
menuDataRender: (menuData) => initialState.menuData || menuData,
rightContentRender: () => <RightContent/>,
disableContentMargin: false,
footerRender: () => <Footer/>,
onPageChange: () => {
// 如果没有登录,重定向到 login
if (!initialState?.currentUser?.userid && history.location.pathname !== '/user/login') {
history.push('/user/login');
}
},
menuHeaderRender: undefined,
...initialState?.settings,
};
};
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
405: '请求方法不被允许。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
/** 异常处理程序
* @see https://beta-pro.ant.design/docs/request-cn
*/
const errorHandler = (error: ResponseError) => {
const {response} = error;
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const {status, url} = response;
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errorText,
});
}
if (!response) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
throw error;
};
// https://umijs.org/zh-CN/plugins/plugin-request
export const request: RequestConfig = {
errorHandler,
};
5.解决icon问题
a.utils下面创建fixMenuItemIcon.ts
// 路径
// src/utils/fixMenuItemIcon.ts
import React from 'react';
import {MenuDataItem} from '@ant-design/pro-layout';
import * as allIcons from '@ant-design/icons';
// FIX从接口获取菜单时icon为string类型
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;
b. app.tsx引入import fixMenuItemIcon from ‘./utils/fixMenuItemIcon’
// 引入fixMenuItemIcon
import fixMenuItemIcon from './utils/fixMenuItemIcon'
//修改 app.tsx 里的 menuDataRender
menuDataRender: () =>{
return fixMenuItemIcon(initialState.menuData)
},