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.5 KiB

选择共享资源 - 资源树接口方案分析

日期:2026-02-08
范围:CreateProjectModal → 选择共享资源 → 资源内容数据来源
结论:建议新增「项目资源树」专用接口,或采用前端组合 + 懒加载;不推荐仅靠改造 /api/v1/folders/tree 承载「项目下角色/场景/道具」层级。


1. 现状

1.1 选择共享资源面板需要的数据

  • ResourceSelectorPanelResourceSelectorPanel.tsx)当前用 Mock 数据,目标结构为:
    • 虚拟根「我的项目」→ 文件夹项目项目下的角色 / 场景 / 道具(character / scene / prop)
  • 能力:按类型过滤(全部 / 角色 / 场景 / 道具)、搜索、级联选择、展示项目下资源统计(如「角色 15 场景 8 道具 12」)。
  • 前端类型:SharedResourcetype: 'project' | 'folder' | 'character' | 'scene' | 'prop',即需要**至少到「项目 + 项目内资源」**这一层。

1.2 现有接口能力

接口 返回内容 是否满足「资源内容」树
GET /api/v1/folders/tree 根 → 文件夹 → 项目;项目的 children 仅为 []子项目不包含 character/scene/prop 只到「文件夹 + 项目」
GET /api/v1/projects/{id}/resources 某项目的素材分页扁平列表(character/scene/prop 等),非树形 有项目下资源,但需按项目逐个请求、且为列表而非树节点
  • folders/tree 当前参数:maxDepthincludeProjectsincludeSubprojectsincludeFullProjectFields category(前端 shared-resources.tscategory=1 在后端未使用,若要做「我的项目/协作项目」需前后端对齐)。
  • 项目资源列表接口:分页、按类型/标签/搜索过滤,返回的是 items[],不是「树节点 + children」。

2. 方案对比

方案 A:改造 /api/v1/folders/tree

  • 做法:增加参数(如 includeProjectResources=true),当为 true 时对每个项目查询其 character/scene/prop,挂到该项目的 children 下。
  • 优点:一次请求拿到「文件夹 + 项目 + 项目内资源」整棵树,前端实现简单。
  • 缺点
    • 树规模大时(多文件夹 × 多项目 × 每项目多资源)响应体大、耗时长。
    • folders/tree 同时服务「选文件夹/选项目」和「选共享资源」两种场景,职责混合,后续扩展(如仅要统计、懒加载)不便。
    • 与现有「项目节点 children 仅子项目」的语义不一致,易造成复用方误解。

结论:仅适合「树规模很小且确定不会膨胀」的场景;一般不推荐作为唯一方案。


方案 B:新增「项目资源树」专用接口

  • 做法:新增例如 GET /api/v1/shared-resources/treeGET /api/v1/projects/resources/tree,专门返回「可共享资源树」:
    • 结构:虚拟根(可选)→ 文件夹 → 项目 → 可选一层:项目下的 character/scene/prop。
    • 可通过查询参数控制:是否包含资源层级、是否只返回资源统计(如 characterCount/sceneCount/propCount)、category(我的项目/协作项目)、最大深度等。
  • 优点
    • 职责清晰,与「选文件夹」用的 folders/tree 分离。
    • 可单独做性能设计:例如先只返回「文件夹 + 项目 + 统计」,项目下明细按需懒加载或另接口分页。
    • 前端 ResourceSelectorPanelgetShareableFoldersAndProjects 的语义一致,便于对接。
  • 缺点:多一个接口需要维护、文档与测试。

结论推荐,尤其当产品需要「一棵清晰的、可扩展的共享资源树」时。


方案 C:前端组合现有接口 + 懒加载

  • 做法
    • 用现有 folders/tree(或对齐后的 getShareableFoldersAndProjects)拉取「文件夹 + 项目」树。
    • 项目节点展示时,可用「项目资源统计」接口(若存在)只显示数量;用户展开某项目时再请求 GET /api/v1/projects/{projectId}/resources,将结果转为树子节点挂到该节点下(懒加载)。
  • 优点:不新增后端接口,首屏只加载文件夹+项目,体积小、响应快。
  • 缺点:展开多个项目时会有多次请求;前端需维护「树节点 + 懒加载状态」逻辑。

结论:在不新增接口的前提下可作为过渡或长期方案;若已有或计划有「项目资源统计」接口,体验会更好。


3. 建议

  1. 资源内容(到 character/scene/prop)

    • 不推荐仅通过改造 folders/tree 把「项目下资源」塞进同一棵树并作为主方案(职责与性能考虑)。
    • 推荐二选一或组合使用:
      • 方案 B:新增「项目资源树」接口,专门服务「选择共享资源」场景,便于后续加统计、过滤、懒加载。
      • 方案 C:沿用 folders/tree + 按项目懒加载 projects/{id}/resources,首屏轻量、不增新接口。
  2. 若选方案 B

    • 建议接口设计时考虑:
      • 是否先只返回「文件夹 + 项目 + 每项目资源统计」,明细(character/scene/prop 列表)通过原 projects/{id}/resources 按需加载,以控制首包体积。
    • 前端 ResourceSelectorPanel 中已注释的 getShareableFoldersAndProjects 可改为调用新树接口(或先接 folders/tree + 统计/明细按需请求)。
  3. 若选方案 C

    • 前端需要:
      • folders/tree(或带 category 的等价能力)拿 文件夹+项目;
      • 项目节点展开时请求 getProjectResources(projectId)(及可选 getProjectResourceStats)并挂到节点;
      • 统一成 ResourceSelectorPanel 所需的树形与 SharedResource 类型。
  4. 与 CreateProjectModal 的衔接

    • 无论 B 或 C,提交时仍将选中项整理为 sharedResources: [{ id, type }] 传给创建/更新项目 API(当前代码中 TODO 部分),后端需有对应字段与校验。

4. 涉及文件(参考)

  • 前端:client/src/components/features/project/CreateProjectModal.tsxResourceSelectorPanel.tsxshared-resources.tstypes/shared-resource.ts
  • 后端:server/app/api/v1/folders.py/tree)、server/app/services/folder_service.pyserver/app/repositories/folder_repository.pyserver/app/api/v1/project_resources.py/projects/{id}/resources