'init_again'
Change-Id: Ib7ecdb9f5baeab1e4681152a57b936edf7475b35
diff --git a/src/app.tsx b/src/app.tsx
new file mode 100644
index 0000000..38f76b4
--- /dev/null
+++ b/src/app.tsx
@@ -0,0 +1,233 @@
+import { Footer, Question, SelectLang, AvatarDropdown, AvatarName } from '@/components';
+import { LinkOutlined } from '@ant-design/icons';
+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, Link } 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';
+
+
+const isDev = process.env.NODE_ENV === 'development';
+
+
+
+/**
+ * @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" />],
+ avatarProps: {
+ src: initialState?.currentUser?.avatar,
+ title: <AvatarName />,
+ render: (_, avatarChildren) => {
+ return <AvatarDropdown menu="True">{avatarChildren}</AvatarDropdown>;
+ },
+ },
+ waterMarkProps: {
+ // content: initialState?.currentUser?.nickName,
+ },
+ 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',
+ },
+ ],
+ 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 function render(oldRender: () => void) {
+ // console.log('render get routers', oldRender)
+ const token = getAccessToken();
+ if(!token || token?.length === 0) {
+ oldRender();
+ return;
+ }
+ getRoutersInfo().then(res => {
+ setRemoteMenu(res);
+ oldRender()
+ });
+}
+
+/**
+ * @name request 配置,可以配置错误处理
+ * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。
+ * @doc https://umijs.org/docs/max/request#配置
+ */
+const checkRegion = 5 * 60 * 1000;
+
+export const request = {
+ ...errorConfig,
+ 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();
+ }
+ }
+ return { url, options };
+ },
+ ],
+ responseInterceptors: [
+ // (response) =>
+ // {
+ // // // 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到
+ // // const { data = {} as any, config } = response;
+ // // // do something
+ // // console.log('data: ', data)
+ // // console.log('config: ', config)
+ // return response
+ // },
+ ],
+};