单应用项目,可以创建很多独立工具类页面 ,不用登录 初始化的页面
zhangchen
2025-09-16 d2e8c18bcd879303a1df45079a906f561cd5d3d3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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