mockChatApi.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import type { CreateChatRequest, ChatResponse, ApiResponse } from "../types/chat"
  2. // Mock 存储,模拟数据库
  3. let mockChats: ChatResponse[] = [
  4. {
  5. id: "550e8400-e29b-41d4-a716-446655440000",
  6. title: "天气查询助手",
  7. user_id: "ba5463f3-72d1-4410-858e-eadd10884713",
  8. created_at: "2025-01-15T10:30:00.000000Z",
  9. updated_at: "2025-01-15T10:30:00.000000Z",
  10. },
  11. {
  12. id: "660f8400-e29b-41d4-a716-446655440001",
  13. title: "编程问题讨论",
  14. user_id: "ba5463f3-72d1-4410-858e-eadd10884713",
  15. created_at: "2025-01-14T15:20:00.000000Z",
  16. updated_at: "2025-01-14T15:20:00.000000Z",
  17. },
  18. {
  19. id: "770e8400-e29b-41d4-a716-446655440002",
  20. title: "数学问题求解",
  21. user_id: "ba5463f3-72d1-4410-858e-eadd10884713",
  22. created_at: "2025-01-13T09:15:00.000000Z",
  23. updated_at: "2025-01-13T09:15:00.000000Z",
  24. },
  25. ];
  26. // 工具函数:生成UUID
  27. function generateUUID(): string {
  28. return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
  29. const r = (Math.random() * 16) | 0;
  30. const v = c === "x" ? r : (r & 0x3) | 0x8;
  31. return v.toString(16);
  32. });
  33. }
  34. // 工具函数:模拟网络延迟
  35. function mockDelay(ms: number = 500): Promise<void> {
  36. return new Promise((resolve) => setTimeout(resolve, ms));
  37. }
  38. // 工具函数:创建成功响应
  39. function createSuccessResponse<T>(data: T): ApiResponse<T> {
  40. return {
  41. ok: true,
  42. message: "ok",
  43. data,
  44. };
  45. }
  46. // 工具函数:创建错误响应
  47. function createErrorResponse(
  48. message: string,
  49. errors?: Record<string, string[]>
  50. ): ApiResponse<any> {
  51. return {
  52. ok: false,
  53. message,
  54. data: "",
  55. errors,
  56. };
  57. }
  58. // Mock Chat API 实现
  59. export const mockChatApi = {
  60. async createChat(
  61. request: CreateChatRequest
  62. ): Promise<ApiResponse<ChatResponse>> {
  63. console.log("[Mock API] Creating chat:", request);
  64. await mockDelay(300);
  65. // 验证请求
  66. if (!request.title || request.title.trim() === "") {
  67. return createErrorResponse("标题不能为空", {
  68. title: ["标题是必填字段"],
  69. });
  70. }
  71. if (request.title.length > 255) {
  72. return createErrorResponse("标题过长", {
  73. title: ["标题长度不能超过255个字符"],
  74. });
  75. }
  76. // 创建新聊天
  77. const newChat: ChatResponse = {
  78. id: generateUUID(),
  79. title: request.title.trim(),
  80. user_id: request.user_id,
  81. created_at: new Date().toISOString(),
  82. updated_at: new Date().toISOString(),
  83. };
  84. mockChats.unshift(newChat); // 新聊天放在最前面
  85. console.log("[Mock API] Chat created:", newChat);
  86. return createSuccessResponse(newChat);
  87. },
  88. async getChat(chatId: string): Promise<ApiResponse<ChatResponse>> {
  89. console.log("[Mock API] Getting chat:", chatId);
  90. await mockDelay(200);
  91. const chat = mockChats.find((c) => c.id === chatId);
  92. if (!chat) {
  93. return createErrorResponse("聊天不存在");
  94. }
  95. return createSuccessResponse(chat);
  96. },
  97. async updateChat(
  98. chatId: string,
  99. updates: Partial<CreateChatRequest>
  100. ): Promise<ApiResponse<ChatResponse>> {
  101. console.log("[Mock API] Updating chat:", chatId, updates);
  102. await mockDelay(300);
  103. const chatIndex = mockChats.findIndex((c) => c.id === chatId);
  104. if (chatIndex === -1) {
  105. return createErrorResponse("聊天不存在");
  106. }
  107. // 验证更新数据
  108. if (updates.title !== undefined) {
  109. if (!updates.title || updates.title.trim() === "") {
  110. return createErrorResponse("标题不能为空", {
  111. title: ["标题是必填字段"],
  112. });
  113. }
  114. if (updates.title.length > 255) {
  115. return createErrorResponse("标题过长", {
  116. title: ["标题长度不能超过255个字符"],
  117. });
  118. }
  119. }
  120. // 更新聊天
  121. const updatedChat: ChatResponse = {
  122. ...mockChats[chatIndex],
  123. ...updates,
  124. title: updates.title?.trim() || mockChats[chatIndex].title,
  125. updated_at: new Date().toISOString(),
  126. };
  127. mockChats[chatIndex] = updatedChat;
  128. console.log("[Mock API] Chat updated:", updatedChat);
  129. return createSuccessResponse(updatedChat);
  130. },
  131. async deleteChat(chatId: string): Promise<ApiResponse<void>> {
  132. console.log("[Mock API] Deleting chat:", chatId);
  133. await mockDelay(200);
  134. const chatIndex = mockChats.findIndex((c) => c.id === chatId);
  135. if (chatIndex === -1) {
  136. return createErrorResponse("聊天不存在");
  137. }
  138. // 软删除:实际项目中会设置 deleted_at 字段
  139. // 这里为了简化,直接从数组中移除
  140. mockChats.splice(chatIndex, 1);
  141. console.log("[Mock API] Chat deleted");
  142. return createSuccessResponse(undefined as any);
  143. },
  144. // 额外的辅助方法,便于测试和开发
  145. async getChats(params?: {
  146. limit?: number;
  147. user_id?: string;
  148. offset?: number;
  149. }): Promise<
  150. ApiResponse<{
  151. rows: ChatResponse[];
  152. total: number;
  153. }>
  154. > {
  155. console.log("[Mock API] Getting chats:", params);
  156. await mockDelay(300);
  157. let filteredChats = [...mockChats];
  158. // 按用户过滤
  159. if (params?.user_id) {
  160. filteredChats = filteredChats.filter(
  161. (chat) => chat.user_id === params.user_id
  162. );
  163. }
  164. // 分页
  165. const total = filteredChats.length;
  166. const offset = params?.offset || 0;
  167. const limit = params?.limit || 20;
  168. const paginatedChats = filteredChats.slice(offset, offset + limit);
  169. return createSuccessResponse({
  170. rows: paginatedChats,
  171. total,
  172. });
  173. },
  174. // 重置 Mock 数据(用于测试)
  175. resetMockData(): void {
  176. console.log("[Mock API] Resetting mock data");
  177. mockChats = [
  178. {
  179. id: "550e8400-e29b-41d4-a716-446655440000",
  180. title: "天气查询助手",
  181. user_id: "ba5463f3-72d1-4410-858e-eadd10884713",
  182. created_at: "2025-01-15T10:30:00.000000Z",
  183. updated_at: "2025-01-15T10:30:00.000000Z",
  184. },
  185. {
  186. id: "660f8400-e29b-41d4-a716-446655440001",
  187. title: "编程问题讨论",
  188. user_id: "ba5463f3-72d1-4410-858e-eadd10884713",
  189. created_at: "2025-01-14T15:20:00.000000Z",
  190. updated_at: "2025-01-14T15:20:00.000000Z",
  191. },
  192. {
  193. id: "770e8400-e29b-41d4-a716-446655440002",
  194. title: "数学问题求解",
  195. user_id: "ba5463f3-72d1-4410-858e-eadd10884713",
  196. created_at: "2025-01-13T09:15:00.000000Z",
  197. updated_at: "2025-01-13T09:15:00.000000Z",
  198. },
  199. ];
  200. },
  201. // 获取当前 Mock 数据(用于调试)
  202. getMockData(): ChatResponse[] {
  203. return [...mockChats];
  204. },
  205. // 模拟网络错误
  206. async createChatWithNetworkError(): Promise<ApiResponse<ChatResponse>> {
  207. await mockDelay(1000);
  208. throw new Error("网络连接失败");
  209. },
  210. // 模拟服务器错误
  211. async createChatWithServerError(): Promise<ApiResponse<ChatResponse>> {
  212. await mockDelay(500);
  213. return {
  214. ok: false,
  215. message: "服务器内部错误",
  216. } as ApiResponse<any>;
  217. },
  218. // 设置延迟时间(用于测试不同网络条件)
  219. setMockDelay(ms: number): void {
  220. // 这里可以实现动态调整延迟的逻辑
  221. console.log(`[Mock API] Mock delay set to ${ms}ms`);
  222. },
  223. };
  224. // 导出类型,便于在其他地方使用
  225. export type MockChatApi = typeof mockChatApi;