app.jsx 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. import { PageLoading } from '@ant-design/pro-layout';
  2. import { notification, Modal, message } from 'antd';
  3. import { history, Link, useModel } from 'umi';
  4. import RightContent from '@/components/RightContent';
  5. import Footer from '@/components/Footer';
  6. import { BookOutlined, LinkOutlined } from '@ant-design/icons';
  7. import { getQueryString } from './utils';
  8. import { stringify } from 'querystring';
  9. import { getSubHosp, getMenus } from './services/user';
  10. import iconEnum from './menuIcons';
  11. import { createRef } from 'react';
  12. import { reject } from 'lodash';
  13. const layoutActionRef = createRef();
  14. const { query = {}, pathname } = history.location;
  15. const { redirect, hospSign = 'dOBHdoPmJgPGnMSH' } = query;
  16. const isDev = process.env.NODE_ENV === 'development';
  17. const loginParams = localStorage.getItem('loginParams');
  18. //医院标识
  19. let sign = '', isExpired = false;
  20. if (hospSign) {
  21. sign = hospSign;
  22. } else {
  23. //query里没有就从localstorage里找
  24. const { hospSign } = JSON.parse(loginParams);
  25. sign = hospSign;
  26. }
  27. const loginPath = `/user/login?hospSign=${sign}`;
  28. let requestMethod = 'get';
  29. /** 获取用户信息比较慢的时候会展示一个 loading */
  30. console.log({ location });
  31. const { search } = location;
  32. let urlStr = search.split('?')[1]
  33. const urlSearchParams = new URLSearchParams(urlStr)
  34. const urlParamsResult = Object.fromEntries(urlSearchParams.entries());
  35. const {token:urlToken} = urlParamsResult
  36. if(urlToken){
  37. //嵌入中台暂时模拟
  38. const userData = {
  39. avatar: "https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png",
  40. name: "中台管理员",
  41. token:urlToken,
  42. userid: 103
  43. }
  44. localStorage.setItem('userData', JSON.stringify(userData))
  45. }
  46. export const initialStateConfig = {
  47. loading: <PageLoading />,
  48. };
  49. /**
  50. * @see https://umijs.org/zh-CN/plugins/plugin-initial-state
  51. * */
  52. export async function getInitialState() {
  53. const fetchUserInfo = async () => {
  54. const userData = localStorage.getItem('userData');
  55. if (userData) {
  56. return userData;
  57. }
  58. return undefined;
  59. };
  60. const getMenuDataFromServer = async () => {
  61. if (window.location.pathname !== `/user/login`) {
  62. const resp = await getMenus();
  63. const { status, data } = resp;
  64. if (status == 200) {
  65. return data;
  66. } else {
  67. return [{
  68. component: './404',
  69. },];
  70. }
  71. }
  72. };
  73. const fetchSubHosp = async () => {
  74. return null
  75. }
  76. if (history.location.pathname !== loginPath) {
  77. const currentUser = await fetchUserInfo();
  78. const menu = await getMenuDataFromServer();
  79. return {
  80. fetchUserInfo,
  81. currentUser,
  82. settings: {},
  83. isExpired: false,
  84. fetchSubHosp,
  85. sign,
  86. isDev: process.env.NODE_ENV == 'development',
  87. menu: menu
  88. };
  89. }
  90. return {
  91. fetchUserInfo,
  92. settings: {},
  93. fetchSubHosp,
  94. sign
  95. };
  96. }
  97. /**
  98. * 退出登录,并且将当前的 url 保存
  99. */
  100. const loginOut = async () => {
  101. // await outLogin();
  102. localStorage.removeItem('userData');
  103. localStorage.removeItem('menus');
  104. if (window.location.pathname !== `/user/login` && !redirect) {
  105. history.replace({
  106. pathname: `/user/login`,
  107. search: stringify({
  108. redirect: pathname,
  109. hospSign: sign
  110. }),
  111. });
  112. }
  113. };
  114. //请求拦截器
  115. const authHeaderInterceptor = (url, options) => {
  116. const { method } = options;
  117. if (method == 'post') {
  118. requestMethod = 'post'
  119. } else {
  120. requestMethod = 'get'
  121. }
  122. let authHeader = {};
  123. const userData = localStorage.getItem('userData');
  124. if (userData) {
  125. const { token } = JSON.parse(userData);
  126. authHeader.token = token;
  127. }
  128. return {
  129. url: `${url}`,
  130. options: { ...options, interceptors: true, headers: authHeader },
  131. };
  132. };
  133. //响应拦截器
  134. const demoResponseInterceptors = async (response, options) => {
  135. try {
  136. const { status } = response;
  137. // console.log({response});
  138. if (status != 200) {
  139. const { errorCode, } = response;
  140. if (errorCode == 500) {
  141. notification.error({
  142. message: '抱歉,服务器出现错误!'
  143. });
  144. }
  145. if (errorCode == 404) {
  146. notification.error({
  147. message: '抱歉,服务器未找到请求!'
  148. });
  149. } else {
  150. notification.error({
  151. message: `错误 ${status}`
  152. });
  153. }
  154. }
  155. const _response = await response.clone().json();
  156. const { status: dataStatus, errorMessage, errorCode } = _response;
  157. const { url } = options;
  158. //success返回
  159. if (dataStatus == 200) {
  160. if (requestMethod == 'post' && url != '/api/costAccount/login') {
  161. message.success('操作成功!');
  162. }
  163. return response;
  164. } else {
  165. // console.log({ isExpired });
  166. if (errorCode == 499 && !isExpired) {
  167. isExpired = true;
  168. Modal.confirm({
  169. title: '抱歉,登录已过期请重新登录!',
  170. onOk: () => {
  171. loginOut();
  172. }
  173. });
  174. } else {
  175. if (errorMessage) {
  176. notification.error({
  177. message: errorMessage,
  178. duration: 5,
  179. });
  180. }
  181. return;
  182. }
  183. }
  184. return {
  185. success: true,
  186. errorMessage: {
  187. info: errorMessage
  188. }
  189. }
  190. } catch (err) {
  191. console.log('catch error:', err)
  192. }
  193. }
  194. const errorHandlerFunc = (error) => {
  195. console.log({ error });
  196. try {
  197. const { info } = error;
  198. const errortext = '';
  199. const { status, errorMessage } = info;
  200. notification.error({
  201. message: ` ${status ? status : ''}: ${errorMessage}`,
  202. description: errortext,
  203. });
  204. } catch (err) {
  205. console.log({ 'errorHandlerFunc': err });
  206. notification.error({
  207. message: '登录遇到未知错误,查看控制台!',
  208. });
  209. }
  210. };
  211. export const request = {
  212. errorHandler: errorHandlerFunc,
  213. // 新增自动添加AccessToken的请求前拦截器
  214. requestInterceptors: [authHeaderInterceptor],
  215. responseInterceptors: [demoResponseInterceptors],
  216. };
  217. //将服务端获取的菜单 icon 字符串映射为对应的 icon Dom
  218. const mappingIcon = menuData => {
  219. const mappingMenu = menuData.map(item => ({
  220. ...item,
  221. icon: item.icon && iconEnum[item.icon],
  222. children: item.children ? mappingIcon(item.children) : [],
  223. }));
  224. return mappingMenu;
  225. };
  226. export const layout = async ({ initialState }) => {
  227. return urlToken?{
  228. headerTitleRender:false,
  229. headerRender:false,
  230. rightContentRender: () => <RightContent />,
  231. disableContentMargin: false,
  232. waterMarkProps: {
  233. content: '',
  234. },
  235. actionRef: layoutActionRef,
  236. footerRender: () => <Footer />,
  237. onPageChange: () => {
  238. const { location } = history; // 如果没有登录,重定向到 login
  239. if (!initialState?.currentUser && location.pathname !== '/user/login') {
  240. history.push(loginPath);
  241. }
  242. },
  243. menu: {
  244. params: {
  245. userId: initialState,
  246. },
  247. request: async (params, defaultMenuData) => {
  248. // initialState.currentUser 中包含了所有用户信息
  249. const { currentUser, isDev } = initialState;
  250. if (isDev || currentUser.userid == 96) {
  251. //开发环境或超级账号
  252. return []
  253. }
  254. if (currentUser) {
  255. const resp = await getMenus();
  256. const { data: menu } = resp;
  257. return mappingIcon(menu);
  258. } else {
  259. return [
  260. {
  261. component: './404',
  262. }
  263. ]
  264. }
  265. },
  266. },
  267. menuHeaderRender: undefined,
  268. // 自定义 403 页面
  269. // unAccessible: <div>unAccessible</div>,
  270. ...initialState?.settings,
  271. }:{
  272. rightContentRender: () => <RightContent />,
  273. disableContentMargin: false,
  274. waterMarkProps: {
  275. content: '',
  276. },
  277. actionRef: layoutActionRef,
  278. footerRender: () => <Footer />,
  279. onPageChange: () => {
  280. const { location } = history; // 如果没有登录,重定向到 login
  281. if (!initialState?.currentUser && location.pathname !== '/user/login') {
  282. history.push(loginPath);
  283. }
  284. },
  285. menu: {
  286. params: {
  287. userId: initialState,
  288. },
  289. request: async (params, defaultMenuData) => {
  290. // initialState.currentUser 中包含了所有用户信息
  291. const { currentUser, isDev } = initialState;
  292. if (isDev || currentUser.userid == 96) {
  293. //开发环境或超级账号
  294. return []
  295. }
  296. if (currentUser) {
  297. const resp = await getMenus();
  298. const { data: menu } = resp;
  299. return mappingIcon(menu);
  300. } else {
  301. return [
  302. {
  303. component: './404',
  304. }
  305. ]
  306. }
  307. },
  308. },
  309. menuHeaderRender: undefined,
  310. // 自定义 403 页面
  311. // unAccessible: <div>unAccessible</div>,
  312. ...initialState?.settings,
  313. };
  314. };