feat(image): 新建 knowai-core:1.0.0 镜像并完成推送
Some checks reported errors
continuous-integration/drone/push Build was killed

- 搭建 api、auth、utils 等逻辑模块
- 通过 tsc、eslint、vitest 测试验证

BREAKING CHANGE: 新镜像分支
This commit is contained in:
tobegold574
2025-11-10 20:20:25 +08:00
commit 6a81b7bb13
73 changed files with 10511 additions and 0 deletions

57
api/README.md Normal file
View File

@@ -0,0 +1,57 @@
# API 模块
## 概述
API 模块提供统一的HTTP客户端和API请求处理功能支持模块化的API端点管理。
## 核心组件
1. **API 客户端 (client.ts)**
- 基于Axios的HTTP客户端
- 提供统一的请求和响应处理
- 支持请求拦截器和响应拦截器
2. **API 工厂 (factory.ts)**
- 创建API客户端实例
- 配置默认请求选项
- 提供单例模式确保全局一致性
3. **API 模块 (modules/)**
- 按功能模块组织API端点
- 提供类型安全的API方法
- 包含用户、聊天等业务模块
4. **类型定义 (types.d.ts)**
- 定义API相关的接口和类型
- 包含请求配置和响应格式
5. **错误处理 (errors.ts)**
- 定义API相关的错误类
- 提供错误处理和转换功能
## 使用方法
```typescript
import { createApiClient } from './api';
// 创建API客户端
const apiClient = createApiClient({
baseURL: 'https://api.example.com',
timeout: 10000,
});
// 使用API模块
import { userApi } from './api/modules/user';
// 获取用户信息
const user = await userApi.getUser('userId');
// 更新用户信息
await userApi.updateUser('userId', { name: 'New Name' });
```
## 设计模式
- **工厂模式**创建API客户端实例
- **单例模式**确保API客户端全局唯一
- **模块化模式**按功能组织API端点

279
api/client.ts Normal file
View File

