Files
FlashSaleSystem/community-fresh-group-buy-frontend/src/api/request.ts
2026-05-06 23:30:54 +08:00

155 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import axios, {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios'
import {ElMessage, ElMessageBox} from 'element-plus'
import {useUserStore} from '@/stores/user'
import router from '@/router'
// 创建axios实例
const service: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || '',
withCredentials: true,
timeout: Number(import.meta.env.VITE_TIMEOUT) || 10000,
headers: {
'Content-Type': 'application/json',
},
})
// 请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const userStore = useUserStore()
// 添加token
if (userStore.token) {
config.headers = config.headers || {}
config.headers['Authorization'] = `Bearer ${userStore.token}`
}
return config
},
(error) => {
console.error('请求错误:', error)
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
const res = response.data
if (typeof res?.success === 'boolean') {
if (!res.success) {
if (response.status === 401) {
ElMessage.error(res.message || '登录状态已失效')
} else {
ElMessage.error(res.message || '请求失败')
}
return Promise.reject(new Error(res.message || '请求失败'))
}
return res
}
// 自定义状态码处理
if (res.code !== 200 && res.code !== 0) {
// 业务错误
if (res.code === 401) {
// 未登录或token失效
ElMessageBox.confirm('登录已过期,请重新登录', '提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
const userStore = useUserStore()
userStore.logout()
router.push('/login')
})
} else if (res.code === 403) {
// 无权限
ElMessage.error('无权限访问')
} else {
// 其他业务错误
ElMessage.error(res.message || '请求失败')
}
return Promise.reject(new Error(res.message || '请求失败'))
}
return res
},
(error) => {
console.error('响应错误:', error)
// 提取后端返回的业务错误消息
const bizMessage = error.response?.data?.message
let displayMessage = ''
if (error.response) {
switch (error.response.status) {
case 400:
// 业务错误(如"该团组已满员"),只显示后端返回的消息
displayMessage = bizMessage || '请求参数错误'
break
case 401:
displayMessage = '未授权,请登录'
break
case 403:
displayMessage = '拒绝访问'
break
case 404:
displayMessage = '请求地址不存在'
break
case 429:
displayMessage = '请求过于频繁,请稍后再试'
break
case 500:
displayMessage = '服务器内部错误'
break
default:
displayMessage = bizMessage || '请求失败'
}
} else if (error.request) {
displayMessage = '网络错误,请检查网络连接'
} else {
displayMessage = '请求配置错误'
}
ElMessage.error(displayMessage)
// 用业务消息替换原始 axios error message避免组件 catch 显示 "Request failed with status code 400"
const rejectError = new Error(displayMessage)
;(rejectError as any)._handled = true
return Promise.reject(rejectError)
}
)
// 通用请求方法
export const request = {
get<T = any>(url: string, params?: any): Promise<T> {
return service.get(url, {params})
},
post<T = any>(url: string, data?: any): Promise<T> {
return service.post(url, data)
},
put<T = any>(url: string, data?: any): Promise<T> {
return service.put(url, data)
},
delete<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return service.delete(url, {
...config,
data,
})
},
}
export default service