Files
shihezi-admin/src/app.tsx

344 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import './utils/amap_system';
import { AvatarDropdown, AvatarName, Footer, SelectLang } from '@/components';
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 } 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';
import { stringify } from 'querystring';
import { message } from 'antd';
import { encrypt, decrypt, needEncrypt } from '@/utils/encrypt';
const isDev = process.env.NODE_ENV === 'development';
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
console.log('redirect', window.location.pathname, redirect);
if (window.location.pathname !== '/qingdao/user/login' && !redirect) {
history.replace({
pathname: '/user/login',
search: stringify({
redirect: pathname.replace('/qingdao', '') + search,
}),
});
}
};
/**
* @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" />],
actionsRender: () => [<SelectLang key="SelectLang" />],
avatarProps: {
src: initialState?.currentUser?.avatar,
title: <AvatarName />,
render: (_, avatarChildren) => {
return <AvatarDropdown menu="True">{avatarChildren}</AvatarDropdown>;
},
},
waterMarkProps: {
// content: initialState?.currentUser?.nickName,
},
// actionRef: layoutActionRef,
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',
},
],
pure: false,
// 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 async function render(oldRender: () => void) {
console.log('render get routers', oldRender);
const token = getAccessToken();
if (!token || token?.length === 0) {
oldRender();
return;
}
await getRoutersInfo().then((res) => {
console.log('render get routers', 123);
setRemoteMenu(res);
oldRender();
});
}
/**
* @name request 配置,可以配置错误处理
* 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
* @doc https://umijs.org/docs/max/request#配置
*/
const checkRegion = 5 * 60 * 1000;
export const request = {
...errorConfig,
baseURL: process.env.NODE_ENV === 'development' ? '' : 'https://qd.zhaopinzao8dian.com/api',
// baseURL: 'http://39.98.44.136:8080',
// baseURL:
// process.env.NODE_ENV === 'development'
// ? 'http://10.213.6.207:19010'
// : 'http://10.213.6.207:19010/api',
requestInterceptors: [
(url: any, options: { headers: any; data?: any; params?: any; method?: string }) => {
const headers = options.headers ? options.headers : {};
console.log('request ====>:', url);
const authHeader = headers['Authorization'];
const isToken = headers['isToken'];
// 处理开发环境API路径
if (process.env.NODE_ENV !== 'development') {
if (url.startsWith('/api')) {
url = url.replace(/^\/api/, '');
}
}
// 处理认证token
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();
}
}
// 处理SM4加密 - 根据config的isEncrypt来判断
if (needEncrypt(options)) {
console.log('进行SM4加密处理');
let requestData = options.data;
let requestParams = options.params;
// 加密请求数据
if (requestData && Object.keys(requestData).length > 0) {
const jsonData = JSON.stringify(requestData);
const encryptedBody = encrypt(jsonData);
requestData = {
encrypted: true,
encryptedData: encryptedBody,
timestamp: Date.now(),
};
}
// 加密查询参数
if (requestParams && Object.keys(requestParams).length > 0) {
const jsonParams = JSON.stringify(requestParams);
const encryptedParams = encrypt(jsonParams);
requestParams = {
encrypted: true,
encryptedData: encryptedParams,
timestamp: Date.now(),
};
}
// 添加加密标识头
headers['X-Encrypted'] = 'true';
return {
url,
options: {
...options,
headers,
data: requestData,
params: requestParams,
},
};
}
return { url, options: { ...options, headers } };
},
],
responseInterceptors: [
(response) => {
// 不再需要异步处理读取返回体内容可直接在data中读出部分字段可在 config 中找到
const { data = {} as any, config } = response;
// 检查是否需要解密
const isEncrypted = data.encrypted;
if (isEncrypted && data.encryptedData) {
console.log('进行SM4解密处理');
try {
// 解密响应数据
const decryptedData = decrypt(data.encryptedData);
// console.log(decryptedData)
response.data =
typeof decryptedData === 'string' ? JSON.parse(decryptedData) : decryptedData;
} catch (error) {
console.error('响应解密失败:', error);
// 如果解密失败,保持原始数据
}
}
// 处理业务状态码
switch (data.code) {
case 401:
loginOut();
break;
}
if (data.code !== 200 && data.msg) {
message.info(data.msg);
}
return response;
},
],
};