@@ -0,0 +1,279 @@
import axios from 'axios';
import type { ApiClient } from './types';
import type { AxiosError, AxiosResponse, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
import { ApiError } from './errors'; // 直接导入ApiError
// 创建API客户端实例的工厂函数
const createApiClientInstance = (config?: Partial<AxiosRequestConfig>): ApiClient => {
// 创建axios实例
const instance = axios.create({
baseURL: '/api', // Core层使用默认值具体配置由Runtime层注入
timeout: 10000,
headers: {
'Content-Type': 'application/json'
},
withCredentials: true, // 允许跨域携带cookie
...config // 应用传入的配置
});
// 请求拦截器数组
const requestInterceptors: Array<number> = [];
// 响应拦截器数组
const responseInterceptors: Array<number> = [];
// 添加请求拦截器
const addRequestInterceptor = (
onFulfilled?: (_config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>,
onRejected?: (_error: unknown) => unknown
): number => {
const handler = instance.interceptors.request.use(onFulfilled, onRejected);
requestInterceptors.push(handler);
return handler;
};
// 添加响应拦截器
const addResponseInterceptor = (
onFulfilled?: (_response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>,
onRejected?: (_error: unknown) => unknown
): number => {
const handler = instance.interceptors.response.use(onFulfilled, onRejected);
responseInterceptors.push(handler);
return handler;
};
// 移除请求拦截器
const removeRequestInterceptor = (handler: number): void => {
const index = requestInterceptors.indexOf(handler);
if (index !== -1) {
instance.interceptors.request.eject(handler);
requestInterceptors.splice(index, 1);
}
};
// 移除响应拦截器
const removeResponseInterceptor = (handler: number): void => {
const index = responseInterceptors.indexOf(handler);
if (index !== -1) {
instance.interceptors.response.eject(handler);
responseInterceptors.splice(index, 1);
}
};
// 设置默认配置
const setDefaults = (_config: Partial<AxiosRequestConfig>): void => {
Object.assign(instance.defaults, _config);
};
// 更新基础URL - 专门用于Runtime层配置
const setBaseURL = (baseURL: string): void => {
instance.defaults.baseURL = baseURL;
};
// 创建新实例 - 用于跨域请求等特殊场景
const createInstance = (config?: Partial<AxiosRequestConfig>): ApiClient => {
// 创建新的axios实例
const newInstance = axios.create({
...instance.defaults,
...config
});
// 为新实例创建拦截器数组
const newRequestInterceptors: Array<number> = [];
const newResponseInterceptors: Array<number> = [];
// 复制拦截器
requestInterceptors.forEach(handler => {
// 由于AxiosInterceptorManager类型定义中没有handlers属性
// 我们使用类型断言来访问内部属性
type RequestHandlerType = {
id: number;
fulfilled: (_config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig;
rejected: (_error: unknown) => unknown;
};
type RequestManagerType = {
handlers?: Array<RequestHandlerType>;
};
const requestManager = instance.interceptors.request as unknown as RequestManagerType;
const originalInterceptor = requestManager.handlers?.find((h: RequestHandlerType) => h.id === handler);
if (originalInterceptor) {
const newHandler = newInstance.interceptors.request.use(
originalInterceptor.fulfilled,
originalInterceptor.rejected
);
newRequestInterceptors.push(newHandler);
}
});
responseInterceptors.forEach(handler => {
// 由于AxiosInterceptorManager类型定义中没有handlers属性
// 我们使用类型断言来访问内部属性
type ResponseHandlerType = {
id: number;
fulfilled: (_response: AxiosResponse) => AxiosResponse;
rejected: (_error: AxiosError) => unknown;
};
type ResponseManagerType = {
handlers?: Array<ResponseHandlerType>;
};
const responseManager = instance.interceptors.response as unknown as ResponseManagerType;
const originalInterceptor = responseManager.handlers?.find((h: ResponseHandlerType) => h.id === handler);
if (originalInterceptor) {
const newHandler = newInstance.interceptors.response.use(
originalInterceptor.fulfilled,
originalInterceptor.rejected
);
newResponseInterceptors.push(newHandler);
}
});
// 返回一个符合ApiClient接口的对象
return {
request: async <T = unknown>(config: AxiosRequestConfig): Promise<T> => {
try {
const response = await newInstance.request<T>(config);
return response.data;
} catch (error) {
// 直接使用ApiError.fromAxiosError静态方法处理错误
return Promise.reject(ApiError.fromAxiosError(error as AxiosError));
}
},
get: <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> => {
return newInstance.request<T>({ ...config, method: 'GET', url }).then((res: AxiosResponse<T>) => res.data);
},
post: <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
return newInstance.request<T>({ ...config, method: 'POST', url, data }).then((res: AxiosResponse<T>) => res.data);
},
put: <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
return newInstance.request<T>({ ...config, method: 'PUT', url, data }).then((res: AxiosResponse<T>) => res.data);
},
delete: <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> => {
return newInstance.request<T>({ ...config, method: 'DELETE', url }).then((res: AxiosResponse<T>) => res.data);
},
patch: <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
return newInstance.request<T>({ ...config, method: 'PATCH', url, data }).then((res: AxiosResponse<T>) => res.data);
},
setDefaults: (_config: Partial<AxiosRequestConfig>): void => {
Object.assign(newInstance.defaults, _config);
},
setBaseURL: (baseURL: string): void => {
newInstance.defaults.baseURL = baseURL;
},
createInstance: (newConfig?: Partial<AxiosRequestConfig>): ApiClient => {
// 手动处理headers字段的类型转换
const { headers, ...otherDefaults } = newInstance.defaults;
const configWithTypedHeaders: Partial<AxiosRequestConfig> = {
...otherDefaults,
...newConfig
};
// 只有当headers存在时才添加
if (headers) {
// 手动转换headers字段确保类型安全
const convertedHeaders: Record<string, string | number | boolean> = {};
Object.entries(headers).forEach(([key, value]) => {
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
convertedHeaders[key] = value;
}
});
configWithTypedHeaders.headers = convertedHeaders;
}
return createInstance(configWithTypedHeaders);
},
addRequestInterceptor: (
onFulfilled?: (_config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>,
onRejected?: (_error: unknown) => unknown
): number => {
const handler = newInstance.interceptors.request.use(onFulfilled, onRejected);
newRequestInterceptors.push(handler);
return handler;
},
addResponseInterceptor: (
onFulfilled?: (_response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>,
onRejected?: (_error: unknown) => unknown
): number => {
const handler = newInstance.interceptors.response.use(onFulfilled, onRejected);
newResponseInterceptors.push(handler);
return handler;
},
removeRequestInterceptor: (handler: number): void => {
const index = newRequestInterceptors.indexOf(handler);
if (index !== -1) {
newInstance.interceptors.request.eject(handler);
newRequestInterceptors.splice(index, 1);
}
},
removeResponseInterceptor: (handler: number): void => {
const index = newResponseInterceptors.indexOf(handler);
if (index !== -1) {
newInstance.interceptors.response.eject(handler);
newResponseInterceptors.splice(index, 1);
}
}
};
};
// 基础请求方法
const request = async <T = unknown>(config: AxiosRequestConfig): Promise<T> => {
try {
const response = await instance.request<T>(config);
return response.data;
} catch (error) {
// 直接使用ApiError.fromAxiosError静态方法处理错误
return Promise.reject(ApiError.fromAxiosError(error as AxiosError));
}
};
// HTTP方法简写
const get = <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> => {
return request<T>({ ...config, method: 'GET', url });
};
const post = <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
return request<T>({ ...config, method: 'POST', url, data });
};
const put = <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
return request<T>({ ...config, method: 'PUT', url, data });
};
const del = <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> => {
return request<T>({ ...config, method: 'DELETE', url });
};
const patch = <T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> => {
return request<T>({ ...config, method: 'PATCH', url, data });
};
return {
request,
get,
post,
put,
delete: del,
patch,
setDefaults,
setBaseURL,
createInstance,
addRequestInterceptor,
addResponseInterceptor,
removeRequestInterceptor,
removeResponseInterceptor
};
};
// 默认实例(单例)
const apiClient = createApiClientInstance();
// 工厂函数
const createApiClient = (config?: Partial<AxiosRequestConfig>) => {
return createApiClientInstance(config);
};
// 导出API客户端和工厂函数
export { apiClient, createApiClient };

