108 lines
3.5 KiB
TypeScript
108 lines
3.5 KiB
TypeScript
import axios, { AxiosResponse, AxiosRequestConfig, Axios, AxiosError, InternalAxiosRequestConfig } from 'axios'
|
||
import { RequestHttpHeaderEnum, ResultEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||
import { PageEnum, ErrorPageNameMap } from '@/enums/pageEnum'
|
||
import { StorageEnum } from '@/enums/storageEnum'
|
||
import { axiosPre } from '@/settings/httpSetting'
|
||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
|
||
import { fetchAllowList, ftsList } from './axios.config'
|
||
import includes from 'lodash/includes'
|
||
|
||
export interface MyResponseType<T> {
|
||
code: ResultEnum
|
||
data?: T
|
||
details?: T
|
||
message: string
|
||
timeseq?: number
|
||
}
|
||
|
||
export interface MyRequestInstance extends Axios {
|
||
<T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
|
||
}
|
||
|
||
const axiosInstance = axios.create({
|
||
// iframe 嵌入模式:直接请求后端地址,不使用代理
|
||
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : import.meta.env.VITE_DEV_PATH}${axiosPre}`,
|
||
timeout: ResultEnum.TIMEOUT
|
||
}) as unknown as MyRequestInstance
|
||
|
||
axiosInstance.interceptors.request.use(
|
||
(config: InternalAxiosRequestConfig) => {
|
||
// fts 接口特殊处理:使用完整路径,不添加 /Visual/v1 前缀
|
||
if (config.url && includes(ftsList, config.url)) {
|
||
const baseUrl = import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : import.meta.env.VITE_DEV_PATH
|
||
config.baseURL = baseUrl
|
||
}
|
||
|
||
// 获取 token 并添加到所有请求
|
||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||
if (info) {
|
||
const userInfo = info[SystemStoreEnum.USER_INFO]
|
||
if (userInfo && userInfo[SystemStoreUserInfoEnum.USER_TOKEN]) {
|
||
config.headers['authorization'] = userInfo[SystemStoreUserInfoEnum.USER_TOKEN]
|
||
}
|
||
}
|
||
|
||
return config
|
||
},
|
||
(err: AxiosError) => {
|
||
Promise.reject(err)
|
||
}
|
||
)
|
||
|
||
// 响应拦截器
|
||
axiosInstance.interceptors.response.use(
|
||
(res: AxiosResponse) => {
|
||
// 统一处理后台返回 details 字段的情况,将其转换为 data 字段
|
||
const { code, details, message } = res.data as { code: number; details?: any; message?: string }
|
||
const responseData = details !== undefined
|
||
? { code, message, data: details }
|
||
: res.data
|
||
|
||
// 预览页面错误不进行处理
|
||
if (isPreview()) {
|
||
return Promise.resolve(responseData)
|
||
}
|
||
|
||
if (code === undefined || code === null) return Promise.resolve(responseData)
|
||
|
||
// 成功
|
||
if (code === ResultEnum.SUCCESS) {
|
||
return Promise.resolve(responseData)
|
||
}
|
||
|
||
// 登录过期
|
||
if (code === ResultEnum.TOKEN_OVERDUE) {
|
||
window['$message'].error(window['$t']('http.token_overdue_message'))
|
||
// iframe 嵌入模式下,token 过期不重定向到登录页
|
||
console.error('[GoView] iframe 模式:token 已过期,请更新 URL 中的 token 参数')
|
||
return Promise.resolve(responseData)
|
||
}
|
||
|
||
// 固定错误码重定向
|
||
if (ErrorPageNameMap.get(code)) {
|
||
redirectErrorPage(code)
|
||
return Promise.resolve(responseData)
|
||
}
|
||
|
||
// 提示错误
|
||
window['$message'].error(window['$t']((res.data as any).msg || message))
|
||
return Promise.resolve(responseData)
|
||
},
|
||
(err: AxiosError) => {
|
||
const status = err.response?.status
|
||
switch (status) {
|
||
case 401:
|
||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||
Promise.reject(err)
|
||
break
|
||
|
||
default:
|
||
Promise.reject(err)
|
||
break
|
||
}
|
||
}
|
||
)
|
||
|
||
export default axiosInstance
|