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 { code: ResultEnum data?: T details?: T message: string timeseq?: number } export interface MyRequestInstance extends Axios { (config: AxiosRequestConfig): Promise> } 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