46
api/errors.ts Normal file
View File

@@ -0,0 +1,46 @@
/**
* API错误处理
*/
import type { AxiosError } from 'axios';
/**
* API错误接口
*/
export interface IApiError {
code: number;
message: string;
details?: unknown;
}
/**
* API错误类
*/
export class ApiError extends Error implements IApiError {
public readonly code: number;
public readonly details: unknown;
constructor(code: number, message: string, details?: unknown) {
super(message);
this.name = 'ApiError';
this.code = code;
this.details = details;
}
/**
* 从Axios错误创建API错误
*/
static fromAxiosError(error: AxiosError): ApiError {
if (!error.response) {
return new ApiError(0, error.message || '网络错误');
}
const { status, data } = error.response;
const message = data && typeof data === 'object' && 'message' in data
? data.message as string
: '请求失败';
return new ApiError(status, message, data);
}
}

40
api/factory.ts Normal file
View File

@@ -0,0 +1,40 @@
import { apiClient, createApiClient } from './client';
import type { AxiosRequestConfig } from 'axios';
import { postApi } from './modules/post';
import { userApi } from './modules/user';
import { chatApi } from './modules/chat';
import { modelApi } from './modules/model';
/**
* API 工厂函数,用于创建和管理 API 实例
* 提供统一的 API 访问入口和配置管理
*/
export const createApi = (config?: Partial<AxiosRequestConfig>) => {
const client = config ? createApiClient(config) : apiClient;
return {
// 核心客户端
client,
// API 模块 - 使用提供的客户端或默认客户端
modules: {
post: postApi(client),
user: userApi(client),
chat: chatApi(client),
model: modelApi(client)
},
// 便捷访问
post: postApi(client),
user: userApi(client),
chat: chatApi(client),
model: modelApi(client)
};
};
// 导出默认 API 实例
export const api = createApi();
// 向后兼容的导出
export { apiClient } from './client';
export { postApi, userApi, chatApi, modelApi } from './modules';

