useKnowledgeCategoriesQuery.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
  2. import { message } from 'antd';
  3. import { silverUsersClient } from '@/client/api';
  4. import type { InferResponseType, InferRequestType } from 'hono/client';
  5. // 定义类型
  6. type KnowledgeCategory = InferResponseType<typeof silverUsersClient['knowledge-categories']['$get'], 200>['data'][0];
  7. type CreateCategoryRequest = InferRequestType<typeof silverUsersClient['knowledge-categories']['$post']>['json'];
  8. type UpdateCategoryRequest = InferRequestType<typeof silverUsersClient['knowledge-categories'][':id']['$put']>['json'];
  9. // 错误响应类型
  10. interface ErrorResponse {
  11. code: number;
  12. message: string;
  13. errors?: Record<string, string[]>;
  14. }
  15. // Query keys
  16. export const KNOWLEDGE_CATEGORIES_KEYS = {
  17. all: ['knowledge-categories'] as const,
  18. lists: () => [...KNOWLEDGE_CATEGORIES_KEYS.all, 'list'] as const,
  19. list: (params: Record<string, any>) => [...KNOWLEDGE_CATEGORIES_KEYS.lists(), params] as const,
  20. details: () => [...KNOWLEDGE_CATEGORIES_KEYS.all, 'detail'] as const,
  21. detail: (id: number) => [...KNOWLEDGE_CATEGORIES_KEYS.details(), id] as const,
  22. tree: () => [...KNOWLEDGE_CATEGORIES_KEYS.all, 'tree'] as const,
  23. };
  24. // 获取知识分类列表
  25. export const useKnowledgeCategories = (params?: {
  26. page?: number;
  27. pageSize?: number;
  28. keyword?: string;
  29. isActive?: number;
  30. }) => {
  31. return useQuery({
  32. queryKey: KNOWLEDGE_CATEGORIES_KEYS.list(params || {}),
  33. queryFn: async () => {
  34. const response = await silverUsersClient['knowledge-categories'].$get({
  35. query: {
  36. page: params?.page || 1,
  37. pageSize: params?.pageSize || 10,
  38. ...(params?.keyword && { keyword: params.keyword }),
  39. ...(params?.isActive !== undefined && { isActive: params.isActive }),
  40. },
  41. });
  42. if (!response.ok) {
  43. throw new Error('获取知识分类失败');
  44. }
  45. return response.json();
  46. },
  47. staleTime: 5 * 60 * 1000, // 5分钟
  48. gcTime: 10 * 60 * 1000, // 10分钟
  49. });
  50. };
  51. // 获取所有知识分类(用于树形选择)
  52. export const useAllKnowledgeCategories = (showAll: boolean = false) => {
  53. return useQuery({
  54. queryKey: KNOWLEDGE_CATEGORIES_KEYS.list({ showAll }),
  55. queryFn: async () => {
  56. const response = await silverUsersClient['knowledge-categories'].$get({
  57. query: {
  58. page: 1,
  59. pageSize: 1000,
  60. ...(showAll ? {} : { isActive: 1 })
  61. }
  62. });
  63. if (!response.ok) {
  64. throw new Error('获取知识分类失败');
  65. }
  66. const result = await response.json();
  67. return result.data;
  68. },
  69. staleTime: 5 * 60 * 1000,
  70. gcTime: 10 * 60 * 1000,
  71. });
  72. };
  73. // 创建知识分类
  74. export const useCreateKnowledgeCategory = () => {
  75. const queryClient = useQueryClient();
  76. return useMutation({
  77. mutationFn: async (data: CreateCategoryRequest) => {
  78. const response = await silverUsersClient['knowledge-categories'].$post({
  79. json: data,
  80. });
  81. if (!response.ok) {
  82. const error = await response.json();
  83. throw new Error(error.message || '创建知识分类失败');
  84. }
  85. return response.json();
  86. },
  87. onSuccess: () => {
  88. message.success('创建成功');
  89. // 刷新相关缓存
  90. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.lists() });
  91. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.tree() });
  92. },
  93. onError: (error) => {
  94. const errorMessage = error instanceof Error ? error.message : '创建失败';
  95. message.error(errorMessage);
  96. },
  97. });
  98. };
  99. // 更新知识分类
  100. export const useUpdateKnowledgeCategory = () => {
  101. const queryClient = useQueryClient();
  102. return useMutation({
  103. mutationFn: async ({ id, data }: { id: number; data: UpdateCategoryRequest }) => {
  104. const response = await silverUsersClient['knowledge-categories'][':id']['$put']({
  105. param: { id: id.toString() },
  106. json: data,
  107. });
  108. if (!response.ok) {
  109. const error = await response.json();
  110. throw new Error(error.message || '更新知识分类失败');
  111. }
  112. return response.json();
  113. },
  114. onSuccess: () => {
  115. message.success('更新成功');
  116. // 刷新相关缓存
  117. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.lists() });
  118. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.tree() });
  119. },
  120. onError: (error) => {
  121. const errorMessage = error instanceof Error ? error.message : '更新失败';
  122. message.error(errorMessage);
  123. },
  124. });
  125. };
  126. // 删除知识分类
  127. export const useDeleteKnowledgeCategory = () => {
  128. const queryClient = useQueryClient();
  129. return useMutation({
  130. mutationFn: async (id: number) => {
  131. const response = await silverUsersClient['knowledge-categories'][':id']['$delete']({
  132. param: { id: id.toString() },
  133. });
  134. if (!response.ok) {
  135. const error = await response.json();
  136. throw new Error(error.message || '删除知识分类失败');
  137. }
  138. return response.json();
  139. },
  140. onSuccess: () => {
  141. message.success('删除成功');
  142. // 刷新相关缓存
  143. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.lists() });
  144. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.tree() });
  145. },
  146. onError: (error) => {
  147. const errorMessage = error instanceof Error ? error.message : '删除失败';
  148. message.error(errorMessage);
  149. },
  150. });
  151. };
  152. // 切换知识分类状态
  153. export const useToggleKnowledgeCategoryStatus = () => {
  154. const queryClient = useQueryClient();
  155. return useMutation({
  156. mutationFn: async ({ id, isActive }: { id: number; isActive: boolean }) => {
  157. const response = await silverUsersClient['knowledge-categories'][':id']['$put']({
  158. param: { id: id.toString() },
  159. json: { isActive: isActive ? 1 : 0 } as UpdateCategoryRequest,
  160. });
  161. if (!response.ok) {
  162. const error = await response.json();
  163. throw new Error(error.message || '更新状态失败');
  164. }
  165. return response.json();
  166. },
  167. onSuccess: () => {
  168. // 刷新相关缓存
  169. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.lists() });
  170. queryClient.invalidateQueries({ queryKey: KNOWLEDGE_CATEGORIES_KEYS.tree() });
  171. },
  172. onError: (error) => {
  173. const errorMessage = error instanceof Error ? error.message : '更新状态失败';
  174. message.error(errorMessage);
  175. },
  176. });
  177. };
  178. // 工具函数:构建分类树
  179. export const buildCategoryTree = (items: KnowledgeCategory[], parentId: number | null = null): KnowledgeCategory[] => {
  180. return items
  181. .filter(item => item.parentId === parentId)
  182. .map(item => ({
  183. ...item,
  184. children: buildCategoryTree(items, item.id)
  185. }));
  186. };
  187. // 工具函数:获取分类路径
  188. export const getCategoryPath = (categoryId: number, allCategories: KnowledgeCategory[]): string[] => {
  189. const path: string[] = [];
  190. const findPath = (id: number) => {
  191. const category = allCategories.find(cat => cat.id === id);
  192. if (category) {
  193. if (category.parentId) {
  194. findPath(category.parentId);
  195. }
  196. path.push(category.name);
  197. }
  198. };
  199. findPath(categoryId);
  200. return path;
  201. };
  202. // 工具函数:获取所有子分类ID
  203. export const getAllChildrenIds = (categoryId: number, categories: KnowledgeCategory[]): number[] => {
  204. const ids: number[] = [categoryId];
  205. const findChildren = (parentId: number) => {
  206. categories.forEach(cat => {
  207. if (cat.parentId === parentId) {
  208. ids.push(cat.id);
  209. findChildren(cat.id);
  210. }
  211. });
  212. };
  213. findChildren(categoryId);
  214. return ids;
  215. };