|
@@ -3,11 +3,18 @@ import { navigate } from '@/router/components/SetupNavigation'
|
|
import { ResultEnum } from '#/enum'
|
|
import { ResultEnum } from '#/enum'
|
|
import { t } from '@/locales/i18n'
|
|
import { t } from '@/locales/i18n'
|
|
import axios, { type AxiosError, type AxiosRequestConfig, type AxiosResponse } from 'axios'
|
|
import axios, { type AxiosError, type AxiosRequestConfig, type AxiosResponse } from 'axios'
|
|
|
|
+import { nanoid } from 'nanoid'
|
|
import qs from 'qs'
|
|
import qs from 'qs'
|
|
import { toast } from 'sonner'
|
|
import { toast } from 'sonner'
|
|
import { serialize } from '@/utils/util'
|
|
import { serialize } from '@/utils/util'
|
|
import { BASE_URL, TIME_OUT } from './config'
|
|
import { BASE_URL, TIME_OUT } from './config'
|
|
|
|
|
|
|
|
+declare module 'axios' {
|
|
|
|
+ interface InternalAxiosRequestConfig {
|
|
|
|
+ nanoid?: string // 唯一id,用于中止请求
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
const handleNetworkError = (response: AxiosResponse) => {
|
|
const handleNetworkError = (response: AxiosResponse) => {
|
|
const { actions } = useUserSessionStore.getState()
|
|
const { actions } = useUserSessionStore.getState()
|
|
if (!response) return
|
|
if (!response) return
|
|
@@ -20,10 +27,8 @@ const handleNetworkError = (response: AxiosResponse) => {
|
|
break
|
|
break
|
|
case 401:
|
|
case 401:
|
|
errMessage = '未授权,请重新登录'
|
|
errMessage = '未授权,请重新登录'
|
|
- // abortRequestFn()
|
|
|
|
- // logoutFn()
|
|
|
|
- actions.clearUserInfoAndToken()
|
|
|
|
- navigate('/login')
|
|
|
|
|
|
+ abortRequestFn()
|
|
|
|
+ actions.logout()
|
|
break
|
|
break
|
|
case 403:
|
|
case 403:
|
|
errMessage = '拒绝访问'
|
|
errMessage = '拒绝访问'
|
|
@@ -39,10 +44,8 @@ const handleNetworkError = (response: AxiosResponse) => {
|
|
break
|
|
break
|
|
case 424:
|
|
case 424:
|
|
errMessage = 'token无效'
|
|
errMessage = 'token无效'
|
|
- // abortRequestFn()
|
|
|
|
- // logoutFn()
|
|
|
|
- actions.clearUserInfoAndToken()
|
|
|
|
- navigate('/login')
|
|
|
|
|
|
+ abortRequestFn()
|
|
|
|
+ actions.logout()
|
|
break
|
|
break
|
|
case 500:
|
|
case 500:
|
|
errMessage = '服务器端出错'
|
|
errMessage = '服务器端出错'
|
|
@@ -79,6 +82,17 @@ const handleNetworkError = (response: AxiosResponse) => {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 请求集合
|
|
|
|
+const requestMap = new Map<string, AbortController>()
|
|
|
|
+
|
|
|
|
+// 中止请求
|
|
|
|
+const abortRequestFn = () => {
|
|
|
|
+ for (const [mapKey, controller] of requestMap) {
|
|
|
|
+ controller.abort() // 中止
|
|
|
|
+ requestMap.delete(mapKey) // 清除
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
// 创建 axios 实例
|
|
// 创建 axios 实例
|
|
const axiosInstance = axios.create({
|
|
const axiosInstance = axios.create({
|
|
baseURL: BASE_URL,
|
|
baseURL: BASE_URL,
|
|
@@ -88,6 +102,13 @@ const axiosInstance = axios.create({
|
|
// 请求拦截
|
|
// 请求拦截
|
|
axiosInstance.interceptors.request.use(
|
|
axiosInstance.interceptors.request.use(
|
|
(config) => {
|
|
(config) => {
|
|
|
|
+ // 收集所有请求
|
|
|
|
+ const mapKey = nanoid()
|
|
|
|
+ const controller = new AbortController()
|
|
|
|
+ config.signal = controller.signal
|
|
|
|
+ config.nanoid = mapKey
|
|
|
|
+ requestMap.set(mapKey, controller)
|
|
|
|
+
|
|
const { tenant_id, access_token } = useUserSessionStore.getState()
|
|
const { tenant_id, access_token } = useUserSessionStore.getState()
|
|
const isToken = (config.headers || {}).isToken === false
|
|
const isToken = (config.headers || {}).isToken === false
|
|
if (access_token && !isToken) {
|
|
if (access_token && !isToken) {
|
|
@@ -120,6 +141,9 @@ axiosInstance.interceptors.request.use(
|
|
// 响应拦截
|
|
// 响应拦截
|
|
axiosInstance.interceptors.response.use(
|
|
axiosInstance.interceptors.response.use(
|
|
(res) => {
|
|
(res) => {
|
|
|
|
+ const mapKey = res.config.nanoid
|
|
|
|
+ requestMap.delete(mapKey as string)
|
|
|
|
+
|
|
if (!res.data) throw new Error(t('sys.api.apiRequestFailed'))
|
|
if (!res.data) throw new Error(t('sys.api.apiRequestFailed'))
|
|
const { data, status, statusText } = res
|
|
const { data, status, statusText } = res
|
|
|
|
|
|
@@ -133,6 +157,9 @@ axiosInstance.interceptors.response.use(
|
|
throw new Error(statusText || t('sys.api.apiRequestFailed'))
|
|
throw new Error(statusText || t('sys.api.apiRequestFailed'))
|
|
},
|
|
},
|
|
(err) => {
|
|
(err) => {
|
|
|
|
+ // 清除当前请求
|
|
|
|
+ const mapKey = err.config.nanoid
|
|
|
|
+ requestMap.delete(mapKey as string)
|
|
handleNetworkError(err.response)
|
|
handleNetworkError(err.response)
|
|
if (err.response) {
|
|
if (err.response) {
|
|
// 请求已发出, 服务器用状态码响应
|
|
// 请求已发出, 服务器用状态码响应
|