19
api/index.ts Normal file
View File

@@ -0,0 +1,19 @@
// 导出API工厂函数和默认实例
export { createApi, api } from './factory';
// 导出API类型和配置
export {
API_ENDPOINTS,
ApiStatusCode,
ApiErrorType,
DEFAULT_REQUEST_CONFIG,
DEFAULT_PAGINATION_CONFIG,
type ApiClient,
type ApiResponse,
type PaginatedResponse,
type ErrorResponse
} from './types';
// 向后兼容的导出
export { apiClient } from './client';
export { postApi, userApi, chatApi, modelApi } from './modules';

48
api/modules/chat.ts Normal file
View File

@@ -0,0 +1,48 @@
import type { AxiosRequestConfig } from 'axios';
import type { ApiClient } from '../types';
import type {
CreateChatSessionRequest,
UpdateChatSessionRequest,
SendMessageRequest,
GetChatSessionsRequest,
GetChatSessionsResponse,
GetChatMessagesRequest,
GetChatMessagesResponse,
MarkMessagesAsReadRequest,
MarkMessagesAsReadResponse
} from '@/types/chat/api';
import type { ChatSession, ChatMessage } from '@/types/chat/base';
// 聊天API服务工厂函数
export const chatApi = (client: ApiClient) => ({
// 创建聊天会话
createSession: (data: CreateChatSessionRequest): Promise<{ session: ChatSession }> => {
return client.post('/chat/sessions', data);
},
// 更新聊天会话
updateSession: ({ sessionId, ...data }: UpdateChatSessionRequest): Promise<{ session: ChatSession }> => {
return client.put(`/chat/sessions/${sessionId}`, data);
},
// 发送消息
sendMessage: (data: SendMessageRequest): Promise<{ message: ChatMessage }> => {
return client.post(`/chat/sessions/${data.sessionId}/messages`, data);
},
// 获取聊天会话列表
getSessions: (params?: GetChatSessionsRequest): Promise<GetChatSessionsResponse> => {
const config: AxiosRequestConfig = params ? { params } : {};
return client.get('/chat/sessions', config);
},
// 获取聊天消息
getMessages: ({ sessionId, ...params }: GetChatMessagesRequest): Promise<GetChatMessagesResponse> => {
return client.get(`/chat/sessions/${sessionId}/messages`, { params });
},
// 标记消息已读
markMessagesAsRead: ({ sessionId, messageIds }: MarkMessagesAsReadRequest): Promise<MarkMessagesAsReadResponse> => {
return client.post(`/chat/sessions/${sessionId}/read`, { messageIds });
}
});

14
api/modules/index.ts Normal file
View File

@@ -0,0 +1,14 @@
import { apiClient } from '../client';
import { postApi as createPostApi } from './post';
import { userApi as createUserApi } from './user';
import { chatApi as createChatApi } from './chat';
import { modelApi as createModelApi } from './model';
// 导出工厂函数
export { postApi as createPostApi, userApi as createUserApi, chatApi as createChatApi, modelApi as createModelApi };
// 向后兼容的默认实例
export const postApi = createPostApi(apiClient);
export const userApi = createUserApi(apiClient);
export const chatApi = createChatApi(apiClient);
export const modelApi = createModelApi(apiClient);

29
api/modules/model.ts Normal file
View File

