blob: c5a779fe6cfae4454bf059eebaf422c3f5a54226 [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
zhaoyumaof8f81842025-06-09 00:00:46 +080064export const layout: ({initialState, setInitialState}: { initialState: any; setInitialState: any }) => any = ({ initialState, setInitialState }) => {
Jiarenxiang38dcb052025-03-13 16:40:09 +080065 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 ],
Jiarenxiang38dcb052025-03-13 16:40:09 +0800118 menuHeaderRender: undefined,
119 // 自定义 403 页面
120 // unAccessible: <div>unAccessible</div>,
121 // 增加一个 loading 的状态
122 childrenRender: (children) => {
123 // if (initialState?.loading) return <PageLoading />;
124 return (
125 <>
126 {children}
127 <SettingDrawer
128 disableUrlParams
129 enableDarkTheme
130 settings={initialState?.settings}
131 onSettingChange={(settings) => {
132 setInitialState((preInitialState) => ({
133 ...preInitialState,
134 settings,
135 }));
136 }}
137 />
138 </>
139 );
140 },
141 ...initialState?.settings,
142 };
143};
144
145export async function onRouteChange({ clientRoutes, location }) {
146 const menus = getRemoteMenu();
147 // console.log('onRouteChange', clientRoutes, location, menus);
148 if(menus === null && location.pathname !== PageEnum.LOGIN) {
149 console.log('refresh')
150 history.go(0);
151 }
152}
153
154// export function patchRoutes({ routes, routeComponents }) {
155// console.log('patchRoutes', routes, routeComponents);
156// }
157
158
159export async function patchClientRoutes({ routes }) {
160 // console.log('patchClientRoutes', routes);
161 patchRouteWithRemoteMenus(routes);
162}
163
164export function render(oldRender: () => void) {
165 // console.log('render get routers', oldRender)
166 const token = getAccessToken();
167 if(!token || token?.length === 0) {
168 oldRender();
169 return;
170 }
171 getRoutersInfo().then(res => {
172 setRemoteMenu(res);
173 oldRender()
174 });
175}
176
177/**
178 * @name request 配置,可以配置错误处理
179 * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
180 * @doc https://umijs.org/docs/max/request#配置
181 */
182const checkRegion = 5 * 60 * 1000;
183
184export const request = {
185 ...errorConfig,
186 requestInterceptors: [
187 (url: any, options: { headers: any }) => {
188 const headers = options.headers ? options.headers : [];
189 console.log('request ====>:', url);
190 const authHeader = headers['Authorization'];
191 const isToken = headers['isToken'];
192 if (!authHeader && isToken !== false) {
193 const expireTime = getTokenExpireTime();
194 if (expireTime) {
195 const left = Number(expireTime) - new Date().getTime();
196 const refreshToken = getRefreshToken();
197 if (left < checkRegion && refreshToken) {
198 if (left < 0) {
199 clearSessionToken();
200 }
201 } else {
202 const accessToken = getAccessToken();
203 if (accessToken) {
204 headers['Authorization'] = `Bearer ${accessToken}`;
205 }
206 }
207 } else {
208 clearSessionToken();
209 }
210 }
211 return { url, options };
212 },
213 ],
214 responseInterceptors: [
215 // (response) =>
216 // {
217 // // // 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到
218 // // const { data = {} as any, config } = response;
219 // // // do something
220 // // console.log('data: ', data)
221 // // console.log('config: ', config)
222 // return response
223 // },
224 ],
225};