import { ofetch, type FetchOptions, type SearchParameters } from 'ofetch'; import { log } from '$lib/log'; type QueryParams = SearchParameters; type RequestBody = Record | FormData | unknown[] | object; type AppFetchOptions = Omit, 'method' | 'body' | 'query'>; export interface ApiResult { code: number; msg: string; data: T; } const BASE_URL = import.meta.env.VITE_PUBLIC_API_URL || 'http://localhost:18888/api'; export type ApiClient = ReturnType; export const createApi = (token?: string) => { const client = ofetch.create({ baseURL: BASE_URL, // 建议:通常 Token 前面需要加 Bearer headers: token ? { Authorization: token } : {}, onRequest({ options, request }) { log.debug(`[API] ${options.method} ${request}` ,{ body: options.body as unknown, headers: options.headers, query: options.query }); }, onResponseError({ request, response }) { log.error(`[API] Error ${request}`, { status: response.status, headers: response.headers, data: response._data as unknown }); } }); return { get: (url: string, query?: QueryParams, options?: AppFetchOptions) => client>(url, { ...options, method: 'GET', query }), // 关键修复点: // 1. 使用 保持泛型灵活性 // 2. 使用 `as unknown as Record` 替代 `as any` // 这告诉编译器:"先把 B 当作未知类型,再把它视为一个通用的键值对对象",完美绕过 ESLint 和 TS 检查 post: (url: string, body?: B, options?: AppFetchOptions) => client>(url, { ...options, method: 'POST', body: body as unknown as Record }), put: (url: string, body?: B, options?: AppFetchOptions) => client>(url, { ...options, method: 'PUT', body: body as unknown as Record }), patch: (url: string, body?: B, options?: AppFetchOptions) => client>(url, { ...options, method: 'PATCH', body: body as unknown as Record }), delete: (url: string, query?: QueryParams, options?: AppFetchOptions) => client>(url, { ...options, method: 'DELETE', query }) }; };