@@ -0,0 +1,29 @@
import type { AxiosRequestConfig } from 'axios';
import type { ApiClient } from '../types';
import type {
GetAIPlazaRequest,
GetAIPlazaResponse,
GetModelDetailRequest,
GetModelDetailResponse,
GetModelCommentsRequest,
GetModelCommentsResponse
} from '@/types/model/api';
// AI模型API服务工厂函数
export const modelApi = (client: ApiClient) => ({
// 获取AI模型广场数据
getAIPlaza: (params?: GetAIPlazaRequest): Promise<GetAIPlazaResponse> => {
const config: AxiosRequestConfig = params ? { params } : {};
return client.get('/models/plaza', config);
},
// 获取模型详情
getModelDetail: ({ modelId, ...params }: GetModelDetailRequest): Promise<GetModelDetailResponse> => {
return client.get(`/models/${modelId}`, { params });
},
// 获取模型评论
getModelComments: ({ modelId, ...params }: GetModelCommentsRequest): Promise<GetModelCommentsResponse> => {
return client.get(`/models/${modelId}/comments`, { params });
}
});

65
api/modules/post.ts Normal file
View File

@@ -0,0 +1,65 @@
import type { AxiosRequestConfig } from 'axios';
import type { ApiClient } from '../types';
import type {
CreatePostRequest,
CreatePostResponse,
GetPostsRequest,
GetPostsResponse,
GetPostRequest,
GetPostResponse,
LikePostRequest,
LikePostResponse,
BookmarkPostRequest,
BookmarkPostResponse,
CreateCommentRequest,
CreateCommentResponse,
GetCommentsRequest,
GetCommentsResponse,
LikeCommentRequest,
LikeCommentResponse
} from '@/types/post/api';
// 帖子API服务工厂函数
export const postApi = (client: ApiClient) => ({
// 创建帖子
createPost: (data: CreatePostRequest): Promise<CreatePostResponse> => {
return client.post('/posts', data);
},
// 获取帖子列表
getPosts: (params: GetPostsRequest): Promise<GetPostsResponse> => {
const config: AxiosRequestConfig = { params };
return client.get('/posts', config);
},
// 获取帖子详情
getPost: ({ postId }: GetPostRequest): Promise<GetPostResponse> => {
return client.get(`/posts/${postId}`);
},
// 点赞帖子
likePost: ({ postId }: LikePostRequest): Promise<LikePostResponse> => {
return client.put(`/posts/${postId}/like`);
},
// 收藏帖子
bookmarkPost: ({ postId }: BookmarkPostRequest): Promise<BookmarkPostResponse> => {
return client.put(`/posts/${postId}/bookmark`);
},
// 创建评论
createComment: (data: CreateCommentRequest): Promise<CreateCommentResponse> => {
return client.post(`/posts/${data.postId}/comments`, data);
},
// 获取评论列表
getComments: (params: GetCommentsRequest): Promise<GetCommentsResponse> => {
const { postId, ...queryParams } = params;
return client.get(`/posts/${postId}/comments`, { params: queryParams });
},
// 点赞评论
likeComment: ({ commentId }: LikeCommentRequest): Promise<LikeCommentResponse> => {
return client.put(`/comments/${commentId}/like`);
}
});

51
api/modules/user.ts Normal file
View File

@@ -0,0 +1,51 @@
import type { ApiClient } from '../types';
import type {
LoginRequest,
LoginResponse,
RegisterRequest,
RegisterResponse,
RefreshTokenRequest,
RefreshTokenResponse,
UserProfileUpdateRequest,
UserProfileUpdateResponse,
UserFollowRequest,
UserFollowResponse
} from '@/types/user';
// 用户API服务工厂函数
export const userApi = (client: ApiClient) => ({
// 用户登录
login: (data: LoginRequest): Promise<LoginResponse> => {
return client.post('/auth/login', data);
},
// 用户注册
register: (data: RegisterRequest): Promise<RegisterResponse> => {
return client.post('/auth/register', data);
},
// 刷新令牌
refreshToken: (data: RefreshTokenRequest): Promise<RefreshTokenResponse> => {
return client.post('/auth/refresh', data);
},
// 获取用户档案
getProfile: (): Promise<UserProfileUpdateResponse> => {
return client.get('/user/profile');
},
// 更新用户档案
updateProfile: (data: UserProfileUpdateRequest): Promise<UserProfileUpdateResponse> => {
return client.put('/user/profile', data);
},
// 关注用户
followUser: ({ userId }: UserFollowRequest): Promise<UserFollowResponse> => {
return client.put(`/user/follow/${userId}`);
},
// 取消关注用户
unfollowUser: ({ userId }: UserFollowRequest): Promise<UserFollowResponse> => {
return client.delete(`/user/follow/${userId}`);
}
});

