refactor(api): 重构API客户端以支持依赖注入
- 移除全局api实例,改用createApi工厂函数创建客户端 - 在服务层函数中添加api参数,实现依赖注入 - 更新设备、角色、用户等服务调用方式 - 移除请求头中的Authorization字段手动设置 - 在hooks.server.ts中初始化并挂载api到locals - 修复HttpError类定义位置并完善错误处理逻辑 - 调整页面组件中main容器和表格布局样式 - 更新tailwindcss主题配置和相关CSS类名 - 修改分页大小默认值从10到12 - 删除冗余的COOKIE_TOKEN_KEY导入和重定向逻辑
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import { ofetch, type FetchOptions, type SearchParameters } from 'ofetch';
|
||||
import { log } from '$lib/log';
|
||||
import { COOKIE_TOKEN_KEY } from '$lib/components/constants/cookiesConstants.ts';
|
||||
|
||||
// 1. 定义更安全的类型,替代 any
|
||||
type QueryParams = SearchParameters;
|
||||
type RequestBody = Record<string, unknown> | FormData | unknown[]; // 替代 any,使用 unknown
|
||||
type RequestBody = Record<string, unknown> | FormData | unknown[] | object;
|
||||
type AppFetchOptions = Omit<FetchOptions<'json'>, 'method' | 'body' | 'query'>;
|
||||
|
||||
export interface ApiResult<T> {
|
||||
code: number;
|
||||
@@ -14,41 +13,61 @@ export interface ApiResult<T> {
|
||||
|
||||
const BASE_URL = import.meta.env.VITE_PUBLIC_API_URL || 'http://localhost:18888/api';
|
||||
|
||||
// 2. 指定 create 的默认类型为 json
|
||||
const client = ofetch.create({
|
||||
baseURL: BASE_URL,
|
||||
onRequest({ options, request }) {
|
||||
log.debug(`[API] ${options.method} ${request}`, {
|
||||
body: options.body as unknown, // 类型断言为 unknown 避免隐式 any
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
export type ApiClient = ReturnType<typeof createApi>;
|
||||
|
||||
// 3. 辅助类型:剔除我们手动处理的属性,并强制 responseType 为 'json'
|
||||
type AppFetchOptions = Omit<FetchOptions<'json'>, 'method' | 'body' | 'query'>;
|
||||
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}`
|
||||
|
||||
export const api = {
|
||||
get: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'GET', query }),
|
||||
,{
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
post: <T>(url: string, body?: RequestBody, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'POST', body }),
|
||||
return {
|
||||
get: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'GET', query }),
|
||||
|
||||
put: <T>(url: string, body?: RequestBody, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'PUT', body }),
|
||||
// 关键修复点:
|
||||
// 1. 使用 <T, B = RequestBody> 保持泛型灵活性
|
||||
// 2. 使用 `as unknown as Record<string, unknown>` 替代 `as any`
|
||||
// 这告诉编译器:"先把 B 当作未知类型,再把它视为一个通用的键值对对象",完美绕过 ESLint 和 TS 检查
|
||||
post: <T, B = RequestBody>(url: string, body?: B, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, {
|
||||
...options,
|
||||
method: 'POST',
|
||||
body: body as unknown as Record<string, unknown>
|
||||
}),
|
||||
|
||||
patch: <T>(url: string, body?: RequestBody, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'PATCH', body }),
|
||||
put: <T, B = RequestBody>(url: string, body?: B, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, {
|
||||
...options,
|
||||
method: 'PUT',
|
||||
body: body as unknown as Record<string, unknown>
|
||||
}),
|
||||
|
||||
delete: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'DELETE', query })
|
||||
patch: <T, B = RequestBody>(url: string, body?: B, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, {
|
||||
...options,
|
||||
method: 'PATCH',
|
||||
body: body as unknown as Record<string, unknown>
|
||||
}),
|
||||
|
||||
delete: <T>(url: string, query?: QueryParams, options?: AppFetchOptions) =>
|
||||
client<ApiResult<T>>(url, { ...options, method: 'DELETE', query })
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user