154 lines
4.6 KiB
TypeScript
154 lines
4.6 KiB
TypeScript
// 运行时配置
|
||
|
||
import { getLocale, history, Link, RunTimeLayoutConfig } from '@umijs/max';
|
||
import { ConfigProvider } from 'antd';
|
||
import dayjs from 'dayjs';
|
||
import { handleRequestConfig as devRequestConfig } from '../config/request_dev';
|
||
import { handleRequestConfig as prodRequestConfig } from '../config/request_prod';
|
||
import { AvatarDropdown } from './components/Avatar/AvatarDropdown';
|
||
import IconFont from './components/IconFont';
|
||
import LanguageSwitcher from './components/Lang/LanguageSwitcher';
|
||
import ThemeProvider from './components/Theme/ThemeProvider';
|
||
import ThemeSwitcher from './components/Theme/ThemeSwitcher';
|
||
import { THEME_KEY } from './constants';
|
||
import { ROUTE_LOGIN } from './constants/routes';
|
||
import NotFoundPage from './pages/Exception/NotFound';
|
||
import UnAccessPage from './pages/Exception/UnAccess';
|
||
import { apiQueryProfile } from './services/master/AuthController';
|
||
import { checkTokenExpired } from './utils/jwt';
|
||
import { getLogoImage } from './utils/logo';
|
||
import {
|
||
clearAllData,
|
||
clearSessionData,
|
||
getToken,
|
||
removeToken,
|
||
} from './utils/storage';
|
||
const isProdBuild = process.env.NODE_ENV === 'production';
|
||
export type InitialStateResponse = {
|
||
getUserProfile?: () => Promise<MasterModel.UserResponse | undefined>;
|
||
currentUserProfile?: MasterModel.UserResponse;
|
||
theme?: 'light' | 'dark';
|
||
};
|
||
|
||
// 全局初始化数据配置,用于 Layout 用户信息和权限初始化
|
||
// 更多信息见文档:https://umijs.org/docs/api/runtime-config#getinitialstate
|
||
export async function getInitialState(): Promise<InitialStateResponse> {
|
||
const userToken: string = getToken();
|
||
const { pathname } = history.location;
|
||
|
||
dayjs.locale(getLocale() === 'en-US' ? 'en' : 'vi');
|
||
if (!userToken) {
|
||
if (pathname !== ROUTE_LOGIN) {
|
||
history.push(`${ROUTE_LOGIN}?redirect=${pathname}`);
|
||
} else {
|
||
history.push(ROUTE_LOGIN);
|
||
}
|
||
return {};
|
||
}
|
||
const isTokenExpried = checkTokenExpired(userToken);
|
||
if (isTokenExpried) {
|
||
removeToken();
|
||
clearAllData();
|
||
clearSessionData();
|
||
window.location.href = ROUTE_LOGIN;
|
||
return {};
|
||
}
|
||
|
||
const getUserProfile = async () => {
|
||
try {
|
||
const resp = await apiQueryProfile();
|
||
return resp;
|
||
} catch (error) {
|
||
removeToken();
|
||
clearAllData();
|
||
clearSessionData();
|
||
window.location.href = ROUTE_LOGIN;
|
||
}
|
||
};
|
||
const resp = await getUserProfile();
|
||
const currentTheme =
|
||
(localStorage.getItem(THEME_KEY) as 'light' | 'dark') || 'light';
|
||
return {
|
||
getUserProfile: getUserProfile!,
|
||
currentUserProfile: resp,
|
||
theme: currentTheme,
|
||
};
|
||
}
|
||
|
||
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
||
const isDark = initialState?.theme === 'dark';
|
||
return {
|
||
logo: getLogoImage(),
|
||
menu: {
|
||
locale: true,
|
||
},
|
||
fixedHeader: true,
|
||
contentWidth: 'Fluid',
|
||
navTheme: isDark ? 'realDark' : 'light',
|
||
splitMenus: true,
|
||
iconfontUrl: '//at.alicdn.com/t/c/font_5096559_pwy498d2aw.js',
|
||
contentStyle: {
|
||
padding: 0,
|
||
margin: 0,
|
||
paddingInline: 0,
|
||
},
|
||
actionsRender: () => [
|
||
<ThemeSwitcher key="theme-switcher" />,
|
||
<LanguageSwitcher key="lang-switcher" type="dropdown" />,
|
||
],
|
||
avatarProps: {
|
||
size: 'small',
|
||
src: '/avatar.svg',
|
||
render: () => (
|
||
<AvatarDropdown currentUserProfile={initialState?.currentUserProfile} />
|
||
),
|
||
},
|
||
childrenRender: (children) => {
|
||
return (
|
||
<ThemeProvider>
|
||
<ConfigProvider
|
||
theme={{
|
||
components: {
|
||
Collapse: {
|
||
contentPadding: '0px',
|
||
borderlessContentPadding: '0px',
|
||
headerPadding: '0px',
|
||
},
|
||
},
|
||
}}
|
||
>
|
||
{children}
|
||
</ConfigProvider>
|
||
</ThemeProvider>
|
||
);
|
||
},
|
||
layout: 'top',
|
||
menuHeaderRender: undefined,
|
||
menuItemRender: (item, dom) => {
|
||
if (item.path) {
|
||
// Coerce values to string to satisfy TypeScript expectations
|
||
const to = String(item.path ?? '');
|
||
const iconType = String(item.icon ?? '');
|
||
const label = String(item.name ?? '');
|
||
return (
|
||
<Link to={to}>
|
||
<IconFont type={iconType} />
|
||
<span>{label}</span>
|
||
</Link>
|
||
);
|
||
}
|
||
return dom;
|
||
},
|
||
token: {
|
||
header: {
|
||
colorBgMenuItemSelected: '#EEF7FF', // background khi chọn
|
||
colorTextMenuSelected: isDark ? '#fff' : '#1A2130', // màu chữ khi chọn
|
||
},
|
||
},
|
||
unAccessible: <UnAccessPage />,
|
||
noFound: <NotFoundPage />,
|
||
};
|
||
};
|
||
|
||
export const request = isProdBuild ? prodRequestConfig : devRequestConfig;
|