You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

6.4 KiB

RFC 122: 文件夹 API 对接

状态: 已实现
创建日期: 2026-01-20
作者: 架构团队


概述

将前端文件夹功能从 Mock API 对接到真实后端 API,实现完整的文件夹管理功能。

动机

  1. 后端文件夹服务已完整实现(RFC 016)
  2. 前端 UI 组件已完成,使用 Mock 数据
  3. 需要对接真实 API 实现完整功能
  4. 为后续清理 Mock 数据做准备

设计方案

架构设计

采用渐进式对接策略,保留 Mock API 作为开发降级方案:

services/
  ├── api/
  │   ├── client.ts           # axios 实例
  │   ├── folders.ts          # 真实 folder API ✅
  │   └── index.ts
  └── mock/                   # 模块化 Mock API
      ├── folderApi.ts        # folder mock(未来可删除)
      ├── projectApi.ts       # project mock
      ├── storyboardApi.ts    # storyboard mock
      ├── resourceApi.ts      # resource mock
      ├── timelineApi.ts      # timeline mock
      └── index.ts

hooks/api/
  ├── useFolders.ts           # folder hooks ✅
  └── index.ts

lib/
  └── api-utils.ts            # 数据转换工具 ✅

核心功能

1. API 服务层 (services/api/folders.ts)

实现的接口:

  • getAll() - 获取文件夹列表(分页)
  • getTree() - 获取树形结构
  • getById() - 获取详情
  • create() - 创建文件夹
  • update() - 更新文件夹
  • delete() - 删除文件夹
  • move() - 移动文件夹
  • getPath() - 获取路径(面包屑)
  • clone() - 克隆文件夹
  • getStats() - 获取统计信息

2. React Query Hooks (hooks/api/useFolders.ts)

实现的 hooks:

  • useFolders() - 查询列表
  • useFolderTree() - 查询树形结构
  • useFolder() - 查询单个文件夹
  • useFolderPath() - 查询路径
  • useCreateFolder() - 创建 mutation
  • useUpdateFolder() - 更新 mutation
  • useDeleteFolder() - 删除 mutation
  • useMoveFolder() - 移动 mutation
  • useCloneFolder() - 克隆 mutation
  • useFolderStats() - 查询统计信息

Query Keys 设计

folderKeys = {
  all: ['folders'],
  lists: () => [...folderKeys.all, 'list'],
  list: (parentId?, page?, pageSize?) => [...folderKeys.lists(), { parentId, page, pageSize }],
  trees: () => [...folderKeys.all, 'tree'],
  tree: (maxDepth?) => [...folderKeys.trees(), { maxDepth }],
  details: () => [...folderKeys.all, 'detail'],
  detail: (id) => [...folderKeys.details(), id],
  paths: () => [...folderKeys.all, 'path'],
  path: (id) => [...folderKeys.paths(), id],
  stats: () => [...folderKeys.all, 'stats'],
  stat: (id, recursive?) => [...folderKeys.stats(), id, { recursive }],
}

缓存策略

  • 列表/树形结构:5 分钟 staleTime
  • 详情:从列表缓存初始化
  • 路径/统计:按需查询

3. 数据转换工具 (lib/api-utils.ts)

处理前后端数据格式差异:

  • keysToCamelCase() - 后端响应 snake_case → 前端 camelCase
  • keysToSnakeCase() - 前端请求 camelCase → 后端 snake_case
  • 递归处理嵌套对象和数组

4. Mock API 模块化重构

services/mockApi.ts (600+ 行) 拆分为独立模块:

  • mock/projectApi.ts
  • mock/storyboardApi.ts
  • mock/resourceApi.ts
  • mock/timelineApi.ts
  • mock/folderApi.ts(未来可删除)

优势

  • 便于维护
  • 清理成本低(删除单个文件即可)
  • 模块独立

组件更新

CreateFolderModal

变更

  • 使用 useCreateFolder()useUpdateFolder() hooks
  • 添加 loading 状态处理
  • 添加 toast 提示
  • 移除 mockDelay() 模拟

代码示例

const createFolder = useCreateFolder();
const updateFolder = useUpdateFolder();

const submitHandler = async (data) => {
  try {
    if (isEditing) {
      await updateFolder.mutateAsync({ id, data });
      toast({ title: '更新成功' });
    } else {
      await createFolder.mutateAsync(data);
      toast({ title: '创建成功' });
    }
    handleClose();
  } catch (error) {
    toast({ title: '操作失败', variant: 'destructive' });
  }
};

实现细节

数据格式转换

后端响应示例(snake_case):

{
  "id": "uuid",
  "name": "文件夹",
  "parent_folder_id": "uuid",
  "owner_id": "uuid",
  "created_at": "2026-01-20T10:00:00Z"
}

前端使用(camelCase):

{
  id: "uuid",
  name: "文件夹",
  parentFolderId: "uuid",
  ownerId: "uuid",
  createdAt: "2026-01-20T10:00:00Z"
}

错误处理

  1. 网络错误:axios 拦截器统一处理
  2. 401 未授权:自动跳转登录页
  3. 业务错误:组件层 try-catch + toast 提示

性能优化

  1. 缓存策略

    • 列表/树:5 分钟 staleTime
    • 详情:从列表缓存初始化
    • 乐观更新:mutation 成功后立即更新缓存
  2. 请求优化

    • 分页查询避免大量数据
    • 树形结构支持限制深度
    • 统计信息按需查询

测试计划

功能测试

  • 创建文件夹(根目录/子文件夹)
  • 更新文件夹(名称/描述/颜色)
  • 删除文件夹(普通/级联)
  • 移动文件夹
  • 克隆文件夹
  • 获取文件夹树
  • 获取文件夹路径

集成测试

  • 与后端 API 联调
  • 错误场景处理
  • 并发操作测试

未来工作

短期(1-2 周)

  1. 完成其他组件对接

    • MoveFolderModal
    • CloneFolderModal
    • FolderContextMenu 操作
    • ProjectSidebar 文件夹树展示
  2. 添加错误边界

    • 网络错误重试
    • 降级到 Mock API

中期(1 个月)

  1. 清理 Mock 数据

    • 删除 services/mock/folderApi.ts
    • 移除环境判断逻辑
  2. 性能优化

    • 虚拟滚动(大量文件夹)
    • 懒加载子节点

长期

  1. 离线支持

    • IndexedDB 缓存
    • 离线操作队列
  2. 实时同步

    • WebSocket 推送
    • 多端协同

清理计划

当所有功能稳定后,清理 Mock 数据:

步骤

  1. 删除 services/mock/folderApi.ts
  2. services/mock/index.ts 移除导出
  3. 完成

清理成本:< 5 分钟

依赖

  • React Query 5.x
  • Axios 1.x
  • TypeScript 5.x

相关文档


实施状态 核心功能已完成,待完善其他组件对接