refactor(classes): 客户端组件迁移至 useQuery + queryKeys 示范

Task 19: 将 class-invitation-manager.tsx 从 initialCodes prop + 本地 codes state +
手动 Action 调用 + 手动 state 更新模式,迁移至 V5 缓存策略新 API:

- 列表查询: useActionQuery + queryKeys.classes.invitations(classId)
- 撤销 mutation: useActionMutation + actionId "classes.invitation.revoke"
  (成功后由 CLIENT_INVALIDATION_MAP 自动失效 ["classes", "invitations"] 前缀)
- 生成回调: queryClient.invalidateQueries 手动失效本班级 invitations 查询
- 移除 initialCodes prop + codes state + isSubmitting 手动管理

配套改动:
- actions-invitations.ts: 新增并导出 ClassInvitationCodeOption 强类型接口,
  listClassInvitationCodesAction 返回类型从 Array<Record<string, unknown>>
  收窄为 ClassInvitationCodeOption[]
- actions.ts barrel: 补充 type ClassInvitationCodeOption 与遗漏的
  bulkEnrollStudentsAction / bulkAssignSubjectTeachersAction 导出
- 架构文档 004/005 同步更新 hook 消费方与 actions.ts exports 清单
This commit is contained in:
SpecialX
2026-07-05 18:57:10 +08:00
parent 9eb02807a4
commit a3dc22cb9e
5 changed files with 69 additions and 52 deletions

View File

@@ -691,8 +691,8 @@ src/auth.ts ──▶ import { ... } from "@/shared/lib/permissions"
| Hook | 文件 | 签名 | 用途 | 消费方 |
|------|------|------|------|--------|
| `useActionMutation` | `hooks/use-action-mutation.ts` | `useActionMutation<T>(options?): { isWorking, mutate }`。Options 联合类型:旧版 `{ successMessage?, errorMessage?, onSuccess?, onError? }` 或新版 `{ mutationFn?, actionId?, params?, invalidateQueryKeys?, ... }`。新版接入 QueryClient成功后按 `CLIENT_INVALIDATION_MAP[actionId]` 自动 invalidateQueries。`mutate(action?)` 参数可选:传 action 走旧模式,不传则使用 options.mutationFn | 通用 Server Action mutation Hook替代 50+ 文件中重复的 setIsWorking + try/catch/finally + toast 模式。V5 缓存策略重构新增 QueryClient + actionId 自动失效,向后兼容旧调用方 | 1 个示范P1-4: schools-view潜在影响 50+ 文件 |
| `useActionQuery` | `hooks/use-action-query.ts` | `useActionQuery<T>(action, options?): { data, loading, error, refetch }`。Options 联合类型:旧版 `{ deps?, enabled?, errorMessage? }` 或新版 `UseActionQueryWithCacheOptions`(含 `queryKey` + `UseQueryOptions`)。传入 `queryKey` 走 useQuery 跨页共享缓存;不传走旧 useEffect + useState。Hook 内部始终声明 useQuery + useState/useEffect 以遵守 React Hooks 规则 | 通用 Server Action 查询 Hook替代 11 个文件中重复的 useEffect + useState(loading) + Action().then().catch().finally() 模式内置竞态防护。V5 缓存策略重构新增 queryKey 入参走 QueryClient向后兼容旧调用方 | 1 个示范P1-4: create-question-dialog潜在影响 11 个文件 |
| `useActionMutation` | `hooks/use-action-mutation.ts` | `useActionMutation<T>(options?): { isWorking, mutate }`。Options 联合类型:旧版 `{ successMessage?, errorMessage?, onSuccess?, onError? }` 或新版 `{ mutationFn?, actionId?, params?, invalidateQueryKeys?, ... }`。新版接入 QueryClient成功后按 `CLIENT_INVALIDATION_MAP[actionId]` 自动 invalidateQueries。`mutate(action?)` 参数可选:传 action 走旧模式,不传则使用 options.mutationFn | 通用 Server Action mutation Hook替代 50+ 文件中重复的 setIsWorking + try/catch/finally + toast 模式。V5 缓存策略重构新增 QueryClient + actionId 自动失效,向后兼容旧调用方 | 示范P1-4 schools-viewTask 19 classes/class-invitation-managerrevoke mutation + actionId 自动失效)。潜在影响 50+ 文件 |
| `useActionQuery` | `hooks/use-action-query.ts` | `useActionQuery<T>(action, options?): { data, loading, error, refetch }`。Options 联合类型:旧版 `{ deps?, enabled?, errorMessage? }` 或新版 `UseActionQueryWithCacheOptions`(含 `queryKey` + `UseQueryOptions`)。传入 `queryKey` 走 useQuery 跨页共享缓存;不传走旧 useEffect + useState。Hook 内部始终声明 useQuery + useState/useEffect 以遵守 React Hooks 规则 | 通用 Server Action 查询 Hook替代 11 个文件中重复的 useEffect + useState(loading) + Action().then().catch().finally() 模式内置竞态防护。V5 缓存策略重构新增 queryKey 入参走 QueryClient向后兼容旧调用方 | 示范P1-4 create-question-dialogTask 19 classes/class-invitation-managerlistClassInvitationCodesAction + queryKeys.classes.invitations(classId))。潜在影响 11 个文件 |
**V5 状态管理统一专项基础设施**(阶段 1 新增,零业务行为变更):

View File

@@ -8254,9 +8254,12 @@
"revokeClassInvitationCodeAction",
"listClassInvitationCodesAction",
"setStudentEnrollmentStatusAction",
"bulkEnrollStudentsAction",
"bulkAssignSubjectTeachersAction",
"createClassScheduleItemAction",
"updateClassScheduleItemAction",
"deleteClassScheduleItemAction"
"deleteClassScheduleItemAction",
"ClassInvitationCodeOption"
]
},
{