单应用项目,可以创建很多独立工具类页面 ,不用登录 初始化的页面
zhangchen
2025-09-16 a99886eb9c73018235e2c373f3d82a2b0b2311d5
src/utils/axios.ts
New file
@@ -0,0 +1,134 @@
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import Qs from 'qs'
import { useBedsideAuxiliaryScreenStore } from '@/store/bedsideAuxiliaryScreen'
import { ElMessage } from 'element-plus/es'
// ====== 配置 ======
const BASE_URL = import.meta.env.VITE_API_BASE_URL
const TIME_OUT = 60 * 1 * 1000
// 正在进行中的请求列表,避免重复请求
let reqList: string[] = []
/**
 * 允许某个请求再次发送
 */
const allowRequest = (url?: string) => {
  if (!url) return
  const idx = reqList.indexOf(url)
  if (idx > -1) reqList.splice(idx, 1)
}
/**
 * 创建 axios 实例
 */
const instance = axios.create({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
  paramsSerializer: (params) => Qs.stringify(params, { arrayFormat: 'brackets' }),
})
// ====== 错误处理函数 ======
const errorHandle = (status: number, error: any): void => {
  const msg = error?.msg || error?.message || ''
  switch (status) {
    case 401:
      ElMessage.error(`Error Code: 401, Message: ${msg || '登录失效,请重新登录'}`);
      break
    case 403:
      ElMessage.error(`Error Code: 403, Message: ${msg || '你没有访问权限'}`);
      break
    case 500:
      ElMessage.error(`Error Code: 500, Message: ${msg || '后台错误,请联系管理员'}`);
      break
    case 502:
      alert()
      ElMessage.error(`Error Code: 502, Message: ${msg || '平台环境异常'}`);
      break
    default:
      ElMessage.error(`Error Code: ${status}, Message: ${msg || '未知错误,请刷新重试'}`);
  }
}
// ====== 请求拦截 ======
instance.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const store = useBedsideAuxiliaryScreenStore()
    // 加 token
    if (store.userInfo?.token) {
      config.headers.set('Authorization', `Bearer ${store.userInfo.token}`)
    }
    // 防止同一接口短时间内重复请求
    if (config.url) {
      if (reqList.includes(config.url)) {
        // return Promise.reject(new axios.Cancel(`重复请求:${config.url}`))
      } else {
        reqList.push(config.url)
      }
    }
    return config
  },
  (error) => Promise.reject(error),
)
// ====== 响应拦截 ======
instance.interceptors.response.use(
  (res: AxiosResponse) => {
    // setTimeout(() => allowRequest(res.config.url), 1000)
    if (String(res.status).charAt(0) !== '2') {
      return Promise.reject({
        code: res.status,
        message: res.data?.message || '请求异常,请刷新重试',
      })
    }
    if (res.data?.code === 200) return res.data
    const whiteList: string[] = []
    const requestUrl: string = res?.config?.url || ''
    const isInWhiteList = whiteList.some((item) => requestUrl.includes(item))
    ElMessage.error(res.data.message);
    if (isInWhiteList) return Promise.reject(res.data)
    return Promise.reject(res.data)
  },
  (err: unknown) => {
    const anyErr = err as any
    const configUrl = anyErr?.config?.url
    // 失败后 1s 允许再次请求
    // setTimeout(() => allowRequest(configUrl), 1000)
    // 先判断是否是取消请求
    // if (axios.isCancel(err as any)) {
    //   console.warn('请求被取消:', (err as any)?.message)
    //   return Promise.reject(err)
    // }
    // 判断是否为 axios 的错误类型(有 response)
    if (axios.isAxiosError(err)) {
      const axErr = err // 现在 TypeScript 知道这是 AxiosError
      if (axErr.response) {
        // 使用你现有的错误处理函数
        errorHandle(axErr.response.status, axErr.response.data)
        if (axErr.response.status === 401) {
            ElMessage.error('请登录');
        }
        return Promise.reject(axErr.response.data || axErr.response)
      }
      ElMessage.error('网络请求失败, 请刷新重试');
      return Promise.reject(axErr)
    }
    //(未知错误)
    ElMessage.error('网络请求失败, 请刷新重试');
    return Promise.reject(err)
  },
)
export default instance