/** * Axios封装 - HTTP请求 */ import axios from 'axios' import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios' import { showToast } from 'vant' import { storage } from '@/utils/storage' import { API_URL, TENANT_ID } from '@/config' import router from '@/router' import { getImageUrl } from '@/utils/image' // 创建axios实例 const request: AxiosInstance = axios.create({ baseURL: API_URL, timeout: 10000, headers: { 'Content-Type': 'application/json', 'tenant-id': TENANT_ID } }) // 请求拦截器 request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { // 添加token const token = storage.get('accessToken') if (token) { config.headers.Authorization = `Bearer ${token}` } // 游客模式: 添加 deviceId header const guestDeviceId = storage.get('guestDeviceId') const guestToken = storage.get('guestToken') if (guestDeviceId) { config.headers['X-Device-Id'] = guestDeviceId } // 游客Token优先(如果已登录游客) if (guestToken && !token) { config.headers.Authorization = `Bearer ${guestToken}` } return config }, (error: any) => { console.error('Request error:', error) return Promise.reject(error) } ) // 响应拦截器 request.interceptors.response.use( (response: AxiosResponse) => { const { data } = response // 处理图片URL if (data && typeof data === 'object') { processImageUrls(data) } // 未登录 if (data.code === 401) { showToast('未登录') storage.remove('accessToken') router.push('/login') return Promise.reject(new Error('未登录')) } // 微信授权相关 if (data.code === 1004004002) { // 处理微信授权 const indexUrl = storage.get('index_url') if (indexUrl && typeof window !== 'undefined') { window.location.href = indexUrl } return Promise.reject(new Error('需要微信授权')) } // 请求失败 if (data.code !== 0) { showToast(data.msg || '请求失败') return Promise.reject(new Error(data.msg || '请求失败')) } // 返回数据 return data.data }, (error: any) => { console.error('Response error:', error) // 开发环境下,如果是演示模式(无后端),不显示错误提示 const isDev = import.meta.env.DEV const isNetworkError = error.code === 'ERR_NETWORK' || error.code === 'ERR_BAD_RESPONSE' if (error.response) { // 服务器返回错误 const { status, data } = error.response if (status === 401) { showToast('未登录') storage.remove('accessToken') router.push('/login') } else if (status === 403) { showToast('没有权限') } else if (status === 404) { !isDev && showToast('请求的资源不存在') } else if (status === 500) { // 开发环境下的500错误不提示(演示模式) !isDev && showToast('服务器错误') } else { !isDev && showToast(data.msg || '请求失败') } } else if (error.request) { // 请求已发出但没有收到响应(开发环境下不提示) if (!isDev || !isNetworkError) { showToast('网络错误,请检查网络连接') } } else { // 其他错误 !isDev && showToast(error.message || '请求失败') } return Promise.reject(error) } ) /** * 递归处理对象中的图片URL */ function processImageUrls(obj: any) { if (!obj || typeof obj !== 'object') return // 处理数组 if (Array.isArray(obj)) { obj.forEach((item) => processImageUrls(item)) return } // 处理对象 for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { // 判断是否为图片字段 if ( typeof obj[key] === 'string' && (key.includes('image') || key.includes('img') || key.includes('pic') || key.includes('avatar') || key.includes('cover') || key.includes('thumb')) ) { // 处理图片URL obj[key] = getImageUrl(obj[key]) } // 递归处理嵌套对象 else if (obj[key] && typeof obj[key] === 'object') { processImageUrls(obj[key]) } } } } export default request