|
|
|
|
|
class ApiClient { |
|
|
constructor(baseURL = '', options = {}) { |
|
|
this.baseURL = baseURL |
|
|
this.timeout = options.timeout || 30000 |
|
|
this.headers = { |
|
|
|
|
|
...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}` |
|
|
|
|
|
|
|
|
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('请求超时') |
|
|
} |
|
|
|
|
|
|
|
|
if (error.toString().includes('CORS') || error.toString().includes('Failed to fetch')) { |
|
|
console.error('CORS错误:', url, error) |
|
|
throw new Error('网络请求失败,请检查网络连接') |
|
|
} |
|
|
|
|
|
throw error |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
get(url, params = {}) { |
|
|
let fullUrl = url.startsWith('http') ? url : `${this.baseURL}${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(url, data = {}) { |
|
|
return this.request(url, { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
...this.headers |
|
|
}, |
|
|
body: JSON.stringify(data) |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
put(url, data = {}) { |
|
|
return this.request(url, { |
|
|
method: 'PUT', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
...this.headers |
|
|
}, |
|
|
body: JSON.stringify(data) |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
delete(url) { |
|
|
return this.request(url, { |
|
|
method: 'DELETE' |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
export const apiClient = new ApiClient() |
|
|
|
|
|
|
|
|
export { ApiClient } |