# Changelog: 项目 API 对接 > **版本**: v1.1.0 > **发布日期**: 2026-01-21 > **类型**: Feature > **影响范围**: 前端 API 层、Hooks、类型定义 --- ## 概述 完成前端项目模块与后端 API 的对接,包括项目 CRUD、回收站功能、分享管理等。 --- ## 变更内容 ### 1. 类型定义更新 **文件**: `client/src/types/project.ts` **新增类型**: - `MoveProjectDto` - 移动项目参数 - `ProjectListParams` - 列表查询参数 - `ProjectListResponse` - 列表响应 - `TrashProject` - 回收站项目 - `TrashListResponse` - 回收站列表响应 - `RestoreProjectResponse` - 恢复响应 **更新类型**: - `Project` - 添加 `displayOrder`, `trashedAt` 字段 - `ProjectStatus` - 添加 `trashed`, `soft_deleted` 状态 - `CreateProjectDto` - 添加影视项目元数据字段 - `UpdateProjectDto` - 添加影视项目元数据字段 ### 2. API 服务实现 **文件**: `client/src/services/api/projects.ts` (新建) **实现功能**: #### 基础 CRUD - `getAll(params)` - 获取项目列表(支持筛选、搜索、排序、分页) - `getById(id)` - 获取单个项目 - `create(data)` - 创建项目 - `update(id, data)` - 更新项目 - `delete(id)` - 删除项目(移至回收站) - `move(id, data)` - 移动项目到文件夹 - `clone(id, data)` - 克隆项目 - `updateOrder(id, displayOrder)` - 更新项目顺序 #### 回收站功能 - `getTrash(params)` - 获取回收站列表 - `restore(id)` - 从回收站恢复 - `permanentDelete(id)` - 永久删除 #### 分享管理 - `createShare(id, data)` - 创建分享 - `getShares(id)` - 获取分享列表 - `revokeShare(id, shareId)` - 撤销分享 #### 成员管理 - `getMembers(id, params)` - 获取成员列表 - `addMember(id, data)` - 添加成员 - `removeMember(id, userId)` - 移除成员 ### 3. React Query Hooks **文件**: `client/src/hooks/api/useProjects.ts` **新增 Hooks**: - `useMoveProject()` - 移动项目 - `useCloneProject()` - 克隆项目 - `useUpdateProjectOrder()` - 更新顺序 - `useTrashProjects(params)` - 获取回收站列表 - `useRestoreProject()` - 恢复项目 - `usePermanentDeleteProject()` - 永久删除 **更新 Hooks**: - `useProjects(params)` - 支持查询参数 - `useDeleteProject()` - 改为移至回收站,失效回收站缓存 **Query Keys 更新**: ```typescript projectKeys = { all: ['projects'], lists: () => ['projects', 'list'], list: (filters) => ['projects', 'list', filters], details: () => ['projects', 'detail'], detail: (id) => ['projects', 'detail', id], trash: () => ['projects', 'trash'], trashList: (params) => ['projects', 'trash', params], } ``` ### 4. API 导出更新 **文件**: `client/src/services/api/index.ts` **变更**: - 从 Mock API 切换到真实 API - `projectApi` 现在导出自 `./projects` 而非 `../mock` --- ## API 对接说明 ### 请求格式 所有请求使用 camelCase 命名: ```typescript { folderId: "xxx", contentType: "movie", sortBy: "updatedAt" } ``` ### 响应格式 后端返回 camelCase 格式(通过 `alias` 配置): ```typescript { id: "xxx", name: "项目名称", folderId: "xxx", createdAt: "2026-01-21T10:00:00Z" } ``` ### 分页参数 ```typescript { page: 1, // 页码(从 1 开始) pageSize: 20 // 每页数量 } ``` ### 分页响应 ```typescript { items: [...], total: 100, page: 1, pageSize: 20, totalPages: 5 } ``` --- ## 使用示例 ### 1. 获取项目列表 ```typescript import { useProjects } from '@/hooks/api'; function ProjectList() { const { data, isLoading } = useProjects({ folderId: 'folder-123', sortBy: 'updatedAt', sortOrder: 'desc', page: 1, pageSize: 20 }); if (isLoading) return
加载中...
; return (
{data?.items.map(project => (
{project.name}
))}
共 {data?.total} 个项目
); } ``` ### 2. 创建项目 ```typescript import { useCreateProject } from '@/hooks/api'; function CreateProjectButton() { const createProject = useCreateProject(); const handleCreate = () => { createProject.mutate({ name: '新项目', description: '项目描述', type: 'mine', folderId: 'folder-123', contentType: 'movie', aspectRatio: '16:9' }, { onSuccess: (project) => { console.log('创建成功:', project); } }); }; return ( ); } ``` ### 3. 删除项目(移至回收站) ```typescript import { useDeleteProject } from '@/hooks/api'; import { useToast } from '@/hooks/use-toast'; function DeleteProjectButton({ projectId }: { projectId: string }) { const deleteProject = useDeleteProject(); const { toast } = useToast(); const handleDelete = () => { deleteProject.mutate(projectId, { onSuccess: () => { toast({ title: '已移至回收站', description: '项目将在 30 天后自动删除' }); } }); }; return ( ); } ``` ### 4. 回收站列表 ```typescript import { useTrashProjects, useRestoreProject, usePermanentDeleteProject } from '@/hooks/api'; function TrashPage() { const { data } = useTrashProjects({ page: 1, pageSize: 20 }); const restore = useRestoreProject(); const permanentDelete = usePermanentDeleteProject(); return (

回收站

{data?.items.map(project => (
{project.name} {project.daysRemaining} 天后自动删除
))}
); } ``` ### 5. 移动项目 ```typescript import { useMoveProject } from '@/hooks/api'; function MoveProjectButton({ projectId }: { projectId: string }) { const moveProject = useMoveProject(); const handleMove = (targetFolderId: string) => { moveProject.mutate({ id: projectId, data: { folderId: targetFolderId } }); }; return ; } ``` --- ## Breaking Changes ### ⚠️ API 切换 **影响**: 所有使用 `projectApi` 的代码 **变更前**: Mock API(内存数据) ```typescript import { projectApi } from '@/services/mock'; ``` **变更后**: 真实 API(后端对接) ```typescript import { projectApi } from '@/services/api'; ``` **迁移方案**: - 代码无需修改(导出路径已更新) - 确保后端服务已启动 - 确保 API 基础 URL 配置正确 ### ⚠️ 响应格式变更 **影响**: 项目列表查询 **变更前**: 返回数组 ```typescript const projects: Project[] = await projectApi.getAll(); ``` **变更后**: 返回分页对象 ```typescript const response: ProjectListResponse = await projectApi.getAll(); const projects = response.items; ``` **迁移方案**: - 使用 `useProjects()` hook 自动处理 - 直接调用 API 需要访问 `.items` 属性 --- ## 测试清单 ### API 测试 - [ ] 获取项目列表(无参数) - [ ] 获取项目列表(带筛选) - [ ] 获取项目列表(带搜索) - [ ] 获取项目列表(带排序) - [ ] 获取项目列表(带分页) - [ ] 获取单个项目 - [ ] 创建项目 - [ ] 更新项目 - [ ] 删除项目(移至回收站) - [ ] 移动项目 - [ ] 克隆项目 - [ ] 更新项目顺序 ### 回收站测试 - [ ] 获取回收站列表 - [ ] 从回收站恢复 - [ ] 永久删除 - [ ] 剩余天数显示正确 ### Hooks 测试 - [ ] useProjects 缓存正常 - [ ] useProject 缓存正常 - [ ] useCreateProject 失效缓存 - [ ] useUpdateProject 更新缓存 - [ ] useDeleteProject 失效缓存 - [ ] useTrashProjects 独立缓存 --- ## 已知问题 无 --- ## 后续工作 1. **回收站页面** - 实现完整的回收站 UI 2. **项目分享** - 实现分享功能 UI 3. **成员管理** - 实现协作项目成员管理 UI 4. **批量操作** - 支持批量删除、移动等 5. **离线支持** - 添加离线缓存策略 --- ## 相关文档 - [后端 RFC 131](../../server/rfcs/131-project-trash-system.md) - [后端 Changelog](../../server/changelogs/2026-01-21-project-trash-system.md) - [项目服务文档](../../requirements/backend/04-services/project/project-service.md) --- **变更作者**: System **审核人**: 待定 **发布状态**: 已完成