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

资源详情API与预览面板集成

日期: 2026-02-08
类型: 功能实现
影响范围: 后端API + 前端预览面板

概述

实现了项目资源(角色/场景/道具)的详情API,并集成到预览面板中,支持展示资源的标签列表及其关联图片。

背景

用户在资源面板点击角色/场景/道具时,需要在预览面板中查看:

  1. 资源的基础信息
  2. 资源的变体标签列表(如角色的"便装"、"正装")
  3. 每个标签关联的图片资源作为缩略图

之前只有列表API(/resource-library/*),无法单独获取某个资源的完整详情。

实施方案

后端改动

1. Service层新增方法(resource_library_service.py

async def get_character_detail(user_id, project_id, character_id)
async def get_location_detail(user_id, project_id, location_id)
async def get_prop_detail(user_id, project_id, prop_id)

逻辑

  • 复用现有的 _build_*_with_resources() 方法
  • 查询 project_element_tags 表获取标签
  • 通过 project_resources.element_tag_id 关联获取每个标签的图片资源
  • 返回标签列表,每个标签包含:
    • tag_id
    • tag_label
    • resource_count: 关联的图片数量(动态计算)
    • thumbnail_url: 第一张图片的缩略图URL

2. API层新增路由(project_elements.py

GET /api/v1/projects/{project_id}/characters/{character_id}
GET /api/v1/projects/{project_id}/locations/{location_id}
GET /api/v1/projects/{project_id}/props/{prop_id}

响应示例

{
  "data": {
    "character_id": "xxx",
    "name": "孙悟空",
    "has_tags": true,
    "tags": [
      {
        "tag_id": "tag-1",
        "tag_label": "便装",
        "description": "日常装扮",
        "display_order": 0,
        "resource_count": 3,
        "thumbnail_url": "https://..."
      }
    ]
  }
}

前端改动

1. API Client 扩展(project-elements.ts

新增类型定义和API方法:

export interface CharacterDetailResponse {
  character_id: string;
  name: string;
  tags: ElementTag[];
  // ...
}

projectElementsApi.getCharacterDetail(projectId, characterId)
projectElementsApi.getLocationDetail(projectId, locationId)
projectElementsApi.getPropDetail(projectId, propId)

2. 新增 Hook(useProjectElementsDetail.ts

useCharacterDetail(projectId, characterId)
useLocationDetail(projectId, locationId)
usePropDetail(projectId, propId)

3. 修改预览数据Hook(usePreviewData.ts

变更前

  • 使用资源库列表API获取数据
  • metadata.tags 读取标签(mock数据)

变更后

  • 根据资源类型调用对应的详情API
  • 直接使用API返回的真实标签数据
  • 格式化为统一的 resource 对象供预览面板使用
const { data: characterDetail } = useCharacterDetail(projectId, characterId);
const resource = {
  id: characterDetail.character_id,
  metadata: {
    tags: characterDetail.tags.map(tag => ({
      tag_id: tag.tag_id,
      tag_label: tag.tag_label,
      resource_count: tag.resource_count,
      thumbnail_url: tag.thumbnail_url,
    }))
  }
};

数据流

1. 用户点击资源面板的"孙悟空"角色
   ↓
2. ProjectResourcePanel 调用 selectResource('characterId', 'character')
   ↓
3. usePreviewData 根据 selectedResourceType 调用 useCharacterDetail
   ↓
4. 后端 GET /api/v1/projects/{projectId}/characters/{characterId}
   ↓
5. ResourceLibraryService.get_character_detail()
   - 查询 project_element_tags 表
   - 查询 project_resources 表(通过 element_tag_id)
   - 构建标签列表(每个标签含 thumbnail_url)
   ↓
6. 前端接收数据,格式化为统一的 resource 对象
   ↓
7. PreviewPanel 渲染标签缩略图列表

技术细节

标签的 resource_count 计算

数据库层面

  • project_element_tags没有 resource_count 字段
  • 通过 SQL JOIN 动态计算:
    resources = await project_resource_repo.get_by_element_tag_id(tag.tag_id)
    resource_count = len(resources)
    

标签的 thumbnail_url 来源

取标签关联的第一张图片的缩略图:

thumbnail_url = resources[0].thumbnail_url or resources[0].file_url

API路由规划

  • 详情接口: /api/v1/projects/{projectId}/characters/{characterId}
  • 列表接口: /api/v1/projects/{projectId}/characters
  • 资源库接口(逐步废弃): /api/v1/projects/{projectId}/resource-library/characters

未来计划用 /characters 替代 /resource-library/characters

测试建议

  1. 后端测试

    curl -X GET "http://localhost:8000/api/v1/projects/{projectId}/characters/{characterId}" \
      -H "Authorization: Bearer {token}"
    
  2. 前端测试

    • 在资源面板点击角色/场景/道具
    • 验证预览面板显示标签列表
    • 验证每个标签显示正确的缩略图

后续扩展

  1. 新增标签功能(待实现):

    • 调用 POST /api/v1/projects/{projectId}/element-tags
    • 刷新详情数据
  2. 上传图片到标签(待实现):

    • 调用 POST /api/v1/projects/{projectId}/resources
    • 传入 element_tag_id 关联到标签
  3. AI生成标签图片(暂不实现):

    • 根据标签描述生成图片
    • 自动关联到标签

影响的文件

后端

  • server/app/services/resource_library_service.py - 新增3个详情方法
  • server/app/api/v1/project_elements.py - 新增3个详情路由

前端

  • client/src/services/api/project-elements.ts - 新增详情API方法
  • client/src/hooks/api/useProjectElementsDetail.ts - 新增详情Hooks
  • client/src/hooks/api/index.ts - 导出新Hooks
  • client/src/components/features/preview/hooks/usePreviewData.ts - 使用详情API

注意事项

  1. 兼容性:实拍资源(footage)仍使用资源库API,未来需统一
  2. 性能:详情API会查询标签和关联资源,数据量大时需优化
  3. 缓存:前端使用 React Query 缓存,5分钟有效期