119
api/types.d.ts vendored Normal file
View File

@@ -0,0 +1,119 @@
/**
* API 类型定义文件
*/
import type { AxiosResponse, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
// API客户端接口定义
export interface ApiClient {
request<T = unknown>(config: AxiosRequestConfig): Promise<T>;
get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>;
post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T>;
patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>;
setDefaults(config: Partial<AxiosRequestConfig>): void;
setBaseURL(baseURL: string): void;
createInstance(config?: Partial<AxiosRequestConfig>): ApiClient;
addRequestInterceptor(
onFulfilled?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>,
onRejected?: (error: unknown) => unknown
): number;
addResponseInterceptor(
onFulfilled?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>,
onRejected?: (error: unknown) => unknown
): number;
removeRequestInterceptor(handler: number): void;
removeResponseInterceptor(handler: number): void;
}
// API响应接口
export interface ApiResponse<T = unknown> {
success: boolean;
data: T;
message?: string;
code?: number;
}
// 分页响应接口
export interface PaginatedResponse<T = unknown> {
items: T[];
total: number;
page: number;
pageSize: number;
totalPages: number;
}
// 错误响应接口
export interface ErrorResponse {
success: false;
message: string;
code?: number;
details?: unknown;
}
// API端点常量
export const API_ENDPOINTS = {
// 用户相关
USER_LOGIN: '/auth/login',
USER_REGISTER: '/auth/register',
USER_LOGOUT: '/auth/logout',
USER_PROFILE: '/user/profile',
USER_CURRENT: '/auth/me',
// 聊天相关
CHAT_LIST: '/chat/list',
CHAT_CREATE: '/chat/create',
CHAT_DETAIL: '/chat/detail',
CHAT_DELETE: '/chat/delete',
CHAT_MESSAGE: '/chat/message',
// 模型相关
MODEL_LIST: '/model/list',
MODEL_DETAIL: '/model/detail',
// 帖子相关
POST_LIST: '/post/list',
POST_DETAIL: '/post/detail',
POST_CREATE: '/post/create',
POST_UPDATE: '/post/update',
POST_DELETE: '/post/delete'
} as const;
// API状态码
export const ApiStatusCode = {
OK: 200,
CREATED: 201,
NO_CONTENT: 204,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
INTERNAL_SERVER_ERROR: 500
} as const;
// API错误类型
export const ApiErrorType = {
NETWORK_ERROR: 'NETWORK_ERROR',
VALIDATION_ERROR: 'VALIDATION_ERROR',
AUTHENTICATION_ERROR: 'AUTHENTICATION_ERROR',
AUTHORIZATION_ERROR: 'AUTHORIZATION_ERROR',
NOT_FOUND_ERROR: 'NOT_FOUND_ERROR',
SERVER_ERROR: 'SERVER_ERROR',
UNKNOWN_ERROR: 'UNKNOWN_ERROR'
} as const;
// 默认请求配置
export const DEFAULT_REQUEST_CONFIG = {
timeout: 10000,
headers: {
'Content-Type': 'application/json'
},
withCredentials: true
} as const;
// 默认分页配置
export const DEFAULT_PAGINATION_CONFIG = {
page: 1,
pageSize: 20
} as const;