|
@@ -1,22 +1,13 @@
|
|
|
import type { Settings as LayoutSettings } from '@ant-design/pro-layout'
|
|
|
-import { PageLoading } from '@ant-design/pro-layout'
|
|
|
import { notification } from 'antd'
|
|
|
-import type { RequestConfig, RunTimeLayoutConfig } from 'umi'
|
|
|
-import { getIntl, getLocale, history } from 'umi'
|
|
|
+import type { RequestConfig, RunTimeLayoutConfig } from '@umijs/max'
|
|
|
+import { getIntl, getLocale, history } from '@umijs/max'
|
|
|
import RightContent from '@/components/RightContent'
|
|
|
-import Footer from '@/components/Footer'
|
|
|
-import type { RequestOptionsInit, ResponseError } from 'umi-request'
|
|
|
import { currentUser as queryCurrentUser } from './services/user/api'
|
|
|
import consts from './utils/consts'
|
|
|
-
|
|
|
-const isDev = process.env.NODE_ENV === 'development'
|
|
|
+import defaultSettings from '../config/defaultSettings'
|
|
|
const loginPath = '/user/login'
|
|
|
|
|
|
-/** 获取用户信息比较慢的时候会展示一个 loading */
|
|
|
-export const initialStateConfig = {
|
|
|
- loading: <PageLoading />
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* @see https://umijs.org/zh-CN/plugins/plugin-initial-state
|
|
|
* */
|
|
@@ -53,118 +44,81 @@ export async function getInitialState(): Promise<{
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const authHeaderInterceptor = (url: string, options: RequestOptionsInit) => {
|
|
|
- const token = window.localStorage.getItem('TOKEN_ID')
|
|
|
+const authHeaderInterceptor = options => {
|
|
|
+ const token = JSON.parse(window.localStorage.getItem('TOKEN_ID'))
|
|
|
// 如果是登录页面,不执行
|
|
|
- if (!token && history.location.pathname !== loginPath) {
|
|
|
- return history.push(loginPath)
|
|
|
- }
|
|
|
- const authHeader = { Authorization: `Bearer ${JSON.parse(token)}` }
|
|
|
- return {
|
|
|
- url: `${url}`,
|
|
|
- options: { ...options, interceptors: true, headers: authHeader }
|
|
|
+ if (token) {
|
|
|
+ // 在白名单里的请求放过
|
|
|
+ if (consts.TOKEN_WHITE_LIST.includes(options.url)) {
|
|
|
+ return options
|
|
|
+ }
|
|
|
+ options.headers[consts.TOKEN_HEADER] = 'bearer ' + token
|
|
|
}
|
|
|
+ return options
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 异常处理程序
|
|
|
- const codeMessage = {
|
|
|
- 200: '服务器成功返回请求的数据。',
|
|
|
- 201: '新建或修改数据成功。',
|
|
|
- 202: '一个请求已经进入后台排队(异步任务)。',
|
|
|
- 204: '删除数据成功。',
|
|
|
- 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
|
|
|
- 401: '用户没有权限(令牌、用户名、密码错误)。',
|
|
|
- 403: '用户得到授权,但是访问是被禁止的。',
|
|
|
- 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
|
|
|
- 405: '请求方法不被允许。',
|
|
|
- 406: '请求的格式不可得。',
|
|
|
- 410: '请求的资源被永久删除,且不会再得到的。',
|
|
|
- 422: '当创建一个对象时,发生一个验证错误。',
|
|
|
- 500: '服务器发生错误,请检查服务器。',
|
|
|
- 502: '网关错误。',
|
|
|
- 503: '服务不可用,服务器暂时过载或维护。',
|
|
|
- 504: '网关超时。',
|
|
|
- };
|
|
|
- * @see https://beta-pro.ant.design/docs/request-cn
|
|
|
- */
|
|
|
-export const request: RequestConfig = {
|
|
|
- errorHandler: (error: ResponseError) => {
|
|
|
- const { messages } = getIntl(getLocale())
|
|
|
- const { response } = error
|
|
|
+const errorHandler = (error: any, opts: any) => {
|
|
|
+ if (opts?.skipErrorHandler) return
|
|
|
|
|
|
- if (response && response.status) {
|
|
|
- const { status, statusText, url } = response
|
|
|
- const requestErrorMessage = messages['app.request.error']
|
|
|
- const errorMessage = `${requestErrorMessage} ${status}: ${url}`
|
|
|
- const errorDescription = messages[`app.request.${status}`] || statusText
|
|
|
+ const errorInfo = error.info
|
|
|
+ if (errorInfo) {
|
|
|
+ const { errorMessage = '请求失败', errorCode } = errorInfo
|
|
|
+ if (consts.TOKEN_INVALID_CODE.includes(errorCode) && window.location.pathname !== consts.loginPath) {
|
|
|
notification.error({
|
|
|
- message: errorMessage,
|
|
|
- description: errorDescription
|
|
|
+ message: '用户信息过期',
|
|
|
+ description: '请重新登录'
|
|
|
})
|
|
|
- }
|
|
|
-
|
|
|
- if (!response) {
|
|
|
- notification.error({
|
|
|
- description: '您的网络发生异常,无法连接服务器',
|
|
|
- message: '网络异常'
|
|
|
+ history.replace({
|
|
|
+ pathname: consts.loginPath,
|
|
|
+ search: createSearchParams({
|
|
|
+ redirect: window.location.pathname
|
|
|
+ }).toString()
|
|
|
})
|
|
|
+ return
|
|
|
}
|
|
|
- throw error
|
|
|
- },
|
|
|
- middlewares: [
|
|
|
- async (ctx, next) => {
|
|
|
- await next()
|
|
|
- const { req, res } = ctx
|
|
|
- // @ts-ignore
|
|
|
- if (req.options?.skipErrorHandler) {
|
|
|
- return
|
|
|
- }
|
|
|
- const errorAdaptor = req.options?.errorConfig.adaptor || (resData => resData)
|
|
|
- const { options } = req
|
|
|
- const { getResponse } = options
|
|
|
- const resData = getResponse ? res.data : res
|
|
|
- const errorInfo = errorAdaptor(resData, ctx)
|
|
|
- if (resData.code !== consts.RET_CODE.SUCCESS) {
|
|
|
- // 抛出错误到 errorHandler 中处理
|
|
|
- const error: ResponseError = new Error(errorInfo.errorMessage)
|
|
|
- error.name = 'BizError'
|
|
|
- error.data = resData
|
|
|
- error.info = errorInfo
|
|
|
- error.response = res
|
|
|
- throw error
|
|
|
- }
|
|
|
- }
|
|
|
- ],
|
|
|
- prefix: '/backstage',
|
|
|
+ notification.error({
|
|
|
+ message: '请求失败',
|
|
|
+ description: errorMessage
|
|
|
+ })
|
|
|
+ } else if (error.response) {
|
|
|
+ // Axios 的错误
|
|
|
+ // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
|
|
|
+ notification.error({
|
|
|
+ description: `状态码为${error.status}, 请联系管理员进行处理`,
|
|
|
+ message: '请求异常'
|
|
|
+ })
|
|
|
+ } else if (error.request) {
|
|
|
+ // 请求已经成功发起,但没有收到响应
|
|
|
+ // 或请求根本没有发送出去
|
|
|
+ notification.error({
|
|
|
+ description: '您的网络请求已经发起,但没有收到响应',
|
|
|
+ message: '响应超时'
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ notification.error({
|
|
|
+ description: '您的网络发生异常,无法连接服务器',
|
|
|
+ message: '网络异常'
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const request: RequestConfig = {
|
|
|
+ baseURL: consts.PREFIX_URL,
|
|
|
errorConfig: {
|
|
|
- adaptor: resData => {
|
|
|
- return {
|
|
|
- // success: resData.code === consts.RET_CODE.SUCCESS,
|
|
|
- data: resData.data,
|
|
|
- errorCode: resData.code,
|
|
|
- errorMessage: resData.msg
|
|
|
- }
|
|
|
- }
|
|
|
+ errorHandler
|
|
|
},
|
|
|
responseInterceptors: [
|
|
|
- async (response, options) => {
|
|
|
- const errorAdaptor = options?.errorConfig.adaptor || (resData => resData)
|
|
|
- const res = await response.clone().json()
|
|
|
- const { getResponse } = options
|
|
|
- const resData = getResponse ? res.data : res
|
|
|
- const errorInfo = errorAdaptor(resData, { res: response, req: options })
|
|
|
-
|
|
|
- if (res?.code !== consts.RET_CODE.SUCCESS) {
|
|
|
- // 抛出错误到 errorHandler 中处理
|
|
|
- const error: ResponseError = new Error(errorInfo.errorMessage)
|
|
|
- error.name = 'BizError'
|
|
|
- error.data = resData
|
|
|
- error.info = errorInfo
|
|
|
- error.response = res
|
|
|
- throw error
|
|
|
+ async response => {
|
|
|
+ const { data, code: errorCode, msg: errorMessage } = response.data
|
|
|
+ if (!errorCode || errorCode !== consts.RET_CODE.SUCCESS) {
|
|
|
+ if (errorCode !== consts.RET_CODE.SUCCESS) {
|
|
|
+ const error: any = new Error(errorMessage)
|
|
|
+ error.name = 'BizError'
|
|
|
+ error.info = { errorCode, errorMessage, data }
|
|
|
+ throw error
|
|
|
+ }
|
|
|
}
|
|
|
- return response
|
|
|
+ return Promise.resolve(response)
|
|
|
}
|
|
|
],
|
|
|
requestInterceptors: [authHeaderInterceptor]
|
|
@@ -178,12 +132,8 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
|
|
waterMarkProps: initialState.currentUser && {
|
|
|
fontColor: 'rgba(0,0,0,.1)',
|
|
|
offsetTop: 200,
|
|
|
- content: `${initialState.currentUser?.username} ${initialState.currentUser?.telephone.slice(
|
|
|
- -4
|
|
|
- )}`
|
|
|
+ content: `${initialState.currentUser?.username} ${initialState.currentUser?.telephone.slice(-4)}`
|
|
|
},
|
|
|
-
|
|
|
- footerRender: () => <Footer />,
|
|
|
onPageChange: () => {
|
|
|
const { location } = history
|
|
|
// 如果没有登录,重定向到 login
|
|
@@ -191,21 +141,9 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
|
|
history.push(loginPath)
|
|
|
}
|
|
|
},
|
|
|
- links: isDev
|
|
|
- ? [
|
|
|
- // <Link to="/umi/plugin/openapi" target="_blank">
|
|
|
- // <LinkOutlined />
|
|
|
- // <span>openAPI 文档</span>
|
|
|
- // </Link>,
|
|
|
- // <Link to="/~docs">
|
|
|
- // <BookOutlined />
|
|
|
- // <span>业务组件文档</span>
|
|
|
- // </Link>
|
|
|
- ]
|
|
|
- : [],
|
|
|
menuHeaderRender: undefined,
|
|
|
// 自定义 403 页面
|
|
|
// unAccessible: <div>unAccessible</div>,
|
|
|
- ...initialState?.settings
|
|
|
+ ...defaultSettings
|
|
|
}
|
|
|
}
|