| import { Footer, Question, SelectLang, AvatarDropdown, AvatarName } from '@/components'; |
| import { LinkOutlined } from '@ant-design/icons'; |
| import type { Settings as LayoutSettings } from '@ant-design/pro-components'; |
| import { SettingDrawer } from '@ant-design/pro-components'; |
| import type { RunTimeLayoutConfig } from '@umijs/max'; |
| import { history, Link } from '@umijs/max'; |
| import defaultSettings from '../config/defaultSettings'; |
| import { errorConfig } from './requestErrorConfig'; |
| import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access'; |
| import { getRemoteMenu, getRoutersInfo, getUserInfo, patchRouteWithRemoteMenus, setRemoteMenu } from './services/session'; |
| import { PageEnum } from './enums/pagesEnums'; |
| |
| |
| const isDev = process.env.NODE_ENV === 'development'; |
| |
| |
| |
| /** |
| * @see https://umijs.org/zh-CN/plugins/plugin-initial-state |
| * */ |
| export async function getInitialState(): Promise<{ |
| settings?: Partial<LayoutSettings>; |
| currentUser?: API.CurrentUser; |
| loading?: boolean; |
| fetchUserInfo?: () => Promise<API.CurrentUser | undefined>; |
| }> { |
| const fetchUserInfo = async () => { |
| try { |
| const response = await getUserInfo({ |
| skipErrorHandler: true, |
| }); |
| if (response.user.avatar === '') { |
| response.user.avatar = |
| 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'; |
| } |
| return { |
| ...response.user, |
| permissions: response.permissions, |
| roles: response.roles, |
| } as API.CurrentUser; |
| } catch (error) { |
| console.log(error); |
| history.push(PageEnum.LOGIN); |
| } |
| return undefined; |
| }; |
| // 如果不是登录页面,执行 |
| const { location } = history; |
| if (location.pathname !== PageEnum.LOGIN) { |
| const currentUser = await fetchUserInfo(); |
| return { |
| fetchUserInfo, |
| currentUser, |
| settings: defaultSettings as Partial<LayoutSettings>, |
| }; |
| } |
| return { |
| fetchUserInfo, |
| settings: defaultSettings as Partial<LayoutSettings>, |
| }; |
| } |
| |
| // ProLayout 支持的api https://procomponents.ant.design/components/layout |
| export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => { |
| return { |
| actionsRender: () => [<Question key="doc" />, <SelectLang key="SelectLang" />], |
| avatarProps: { |
| src: initialState?.currentUser?.avatar, |
| title: <AvatarName />, |
| render: (_, avatarChildren) => { |
| return <AvatarDropdown menu="True">{avatarChildren}</AvatarDropdown>; |
| }, |
| }, |
| waterMarkProps: { |
| // content: initialState?.currentUser?.nickName, |
| }, |
| menu: { |
| locale: false, |
| // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request |
| params: { |
| userId: initialState?.currentUser?.userId, |
| }, |
| request: async () => { |
| if (!initialState?.currentUser?.userId) { |
| return []; |
| } |
| return getRemoteMenu(); |
| }, |
| }, |
| footerRender: () => <Footer />, |
| onPageChange: () => { |
| const { location } = history; |
| // 如果没有登录,重定向到 login |
| if (!initialState?.currentUser && location.pathname !== PageEnum.LOGIN) { |
| history.push(PageEnum.LOGIN); |
| } |
| }, |
| layoutBgImgList: [ |
| { |
| src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr', |
| left: 85, |
| bottom: 100, |
| height: '303px', |
| }, |
| { |
| src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr', |
| bottom: -68, |
| right: -45, |
| height: '303px', |
| }, |
| { |
| src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr', |
| bottom: 0, |
| left: 0, |
| width: '331px', |
| }, |
| ], |
| links: isDev |
| ? [ |
| <Link key="openapi" to="/umi/plugin/openapi" target="_blank"> |
| <LinkOutlined /> |
| <span>OpenAPI 文档</span> |
| </Link>, |
| ] |
| : [], |
| menuHeaderRender: undefined, |
| // 自定义 403 页面 |
| // unAccessible: <div>unAccessible</div>, |
| // 增加一个 loading 的状态 |
| childrenRender: (children) => { |
| // if (initialState?.loading) return <PageLoading />; |
| return ( |
| <> |
| {children} |
| <SettingDrawer |
| disableUrlParams |
| enableDarkTheme |
| settings={initialState?.settings} |
| onSettingChange={(settings) => { |
| setInitialState((preInitialState) => ({ |
| ...preInitialState, |
| settings, |
| })); |
| }} |
| /> |
| </> |
| ); |
| }, |
| ...initialState?.settings, |
| }; |
| }; |
| |
| export async function onRouteChange({ clientRoutes, location }) { |
| const menus = getRemoteMenu(); |
| // console.log('onRouteChange', clientRoutes, location, menus); |
| if(menus === null && location.pathname !== PageEnum.LOGIN) { |
| console.log('refresh') |
| history.go(0); |
| } |
| } |
| |
| // export function patchRoutes({ routes, routeComponents }) { |
| // console.log('patchRoutes', routes, routeComponents); |
| // } |
| |
| |
| export async function patchClientRoutes({ routes }) { |
| // console.log('patchClientRoutes', routes); |
| patchRouteWithRemoteMenus(routes); |
| } |
| |
| export function render(oldRender: () => void) { |
| // console.log('render get routers', oldRender) |
| const token = getAccessToken(); |
| if(!token || token?.length === 0) { |
| oldRender(); |
| return; |
| } |
| getRoutersInfo().then(res => { |
| setRemoteMenu(res); |
| oldRender() |
| }); |
| } |
| |
| /** |
| * @name request 配置,可以配置错误处理 |
| * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 |
| * @doc https://umijs.org/docs/max/request#配置 |
| */ |
| const checkRegion = 5 * 60 * 1000; |
| |
| export const request = { |
| ...errorConfig, |
| requestInterceptors: [ |
| (url: any, options: { headers: any }) => { |
| const headers = options.headers ? options.headers : []; |
| console.log('request ====>:', url); |
| const authHeader = headers['Authorization']; |
| const isToken = headers['isToken']; |
| if (!authHeader && isToken !== false) { |
| const expireTime = getTokenExpireTime(); |
| if (expireTime) { |
| const left = Number(expireTime) - new Date().getTime(); |
| const refreshToken = getRefreshToken(); |
| if (left < checkRegion && refreshToken) { |
| if (left < 0) { |
| clearSessionToken(); |
| } |
| } else { |
| const accessToken = getAccessToken(); |
| if (accessToken) { |
| headers['Authorization'] = `Bearer ${accessToken}`; |
| } |
| } |
| } else { |
| clearSessionToken(); |
| } |
| } |
| return { url, options }; |
| }, |
| ], |
| responseInterceptors: [ |
| // (response) => |
| // { |
| // // // 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到 |
| // // const { data = {} as any, config } = response; |
| // // // do something |
| // // console.log('data: ', data) |
| // // console.log('config: ', config) |
| // return response |
| // }, |
| ], |
| }; |