/** * HTTP 请求封装 * - 自动注入 Authorization token * - 统一异常处理 * - 类型友好的响应 */ const API_BASE = import.meta.env.VITE_API_BASE || '/pms/api'; export interface ApiResponse { code: number; data: T; message: string; } export class ApiError extends Error { public code: number; constructor( code: number, message: string, ) { super(message); this.name = 'ApiError'; this.code = code; } } function getToken(): string | null { return localStorage.getItem('token'); } async function request( url: string, options: RequestInit = {}, ): Promise> { const token = getToken(); const headers: Record = { 'Content-Type': 'application/json', ...(options.headers as Record), }; if (token) { headers['Authorization'] = `Bearer ${token}`; } try { const res = await fetch(`${API_BASE}${url}`, { ...options, headers, }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new ApiError(res.status, body.message || res.statusText); } return res.json(); } catch (err) { if (err instanceof ApiError) throw err; throw new ApiError(0, (err as Error).message || '网络错误'); } } export const api = { get: (url: string) => request(url), post: (url: string, data?: unknown) => request(url, { method: 'POST', body: JSON.stringify(data) }), put: (url: string, data?: unknown) => request(url, { method: 'PUT', body: JSON.stringify(data) }), delete: (url: string) => request(url, { method: 'DELETE' }), };