app.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import Footer from '@/components/Footer';
  2. import RightContent from '@/components/RightContent';
  3. import type { Settings as LayoutSettings } from '@ant-design/pro-components';
  4. import { PageLoading, SettingDrawer } from '@ant-design/pro-components';
  5. import type { RunTimeLayoutConfig } from 'umi';
  6. import { history } from 'umi';
  7. import defaultSettings from '../config/defaultSettings';
  8. import { currentUser as queryCurrentUser } from './services/ant-design-pro/api';
  9. import { message } from 'antd';
  10. import { queryMenu } from '@/services/menu';
  11. import Icon from '@ant-design/icons';
  12. import * as icons from '@ant-design/icons';
  13. const loginPath = '/user/login';
  14. /** 获取用户信息比较慢的时候会展示一个 loading */
  15. export const initialStateConfig = {
  16. loading: <PageLoading />,
  17. };
  18. /**
  19. * @see https://umijs.org/zh-CN/plugins/plugin-initial-state
  20. * */
  21. export 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 msg: any = await queryCurrentUser(localStorage.getItem('token'));
  30. return {
  31. name: msg.data.user_name,
  32. };
  33. } catch (error) {
  34. history.push(loginPath);
  35. }
  36. return undefined;
  37. };
  38. // 如果不是登录页面,执行
  39. if (history.location.pathname !== loginPath) {
  40. const currentUser = await fetchUserInfo();
  41. return {
  42. fetchUserInfo,
  43. currentUser,
  44. settings: defaultSettings,
  45. };
  46. }
  47. return {
  48. fetchUserInfo,
  49. settings: defaultSettings,
  50. };
  51. }
  52. /**
  53. * 映射菜单对应的图标
  54. * */
  55. const loopMenuItem: any = (menus: any[]) =>
  56. menus.map(({ icon, routes, ...item }) => ({
  57. ...item,
  58. icon: icon && <Icon component={icons[icon]} />,
  59. routes: routes && loopMenuItem(routes),
  60. }));
  61. const permissionsMenu = (routers: any[], data: any) => {
  62. data.forEach((item: any) => {
  63. let menu: any;
  64. if (item.children && item.children.length > 0) {
  65. // 还有下级
  66. menu = {
  67. path: item.router,
  68. routes: [],
  69. name: item.name,
  70. icon: item.icon,
  71. };
  72. } else {
  73. // 最后一级
  74. menu = {
  75. path: item.router,
  76. name: item.name,
  77. icon: item.icon,
  78. };
  79. }
  80. if (item.children) {
  81. permissionsMenu(menu.routes, item.children);
  82. }
  83. routers.push(menu);
  84. });
  85. };
  86. // ProLayout 支持的api https://procomponents.ant.design/components/layout
  87. export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
  88. return {
  89. rightContentRender: () => <RightContent />,
  90. disableContentMargin: false,
  91. waterMarkProps: {
  92. content: initialState?.currentUser?.name,
  93. },
  94. footerRender: () => <Footer />,
  95. onPageChange: () => {
  96. const { location } = history;
  97. // 如果没有登录,重定向到 login
  98. if (!initialState?.currentUser && location.pathname !== loginPath) {
  99. history.push(loginPath);
  100. }
  101. },
  102. menu: {
  103. locale: false,
  104. params: initialState?.currentUser,
  105. request: async () => {
  106. const menuData = await queryMenu({ q: 'tree', query_all: 1 });
  107. const routers: any[] = [];
  108. permissionsMenu(routers, menuData.data.list);
  109. return loopMenuItem(routers);
  110. },
  111. },
  112. menuHeaderRender: undefined,
  113. // 自定义 403 页面
  114. // unAccessible: <div>unAccessible</div>,
  115. // 增加一个 loading 的状态
  116. childrenRender: (children: any, props: { location: { pathname: string | string[] } }) => {
  117. // if (initialState?.loading) return <PageLoading />;
  118. return (
  119. <>
  120. {children}
  121. {!props.location?.pathname?.includes('/login') && (
  122. <SettingDrawer
  123. disableUrlParams
  124. enableDarkTheme
  125. settings={initialState?.settings}
  126. onSettingChange={(settings) => {
  127. setInitialState((preInitialState: any) => ({
  128. ...preInitialState,
  129. settings,
  130. }));
  131. }}
  132. />
  133. )}
  134. </>
  135. );
  136. },
  137. ...initialState?.settings,
  138. };
  139. };
  140. const addToken = async (url: any, options: any) => {
  141. // 此处为拦截器,每次发送请求之前判断能否取到token
  142. if (localStorage.getItem('token')) {
  143. const headers = {
  144. Authorization: `${localStorage.getItem('token')}`,
  145. };
  146. return {
  147. url,
  148. options: { ...options, headers },
  149. };
  150. }
  151. return false;
  152. };
  153. const MainResponseInterceptors = (response: { status: number }) => {
  154. if (response.status === 401) {
  155. message.warn('帐号登录过期,请重新登录');
  156. history.push(loginPath);
  157. }
  158. return response;
  159. };
  160. export const request = {
  161. errorConfig: {
  162. adaptor: (resData: any) => {
  163. return {
  164. showType: resData.code ? 2 : 0,
  165. errorMessage: resData.message,
  166. };
  167. },
  168. },
  169. requestInterceptors: [addToken],
  170. responseInterceptors: [MainResponseInterceptors],
  171. };