import type { AxiosError, InternalAxiosRequestConfig } from 'axios' import axios from 'axios' import { showNotify } from 'vant' import { localStorage } from '@/utils/local-storage' import { STORAGE_TOKEN_KEY } from '@/stores/mutation-type' // 这里是用于设定请求后端时,所用的 Token KEY // 可以根据自己的需要修改,常见的如 Access-Token,Authorization // 需要注意的是,请尽量保证使用中横线`-` 来作为分隔符, // 避免被 nginx 等负载均衡器丢弃了自定义的请求头 export const REQUEST_TOKEN_KEY = 'Authorization' // 创建 axios 实例 const request = axios.create({ // API 请求的默认前缀 baseURL: process.env.VUE_APP_API_BASE_URL, // 上传/生图等接口常超过 6s;过短会导致旧业务也误超时 timeout: 30000, }) export type RequestError = AxiosError<{ message?: string result?: any errorMessage?: string }> // 异常拦截处理器 const errorHandler = (error: RequestError): Promise => { if (error.response) { const { data = {}, status, statusText } = error.response // 403 无权限 if (status === 403) { showNotify({ type: 'danger', message: (data && data.message) || statusText, }) } // 401 未登录/未授权 if (status === 401) { showNotify({ type: 'danger', message: (data && data.message) || '链接已失效,请联系平台客服', duration: 0 }) // 如果你需要直接跳转登录页面 // location.replace(loginRoutePath) } } return Promise.reject(error) } // 请求拦截器 const requestHandler = (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig | Promise => { // 从 localStorage 读取 code(刷新时也能获取到) const code = localStorage.get('code') const userId = localStorage.get('userId') // 让每个请求携带自定义 token, 请根据实际情况修改 if (code) { config.headers['Authorization'] = code } if (userId) { config.headers['Userid'] = userId } return config } // Add a request interceptor request.interceptors.request.use(requestHandler, errorHandler) function coerceJsonPayload(payload: any) { // 后端若用 text/plain 返回 JSON,axios 不会自动 parse,这里补一层 if (typeof payload !== 'string') return payload const text = payload.replace(/^\uFEFF/, '').trim() if (!text) return payload try { return JSON.parse(text) } catch { const start = text.indexOf('{') const end = text.lastIndexOf('}') if (start >= 0 && end > start) { try { return JSON.parse(text.slice(start, end + 1)) } catch { return payload } } return payload } } // 响应拦截器 const responseHandler = (response: { data: any }) => { if (!response?.data && response?.data !== 0 && response?.data !== false) return response // 兼容偶发双层:{ data: { code, data, message } } let payload = coerceJsonPayload(response.data) if ( payload && typeof payload === 'object' && payload.code == null && payload.data && typeof payload.data === 'object' && payload.data.code != null ) { payload = payload.data } if (!payload || typeof payload !== 'object') return payload const { code, data, message } = payload if (code == null || code === '') return payload // 兼容 code 为字符串 "1000" const numericCode = Number(code) if (numericCode === 1000) { if (Array.isArray(data)) { // transfter(data, timezone.info); } else if (data && data.list !== undefined && data.list?.length > 0) { // transfter(data.list, timezone.info); } return data } return Promise.reject(new Error(message || '请求失败')) } // Add a response interceptor request.interceptors.response.use(responseHandler, errorHandler) export default request