blob: 38f76b4a98d80348f7afdd25cfb65bc54fd455f7 [file] [log] [blame]
Jiarenxiang38dcb052025-03-13 16:40:09 +08001import { Footer, Question, SelectLang, AvatarDropdown, AvatarName } from '@/components';
2import { LinkOutlined } from '@ant-design/icons';
3import type { Settings as LayoutSettings } from '@ant-design/pro-components';
4import { SettingDrawer } from '@ant-design/pro-components';
5import type { RunTimeLayoutConfig } from '@umijs/max';
6import { history, Link } from '@umijs/max';
7import defaultSettings from '../config/defaultSettings';
8import { errorConfig } from './requestErrorConfig';
9import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access';
10import { getRemoteMenu, getRoutersInfo, getUserInfo, patchRouteWithRemoteMenus, setRemoteMenu } from './services/session';
11import { PageEnum } from './enums/pagesEnums';
12
13
14const isDev = process.env.NODE_ENV === 'development';
15
16
17
18/**
19 * @see https://umijs.org/zh-CN/plugins/plugin-initial-state
20 * */
21export async function getInitialState(): Promise<{
22 settings?: Partial<LayoutSettings>;
23 currentUser?: API.CurrentUser;
24 loading?: boolean;
25 fetchUserInfo?: () => Promise<API.CurrentUser | undefined>;
26}> {
27 const fetchUserInfo = async () => {
28 try {
29 const response = await getUserInfo({
30 skipErrorHandler: true,
31 });
32 if (response.user.avatar === '') {
33 response.user.avatar =
34 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png';
35 }
36 return {
37 ...response.user,
38 permissions: response.permissions,
39 roles: response.roles,
40 } as API.CurrentUser;
41 } catch (error) {
42 console.log(error);
43 history.push(PageEnum.LOGIN);
44 }
45 return undefined;
46 };
47 // 如果不是登录页面,执行
48 const { location } = history;
49 if (location.pathname !== PageEnum.LOGIN) {
50 const currentUser = await fetchUserInfo();
51 return {
52 fetchUserInfo,
53 currentUser,
54 settings: defaultSettings as Partial<LayoutSettings>,
55 };
56 }
57 return {
58 fetchUserInfo,
59 settings: defaultSettings as Partial<LayoutSettings>,
60 };
61}
62
63// ProLayout 支持的api https://procomponents.ant.design/components/layout
64export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
65 return {
66 actionsRender: () => [<Question key="doc" />, <SelectLang key="SelectLang" />],
67 avatarProps: {
68 src: initialState?.currentUser?.avatar,
69 title: <AvatarName />,
70 render: (_, avatarChildren) => {
71 return <AvatarDropdown menu="True">{avatarChildren}</AvatarDropdown>;
72 },
73 },
74 waterMarkProps: {
75 // content: initialState?.currentUser?.nickName,
76 },
77 menu: {
78 locale: false,
79 // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request
80 params: {
81 userId: initialState?.currentUser?.userId,
82 },
83 request: async () => {
84 if (!initialState?.currentUser?.userId) {
85 return [];
86 }
87 return getRemoteMenu();
88 },
89 },
90 footerRender: () => <Footer />,
91 onPageChange: () => {
92 const { location } = history;
93 // 如果没有登录,重定向到 login
94 if (!initialState?.currentUser && location.pathname !== PageEnum.LOGIN) {
95 history.push(PageEnum.LOGIN);
96 }
97 },
98 layoutBgImgList: [
99 {
100 src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/D2LWSqNny4sAAAAAAAAAAAAAFl94AQBr',
101 left: 85,
102 bottom: 100,
103 height: '303px',
104 },
105 {
106 src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/C2TWRpJpiC0AAAAAAAAAAAAAFl94AQBr',
107 bottom: -68,
108 right: -45,
109 height: '303px',
110 },
111 {
112 src: 'https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/F6vSTbj8KpYAAAAAAAAAAAAAFl94AQBr',
113 bottom: 0,
114 left: 0,
115 width: '331px',
116 },
117 ],
118 links: isDev
119 ? [
120 <Link key="openapi" to="/umi/plugin/openapi" target="_blank">
121 <LinkOutlined />
122 <span>OpenAPI 文档</span>
123 </Link>,
124 ]
125 : [],
126 menuHeaderRender: undefined,
127 // 自定义 403 页面
128 // unAccessible: <div>unAccessible</div>,
129 // 增加一个 loading 的状态
130 childrenRender: (children) => {
131 // if (initialState?.loading) return <PageLoading />;
132 return (
133 <>
134 {children}
135 <SettingDrawer
136 disableUrlParams
137 enableDarkTheme
138 settings={initialState?.settings}
139 onSettingChange={(settings) => {
140 setInitialState((preInitialState) => ({
141 ...preInitialState,
142 settings,
143 }));
144 }}
145 />
146 </>
147 );
148 },
149 ...initialState?.settings,
150 };
151};
152
153export async function onRouteChange({ clientRoutes, location }) {
154 const menus = getRemoteMenu();
155 // console.log('onRouteChange', clientRoutes, location, menus);
156 if(menus === null && location.pathname !== PageEnum.LOGIN) {
157 console.log('refresh')
158 history.go(0);
159 }
160}
161
162// export function patchRoutes({ routes, routeComponents }) {
163// console.log('patchRoutes', routes, routeComponents);
164// }
165
166
167export async function patchClientRoutes({ routes }) {
168 // console.log('patchClientRoutes', routes);
169 patchRouteWithRemoteMenus(routes);
170}
171
172export function render(oldRender: () => void) {
173 // console.log('render get routers', oldRender)
174 const token = getAccessToken();
175 if(!token || token?.length === 0) {
176 oldRender();
177 return;
178 }
179 getRoutersInfo().then(res => {
180 setRemoteMenu(res);
181 oldRender()
182 });
183}
184
185/**
186 * @name request 配置,可以配置错误处理
187 * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
188 * @doc https://umijs.org/docs/max/request#配置
189 */
190const checkRegion = 5 * 60 * 1000;
191
192export const request = {
193 ...errorConfig,
194 requestInterceptors: [
195 (url: any, options: { headers: any }) => {
196 const headers = options.headers ? options.headers : [];
197 console.log('request ====>:', url);
198 const authHeader = headers['Authorization'];
199 const isToken = headers['isToken'];
200 if (!authHeader && isToken !== false) {
201 const expireTime = getTokenExpireTime();
202 if (expireTime) {
203 const left = Number(expireTime) - new Date().getTime();
204 const refreshToken = getRefreshToken();
205 if (left < checkRegion && refreshToken) {
206 if (left < 0) {
207 clearSessionToken();
208 }
209 } else {
210 const accessToken = getAccessToken();
211 if (accessToken) {
212 headers['Authorization'] = `Bearer ${accessToken}`;
213 }
214 }
215 } else {
216 clearSessionToken();
217 }
218 }
219 return { url, options };
220 },
221 ],
222 responseInterceptors: [
223 // (response) =>
224 // {
225 // // // 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到
226 // // const { data = {} as any, config } = response;
227 // // // do something
228 // // console.log('data: ', data)
229 // // console.log('config: ', config)
230 // return response
231 // },
232 ],
233};