Files
asset_helper/frontend/src/api/client.ts
2026-04-26 14:40:55 +08:00

96 lines
2.4 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, { AxiosError, type AxiosInstance, type AxiosRequestConfig } from 'axios'
import { Device, Language, type ApiRequest, type ApiResponse, type ErrorResponse } from '@/types/api'
import { useAuthStore } from '@/stores/auth'
// 根据环境选择基础地址
// Docker 开发环境Vite proxy 会将 /api 转发到后端
// 生产环境Nginx 代理 /api 到后端网关
const baseURL = import.meta.env.DEV ? '/' : '/api'
const client: AxiosInstance = axios.create({
baseURL,
timeout: 30000,
headers: {
'Content-Type': 'application/json',
},
})
// 请求拦截器:注入 JWT
client.interceptors.request.use((config) => {
const token = useAuthStore.getState().token
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器:统一错误处理
client.interceptors.response.use(
(response) => response,
(error: AxiosError<ErrorResponse>) => {
const status = error.response?.status
const message = error.response?.data?.message || error.message || '请求失败'
if (status === 401) {
useAuthStore.getState().logout()
window.location.href = '/login'
}
return Promise.reject(new Error(message))
}
)
/** 包装业务请求(注册/业务类接口) */
export async function apiPost<TReq, TRes>(
url: string,
data: TReq,
config?: AxiosRequestConfig
): Promise<TRes> {
const body: ApiRequest<TReq> = {
device: Device.Web,
language: Language.SimplifiedChinese,
data,
}
const response = await client.post<ApiResponse<TRes>>(url, body, config)
const result = response.data
if (!result.success) {
throw new Error(result.message)
}
if (result.data === null) {
throw new Error('接口返回数据为空')
}
return result.data
}
/** 原始 POST登录/认证类接口,不包装) */
export async function rawPost<TReq, TRes>(
url: string,
data: TReq,
config?: AxiosRequestConfig
): Promise<TRes> {
const response = await client.post<TRes>(url, data, config)
return response.data
}
/** 通用 GET */
export async function apiGet<TRes>(url: string, config?: AxiosRequestConfig): Promise<TRes> {
const response = await client.get<ApiResponse<TRes>>(url, config)
const result = response.data
if (!result.success) {
throw new Error(result.message)
}
if (result.data === null) {
throw new Error('接口返回数据为空')
}
return result.data
}
export default client