You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.1 KiB
TypeScript

1 month ago
// utils/apiClient.ts
import { ofetch } from 'ofetch'
import { CookieManager } from './cookieManager'
import { STORAGE_KEYS } from '~/utils/storageKeys';
import { AuthService } from '~/services/authService';
// 创建API客户端实例
class ApiClient {
private baseUrl: string = '/api' // 默认值
// 设置基础URL的公共方法
setBaseUrl() {
const config = useRuntimeConfig();
this.baseUrl = config.public.apiBaseUrl || '/api';
}
private buildUrl(url: string): string {
this.setBaseUrl();
const basePath = this.baseUrl.replace(/\/$/, '')
const apiPath = url.startsWith('/') ? url : '/' + url
return basePath + apiPath
}
// 通用请求方法
private async request<T>(
url: string,
options: any = {}
): Promise<T> {
const fullUrl = this.buildUrl(url)
// AuthService.getAuthToken();
// 自动添加认证头
let token = AuthService.getAuthToken();
if (import.meta.client && !token) {
token = localStorage.getItem(STORAGE_KEYS.GLOBAL_TOKEN);
}
// CookieManager.get(STORAGE_KEYS.GLOBAL_TOKEN)
console.log('API Request:', fullUrl, options, token)
if (token && !options.headers?.Authorization) {
options.headers = {
...options.headers,
Authorization: `Bearer ${token}`
}
}
try {
const response = await ofetch<T>(fullUrl, {
...options,
// 默认配置
retry: 0, // 开发环境不重试
timeout: 30000, // 30秒超时
onResponse({ response }) {
// 响应拦截器
// if (response.status === 401) {
// console.warn('Authentication required')
// }
},
onResponseError({ response }) {
// 响应错误拦截器
console.error(`API Error: ${fullUrl} -- ${response}`)
}
})
return response
} catch (error: any) {
// 统一错误处理
if (error.name === 'FetchError') {
throw new Error(`网络请求失败: ${error.message}`)
}
throw error
}
}
// GET请求
async get<T>(url: string, options: any = {}): Promise<T> {
return this.request<T>(url, {
...options,
method: 'GET'
})
}
// POST请求
async post<T>(url: string, data?: any, options: any = {}): Promise<T> {
return this.request<T>(url, {
...options,
method: 'POST',
body: data
})
}
// PUT请求
async put<T>(url: string, data?: any, options: any = {}): Promise<T> {
return this.request<T>(url, {
...options,
method: 'PUT',
body: data
})
}
// DELETE请求
async delete<T>(url: string, data?: any, options: any = {}): Promise<T> {
return this.request<T>(url, {
...options,
method: 'DELETE',
body: data
})
}
// PATCH请求
async patch<T>(url: string, data?: any, options: any = {}): Promise<T> {
return this.request<T>(url, {
...options,
method: 'PATCH',
body: data
})
}
}
// 导出单例实例
export const apiClient = new ApiClient()
// 也可以导出ofetch实例供直接使用
export { ofetch }