73 lines
1.6 KiB
TypeScript
Raw Normal View History

/**
* HTTP
* - Authorization token
* -
* -
*/
const API_BASE = import.meta.env.VITE_API_BASE || '/pms/api';
export interface ApiResponse<T = unknown> {
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<T>(
url: string,
options: RequestInit = {},
): Promise<ApiResponse<T>> {
const token = getToken();
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...(options.headers as Record<string, string>),
};
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: <T>(url: string) => request<T>(url),
post: <T>(url: string, data?: unknown) =>
request<T>(url, { method: 'POST', body: JSON.stringify(data) }),
put: <T>(url: string, data?: unknown) =>
request<T>(url, { method: 'PUT', body: JSON.stringify(data) }),
delete: <T>(url: string) => request<T>(url, { method: 'DELETE' }),
};