2025-03-28 15:30:35 +08:00
|
|
|
|
import { AvatarDropdown, AvatarName, Footer, SelectLang } from '@/components';
|
2024-11-18 16:38:38 +08:00
|
|
|
|
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
|
|
|
|
|
|
import { SettingDrawer } from '@ant-design/pro-components';
|
|
|
|
|
|
import type { RunTimeLayoutConfig } from '@umijs/max';
|
2025-03-28 15:30:35 +08:00
|
|
|
|
import { history } from '@umijs/max';
|
2024-11-18 16:38:38 +08:00
|
|
|
|
import defaultSettings from '../config/defaultSettings';
|
|
|
|
|
|
import { errorConfig } from './requestErrorConfig';
|
|
|
|
|
|
import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access';
|
2025-03-28 15:30:35 +08:00
|
|
|
|
import {
|
|
|
|
|
|
getRemoteMenu,
|
|
|
|
|
|
getRoutersInfo,
|
|
|
|
|
|
getUserInfo,
|
|
|
|
|
|
patchRouteWithRemoteMenus,
|
|
|
|
|
|
setRemoteMenu,
|
|
|
|
|
|
} from './services/session';
|
2024-11-18 16:38:38 +08:00
|
|
|
|
import { PageEnum } from './enums/pagesEnums';
|
2024-11-19 16:16:30 +08:00
|
|
|
|
import { stringify } from 'querystring';
|
2025-03-28 15:30:35 +08:00
|
|
|
|
import { message } from 'antd';
|
2024-11-18 16:38:38 +08:00
|
|
|
|
|
|
|
|
|
|
const isDev = process.env.NODE_ENV === 'development';
|
2024-11-19 16:16:30 +08:00
|
|
|
|
const loginOut = async () => {
|
|
|
|
|
|
clearSessionToken();
|
|
|
|
|
|
setRemoteMenu(null);
|
|
|
|
|
|
const { search, pathname } = window.location;
|
|
|
|
|
|
const urlParams = new URL(window.location.href).searchParams;
|
|
|
|
|
|
/** 此方法会跳转到 redirect 参数所在的位置 */
|
|
|
|
|
|
const redirect = urlParams.get('redirect');
|
|
|
|
|
|
// Note: There may be security issues, please note
|
2025-03-28 15:30:35 +08:00
|
|
|
|
console.log('redirect', window.location.pathname, redirect);
|
2025-01-20 17:42:05 +08:00
|
|
|
|
if (window.location.pathname !== '/qingdao/user/login' && !redirect) {
|
2024-11-19 16:16:30 +08:00
|
|
|
|
history.replace({
|
|
|
|
|
|
pathname: '/user/login',
|
|
|
|
|
|
search: stringify({
|
2025-01-20 17:42:05 +08:00
|
|
|
|
redirect: pathname.replace('/qingdao', '') + search,
|
2024-11-19 16:16:30 +08:00
|
|
|
|
}),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2024-11-18 16:38:38 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @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>,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-03-28 15:30:35 +08:00
|
|
|
|
|
2024-11-18 16:38:38 +08:00
|
|
|
|
// ProLayout 支持的api https://procomponents.ant.design/components/layout
|
|
|
|
|
|
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
|
|
|
|
|
|
return {
|
2024-11-19 16:16:30 +08:00
|
|
|
|
// actionsRender: () => [<Question key="doc" />, <SelectLang key="SelectLang" />],
|
2025-03-28 15:30:35 +08:00
|
|
|
|
actionsRender: () => [<SelectLang key="SelectLang" />],
|
2024-11-18 16:38:38 +08:00
|
|
|
|
avatarProps: {
|
|
|
|
|
|
src: initialState?.currentUser?.avatar,
|
|
|
|
|
|
title: <AvatarName />,
|
|
|
|
|
|
render: (_, avatarChildren) => {
|
|
|
|
|
|
return <AvatarDropdown menu="True">{avatarChildren}</AvatarDropdown>;
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
waterMarkProps: {
|
|
|
|
|
|
// content: initialState?.currentUser?.nickName,
|
|
|
|
|
|
},
|
2025-01-20 17:42:05 +08:00
|
|
|
|
// actionRef: layoutActionRef,
|
2024-11-18 16:38:38 +08:00
|
|
|
|
menu: {
|
|
|
|
|
|
locale: false,
|
2025-01-20 17:42:05 +08:00
|
|
|
|
// // 每当 initialState?.currentUser?.userid 发生修改时重新执行 request
|
2024-11-18 16:38:38 +08:00
|
|
|
|
params: {
|
|
|
|
|
|
userId: initialState?.currentUser?.userId,
|
|
|
|
|
|
},
|
|
|
|
|
|
request: async () => {
|
|
|
|
|
|
if (!initialState?.currentUser?.userId) {
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
2025-03-28 15:30:35 +08:00
|
|
|
|
return getRemoteMenu();
|
2024-11-18 16:38:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
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',
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2025-03-28 15:30:35 +08:00
|
|
|
|
pure: false,
|
2024-11-19 16:16:30 +08:00
|
|
|
|
// links: isDev
|
|
|
|
|
|
// ? [
|
|
|
|
|
|
// <Link key="openapi" to="/umi/plugin/openapi" target="_blank">
|
|
|
|
|
|
// <LinkOutlined />
|
|
|
|
|
|
// <span>OpenAPI 文档</span>
|
|
|
|
|
|
// </Link>,
|
|
|
|
|
|
// ]
|
|
|
|
|
|
// : [],
|
2024-11-18 16:38:38 +08:00
|
|
|
|
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();
|
2025-03-28 15:30:35 +08:00
|
|
|
|
// console.log('onRouteChange', clientRoutes, location, menus);
|
|
|
|
|
|
if (menus === null && location.pathname !== PageEnum.LOGIN) {
|
|
|
|
|
|
console.log('refresh');
|
2025-01-20 17:42:05 +08:00
|
|
|
|
// history.go(0);
|
2024-11-18 16:38:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// export function patchRoutes({ routes, routeComponents }) {
|
|
|
|
|
|
// console.log('patchRoutes', routes, routeComponents);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
export async function patchClientRoutes({ routes }) {
|
|
|
|
|
|
// console.log('patchClientRoutes', routes);
|
|
|
|
|
|
patchRouteWithRemoteMenus(routes);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-19 16:16:30 +08:00
|
|
|
|
export async function render(oldRender: () => void) {
|
2025-03-28 15:30:35 +08:00
|
|
|
|
console.log('render get routers', oldRender);
|
2024-11-18 16:38:38 +08:00
|
|
|
|
const token = getAccessToken();
|
2025-03-28 15:30:35 +08:00
|
|
|
|
if (!token || token?.length === 0) {
|
2024-11-18 16:38:38 +08:00
|
|
|
|
oldRender();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-03-28 15:30:35 +08:00
|
|
|
|
await getRoutersInfo().then((res) => {
|
|
|
|
|
|
console.log('render get routers', 123);
|
2025-01-20 17:42:05 +08:00
|
|
|
|
|
2024-11-18 16:38:38 +08:00
|
|
|
|
setRemoteMenu(res);
|
2025-03-28 15:30:35 +08:00
|
|
|
|
oldRender();
|
2024-11-18 16:38:38 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @name request 配置,可以配置错误处理
|
|
|
|
|
|
* 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
|
|
|
|
|
|
* @doc https://umijs.org/docs/max/request#配置
|
|
|
|
|
|
*/
|
|
|
|
|
|
const checkRegion = 5 * 60 * 1000;
|
|
|
|
|
|
export const request = {
|
|
|
|
|
|
...errorConfig,
|
2025-04-25 15:02:46 +08:00
|
|
|
|
baseURL: process.env.NODE_ENV === 'development' ? '' : 'https://qd.zhaopinzao8dian.com/api',
|
2025-01-20 17:42:05 +08:00
|
|
|
|
// baseURL: 'http://39.98.44.136:8080',
|
2024-11-18 16:38:38 +08:00
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-03-28 15:30:35 +08:00
|
|
|
|
if (process.env.NODE_ENV !== 'development') {
|
2025-01-20 17:42:05 +08:00
|
|
|
|
if (url.startsWith('/api')) {
|
|
|
|
|
|
url = url.replace(/^\/api/, '');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-18 16:38:38 +08:00
|
|
|
|
return { url, options };
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
responseInterceptors: [
|
2024-11-19 16:16:30 +08:00
|
|
|
|
(response) => {
|
|
|
|
|
|
// 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到
|
|
|
|
|
|
const { data = {} as any, config } = response;
|
|
|
|
|
|
switch (data.code) {
|
|
|
|
|
|
case 401:
|
2025-03-28 15:30:35 +08:00
|
|
|
|
loginOut();
|
|
|
|
|
|
break;
|
2024-11-19 16:16:30 +08:00
|
|
|
|
}
|
2025-03-28 15:30:35 +08:00
|
|
|
|
if (data.code !== 200 && data.msg) {
|
|
|
|
|
|
message.info(data.msg);
|
2024-12-05 16:32:02 +08:00
|
|
|
|
}
|
2025-03-28 15:30:35 +08:00
|
|
|
|
// console.log('data: ', data)
|
2024-11-19 16:16:30 +08:00
|
|
|
|
// console.log('config: ', config)
|
2025-03-28 15:30:35 +08:00
|
|
|
|
return response;
|
2024-11-19 16:16:30 +08:00
|
|
|
|
},
|
2024-11-18 16:38:38 +08:00
|
|
|
|
],
|
|
|
|
|
|
};
|