按照 TDD 规范完成三个核心功能的接口对接: ## 新增功能 ### 1. 删除作品功能 (app/generationRecord.tsx) - 新增 use-template-generation-actions.ts hook - 支持单个删除和批量删除作品 - 删除确认对话框 - 删除成功后自动刷新列表 - 完整的错误处理和加载状态 ### 2. 作品搜索功能 (app/searchWorksResults.tsx) - 新增 use-works-search.ts hook - 替换模拟数据为真实 SDK 接口 - 支持关键词搜索和分类筛选 - 支持分页加载 - 完整的加载、错误、空结果状态处理 ### 3. 修改密码功能 (app/changePassword.tsx) - 新增 use-change-password.ts hook - 使用 Better Auth 的 changePassword API - 客户端表单验证(密码长度、确认密码匹配等) - 成功后自动返回并提示 ## 技术实现 - 严格遵循 TDD 规范(先写测试,后写实现) - 新增 3 个 hooks 和对应的单元测试 - 更新中英文翻译文件 - 更新 jest.setup.js 添加必要的 mock ## 文档 - 新增 api_integration_report.md - API 对接分析报告 - 新增 api_integration_development_plan.md - 开发计划和完成汇总 Co-Authored-By: Claude <noreply@anthropic.com>
105 lines
2.5 KiB
TypeScript
105 lines
2.5 KiB
TypeScript
/**
|
|
* TDD Phase 2: GREEN - Minimal code to pass tests
|
|
*
|
|
* This Hook implements works search functionality:
|
|
* - Uses @tanstack/react-query for data fetching
|
|
* - Supports keyword search
|
|
* - Supports category filter
|
|
* - Supports pagination
|
|
* - Only executes query when keyword is provided
|
|
*/
|
|
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import { root } from '@repo/core'
|
|
import { TemplateGenerationController } from '@repo/sdk'
|
|
import { useCallback } from 'react'
|
|
|
|
// Type definitions
|
|
export interface UseWorksSearchParams {
|
|
keyword: string
|
|
category?: '全部' | '萌宠' | '写真' | '合拍'
|
|
page?: number
|
|
limit?: number
|
|
}
|
|
|
|
export interface WorksSearchResult {
|
|
id: string
|
|
createdAt: Date
|
|
template: {
|
|
id: string
|
|
name: string
|
|
}
|
|
status: string
|
|
duration: number
|
|
}
|
|
|
|
export interface WorksSearchResponse {
|
|
data: WorksSearchResult[]
|
|
total: number
|
|
page: number
|
|
limit: number
|
|
totalPages: number
|
|
}
|
|
|
|
/**
|
|
* Hook for searching works with keyword and category filtering
|
|
*
|
|
* @param params - Search parameters including keyword, category, page, and limit
|
|
* @returns Query result with data, loading state, error, and refetch function
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* const { data, works, isLoading, error } = useWorksSearch({
|
|
* keyword: '测试',
|
|
* category: '萌宠',
|
|
* page: 1,
|
|
* limit: 20
|
|
* })
|
|
* ```
|
|
*/
|
|
export function useWorksSearch(params: UseWorksSearchParams) {
|
|
const { keyword, category, page = 1, limit = 20 } = params
|
|
|
|
// Build query key - "全部" category should not be included
|
|
const queryKey = [
|
|
'worksSearch',
|
|
keyword,
|
|
category === '全部' ? undefined : category,
|
|
page,
|
|
limit,
|
|
] as const
|
|
|
|
// Build API params - only include category if it's not "全部"
|
|
const apiParams = {
|
|
keyword,
|
|
...(category && category !== '全部' && { category }),
|
|
page,
|
|
limit,
|
|
}
|
|
|
|
// Query function
|
|
const queryFn = useCallback(async (): Promise<WorksSearchResponse> => {
|
|
const controller = root.get(TemplateGenerationController)
|
|
const result = await controller.list(apiParams)
|
|
return result as WorksSearchResponse
|
|
}, [keyword, category, page, limit])
|
|
|
|
// Execute query only when keyword has content
|
|
const trimmedKeyword = keyword?.trim() || ''
|
|
const isEnabled = !!trimmedKeyword
|
|
|
|
const query = useQuery({
|
|
queryKey,
|
|
queryFn,
|
|
enabled: isEnabled,
|
|
})
|
|
|
|
return {
|
|
data: query.data,
|
|
works: query.data?.data || [],
|
|
isLoading: query.isLoading,
|
|
error: query.error,
|
|
refetch: query.refetch,
|
|
}
|
|
}
|