// 基础API请求封装 class ApiClient { constructor(baseURL = '', options = {}) { this.baseURL = baseURL this.timeout = options.timeout || 30000 // 改为30秒 this.headers = { // 不要默认设置Content-Type,避免触发预检请求 ...options.headers } } // 基础请求方法 async request(url, options = {}) { const controller = new AbortController() const timeoutId = setTimeout(() => controller.abort(), this.timeout) try { const fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}` // 对于所有请求,都不要添加默认的Content-Type头部,避免触发预检请求 const fetchOptions = { signal: controller.signal, ...options } const response = await fetch(fullUrl, fetchOptions) clearTimeout(timeoutId) if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`) } const contentType = response.headers.get('content-type') if (contentType && contentType.includes('application/json')) { return await response.json() } return await response.text() } catch (error) { clearTimeout(timeoutId) if (error.name === 'AbortError') { throw new Error('请求超时') } // 处理CORS错误,重新抛出错误让上层处理 if (error.toString().includes('CORS') || error.toString().includes('Failed to fetch')) { console.error('CORS错误:', url, error) throw new Error('网络请求失败,请检查网络连接') } throw error } } // GET请求 get(url, params = {}) { let fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}` // 统一使用手动构建查询字符串的方式,避免URL对象可能带来的问题 const queryString = Object.entries(params) .filter(([_, value]) => value !== undefined && value !== null) .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`) .join('&') fullUrl = queryString ? `${fullUrl}?${queryString}` : fullUrl return this.request(fullUrl, { method: 'GET' }) } // POST请求 post(url, data = {}) { return this.request(url, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.headers }, body: JSON.stringify(data) }) } // PUT请求 put(url, data = {}) { return this.request(url, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...this.headers }, body: JSON.stringify(data) }) } // DELETE请求 delete(url) { return this.request(url, { method: 'DELETE' }) } } // 创建默认实例 export const apiClient = new ApiClient() // 导出类以便创建自定义实例 export { ApiClient }