feat: 实现 API 接口对接功能 (删除作品、作品搜索、修改密码)
按照 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>
This commit is contained in:
104
hooks/use-works-search.ts
Normal file
104
hooks/use-works-search.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user