// 运行时配置 // 全局初始化数据配置,用于 Layout 用户信息和权限初始化 // 更多信息见文档:https://umijs.org/docs/api/runtime-config#getinitialstate import auth from '@/services/auth'; import { getRedirectUrl } from '@/utils/getRedirectUrl'; import { RunTimeLayoutConfig } from '@@/plugin-layout/types'; import { RequestConfig } from '@@/plugin-request/request'; import { history } from '@umijs/max'; import { message, notification } from 'antd'; import './global.less'; interface InitialState { channel?: AuthAPI.ChannelVO; homePagePath?: string; tip?: { show: boolean; message: string; }; } export async function getInitialState(): Promise { await getRedirectUrl(); const { data: channel } = await auth.channel.selectChannelByDomain({ domain: window.location.host, }); return { channel, tip: { show: false, message: '', }, }; } export const layout: RunTimeLayoutConfig = ({ initialState }) => { const link = document.querySelector("link[rel*='icon']") || document.createElement('link'); link.type = 'image/x-icon'; link.rel = 'shortcut icon'; link.href = initialState?.channel?.logo; document.getElementsByTagName('head')[0].appendChild(link); return { title: initialState?.channel?.title, subTitle: initialState?.channel?.subTitle, logo: initialState?.channel?.logo, }; }; // 错误处理方案: 错误类型 enum ErrorShowType { SILENT = 0, WARN_MESSAGE = 1, ERROR_MESSAGE = 2, NOTIFICATION = 3, REDIRECT = 9, } // 与后端约定的响应数据格式 interface ResponseStructure { success: boolean; data: any; errCode?: string; errMessage?: string; showType?: ErrorShowType; } // 运行时配置 export const request: RequestConfig = { // 统一的请求设定 timeout: 60000, headers: { 'X-Requested-With': 'XMLHttpRequest', 'Xh-Platform-Id': '1769220738064285698', }, // 错误处理: umi@3 的错误处理方案。 errorConfig: { // 错误抛出 errorThrower: (res: ResponseStructure) => { const { success, data, errCode, errMessage, showType } = res; if (!success) { if (errCode === '401' || errCode === '403') { // 未登录,跳转到登录页面 history.push('/login'); return; } if (errCode === '400') { message.error(errMessage); return; } if (errCode === 'UNKNOWN_ERROR') { message.error('未知的错误'); return; } if (errCode === 'USER_AUTH_NOT_LOGIN') { return; } if (errCode === 'USER_AUTH_NO_APP_PERMISSION') { message.error(errMessage); return; } const error: any = new Error(errMessage || errCode); error.name = 'BizError'; error.info = { errCode, errMessage, showType, data }; throw error; // 抛出自制的错误 } }, // 错误接收及处理 errorHandler: (error: any, opts: any) => { if (opts?.skipErrorHandler) throw error; // 我们的 errorThrower 抛出的错误。 if (error.name === 'BizError') { const errorInfo: ResponseStructure | undefined = error.info; if (errorInfo) { const { errMessage, errCode } = errorInfo; switch (errorInfo.showType) { case ErrorShowType.SILENT: // do nothing break; case ErrorShowType.WARN_MESSAGE: message.warning(errMessage); break; case ErrorShowType.ERROR_MESSAGE: message.error(errMessage); break; case ErrorShowType.NOTIFICATION: notification.open({ description: errMessage, message: errCode, }); break; case ErrorShowType.REDIRECT: // TODO: redirect break; default: message.error(errMessage); } } } else if (error.response) { // Axios 的错误 // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围 message.error(`Response status:${error.response.status}`); } else if (error.request) { // 请求已经成功发起,但没有收到响应 // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例, // 而在node.js中是 http.ClientRequest 的实例 message.error('None response! Please retry.1'); } else { // 发送请求时出了点问题 message.error('Request error, please retry.2'); } }, }, // 请求拦截器 requestInterceptors: [ ( url: any, options: { headers: any; }, ) => { console.log('请求拦截器', url, options); const apiUrl = '/api' + url; return { url: apiUrl, options, }; }, ], // 响应拦截器 responseInterceptors: [ (response: ResponseStructure) => { // 拦截响应数据,进行个性化处理 return response; }, ], } as any;