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.
 

9.6 KiB

项目资源服务实现总结

日期: 2026-02-02
类型: 功能实现
影响范围: 后端 - 项目资源管理、子项目功能

概述

完整实现了项目资源服务(ProjectResourceService)和子项目功能,支持项目专属素材管理(角色、场景、道具、实拍)和分镜素材关联。

实现内容

1. 数据模型

ProjectResource 模型 (server/app/models/project_resource.py)

  • 支持 4 种素材类型:角色(1)、场景(2)、道具(3)、实拍(4)
  • 文件信息:URL、缩略图、尺寸、MIME 类型、校验和
  • 标签关联:element_tag_idelement_nametag_label(冗余字段)
  • AI 生成:ai_job_idextra_data(JSONB)
  • 使用统计:usage_count(引用计数)
  • 软删除:deleted_at

StoryboardResource 关联模型

  • 多对多关联:分镜 ↔ 素材
  • 类型标记:resource_type(冗余存储)
  • 自动维护 usage_count

Project 模型扩展

  • parent_project_id: 父项目 ID(子项目功能)
  • screenplay_id: 关联剧本 ID
  • is_subproject 属性:判断是否为子项目

2. 仓储层

ProjectResourceRepository (server/app/repositories/project_resource_repository.py)

  • create(): 创建素材
  • get_by_id(): 获取单个素材
  • get_by_project(): 获取项目素材列表(支持类型、标签、搜索过滤)
  • update(): 更新素材
  • delete(): 软删除素材
  • get_by_checksum(): 通过校验和查找(去重)
  • increment_usage() / decrement_usage(): 维护使用计数

ProjectRepository 扩展

  • create_subproject(): 创建子项目
  • get_subprojects(): 获取子项目列表
  • count_subprojects(): 统计子项目数量

3. Schema 定义

请求 Schema (server/app/schemas/project_resource.py)

  • ProjectResourceCreate: 创建素材(上传)
  • ProjectResourceUpdate: 更新素材
  • AIGenerateRequest: AI 生成素材请求

响应 Schema

  • ProjectResourceResponse: 素材详情
  • ProjectResourceListResponse: 素材列表(分页)
  • ResourceUsageResponse: 使用统计

4. 服务层

ProjectResourceService (server/app/services/project_resource_service.py)

  • 素材上传

    • upload_image(): 上传图片素材
    • upload_video(): 上传视频素材(支持 ffmpeg 处理)
    • 自动生成缩略图
    • 文件去重(基于 SHA256)
  • AI 生成

    • generate_resource(): AI 生成素材
    • 支持角色、场景、道具生成
    • 自动关联 AI 任务
  • 素材管理

    • get_resource(): 获取素材详情
    • list_resources(): 获取素材列表(支持过滤、搜索、分页)
    • update_resource(): 更新素材
    • delete_resource(): 删除素材
    • get_usage_stats(): 获取使用统计
  • 权限检查

    • _check_project_permission(): 检查项目权限

StoryboardResourceService (server/app/services/storyboard_resource_service.py)

  • add_resource_to_storyboard(): 添加素材到分镜
  • remove_resource_from_storyboard(): 从分镜移除素材
  • get_storyboard_resources(): 获取分镜的所有素材
  • get_resource_storyboards(): 获取素材关联的分镜
  • batch_add_resources(): 批量添加素材
  • batch_remove_resources(): 批量移除素材
  • 自动维护 usage_count 字段

ProjectService 扩展

  • create_subproject(): 创建子项目
  • get_subprojects(): 获取子项目列表(分页)

5. API 路由

ProjectResourcesRouter (server/app/api/v1/project_resources.py)

POST   /api/v1/projects/{project_id}/resources/upload/image    # 上传图片
POST   /api/v1/projects/{project_id}/resources/upload/video    # 上传视频
POST   /api/v1/projects/{project_id}/resources/generate        # AI 生成
GET    /api/v1/projects/{project_id}/resources                 # 获取列表
GET    /api/v1/projects/{project_id}/resources/{resource_id}   # 获取详情
PUT    /api/v1/projects/{project_id}/resources/{resource_id}   # 更新素材
DELETE /api/v1/projects/{project_id}/resources/{resource_id}   # 删除素材
GET    /api/v1/projects/{project_id}/resources/{resource_id}/usage # 使用统计

ProjectsRouter 扩展 (server/app/api/v1/projects.py)

GET    /api/v1/projects/{parent_project_id}/subprojects        # 获取子项目列表

6. 数据库迁移

迁移脚本 (server/alembic/versions/20260202_1600_add_project_resources_and_subprojects.py)

project_resources 表

  • 主键:project_resource_id (UUID v7)

  • 索引:

    • idx_project_resources_project_id (project_id, WHERE deleted_at IS NULL)
    • idx_project_resources_type (type, WHERE deleted_at IS NULL)
    • idx_project_resources_created_by (created_by, WHERE deleted_at IS NULL)
    • idx_project_resources_checksum (checksum) - 去重
    • idx_project_resources_element_tag_id (element_tag_id, WHERE NOT NULL)
    • idx_project_resources_ai_job_id (ai_job_id, WHERE NOT NULL)
    • idx_project_resources_usage_count (usage_count, WHERE deleted_at IS NULL)
    • idx_project_resources_extra_data_gin (extra_data) - GIN 索引
    • idx_project_resources_name_trgm (name) - 全文搜索
    • idx_project_resources_element_name_trgm (element_name) - 全文搜索
    • idx_project_resources_tag_label_trgm (tag_label) - 全文搜索
  • 约束:

    • usage_count >= 0
    • 实拍素材不能有标签关联

storyboard_resources 表

  • 主键:id (UUID v7)
  • 索引:
    • idx_storyboard_resources_storyboard_id
    • idx_storyboard_resources_project_resource_id
    • idx_storyboard_resources_type
  • 唯一约束:(storyboard_id, project_resource_id)

projects 表扩展

  • 新增字段:
    • parent_project_id (UUID, nullable)
    • screenplay_id (UUID, nullable)
  • 索引:
    • idx_projects_parent_project_id
    • idx_projects_screenplay_id
  • 约束:子项目必须有 screenplay_id

7. Docker 配置

Dockerfile 更新 (server/Dockerfile)

  • 添加 ffmpeg 依赖(视频处理)

技术亮点

1. 文件去重

  • 基于 SHA256 校验和
  • 避免重复上传相同文件
  • 节省存储空间

2. 使用计数维护

  • 自动维护 usage_count 字段
  • 通过 StoryboardResourceService 统一管理
  • 支持批量操作

3. 冗余字段设计

  • element_nametag_label 冗余存储
  • 减少 JOIN 查询
  • 提升列表查询性能

4. 全文搜索

  • 使用 pg_trgm 扩展
  • 支持模糊搜索素材名称、元素名称、标签
  • GIN 索引优化 JSONB 查询

5. 权限控制

  • 继承项目权限
  • 支持 viewer/editor/owner 角色
  • 应用层校验(无物理外键)

6. 软删除

  • deleted_at 字段
  • 索引过滤 WHERE deleted_at IS NULL
  • 保留历史数据

数据流程

上传素材流程

1. 用户上传文件 → API 接收
2. 计算 SHA256 校验和
3. 检查是否已存在(去重)
4. 上传到文件存储服务
5. 生成缩略图(图片/视频)
6. 创建 ProjectResource 记录
7. 返回素材信息

AI 生成素材流程

1. 用户提交生成请求 → API 接收
2. 检查项目权限
3. 调用 AI 服务生成素材
4. 下载生成的文件
5. 上传到文件存储
6. 创建 ProjectResource 记录(关联 ai_job_id)
7. 返回素材信息

分镜关联素材流程

1. 用户添加素材到分镜
2. 创建 StoryboardResource 关联
3. 增加 ProjectResource.usage_count
4. 返回成功

移除时:
1. 删除 StoryboardResource 关联
2. 减少 ProjectResource.usage_count
3. 返回成功

待实现功能

1. 分镜素材关联 API

  • 需要在 storyboards 路由中添加:
    • POST /api/v1/storyboards/{storyboard_id}/resources - 添加素材
    • DELETE /api/v1/storyboards/{storyboard_id}/resources/{resource_id} - 移除素材
    • GET /api/v1/storyboards/{storyboard_id}/resources - 获取素材列表

2. 视频处理优化

  • 当前为同步处理,大文件可能超时
  • 建议改为异步任务(Celery)
  • 支持进度查询

3. 缩略图生成优化

  • 支持多种尺寸
  • 支持自定义裁剪
  • 异步生成

4. 素材库集成

  • 从素材库导入到项目
  • 支持批量导入
  • 自动关联标签

5. 测试

  • 单元测试
  • 集成测试
  • API 测试

注意事项

1. 字段命名变更

  • ⚠️ 原设计中的 metadata 字段改为 extra_data
  • 原因:metadata 是 SQLAlchemy 保留字段名
  • 影响:迁移脚本、模型定义、索引名称

2. ffmpeg 依赖

  • 需要重新构建 Docker 镜像:
    docker compose build app
    docker compose up -d app
    

3. 权限检查

  • 所有操作都需要检查项目权限
  • 使用 ProjectService._check_permission() 方法
  • 支持 viewer/editor/owner 角色

4. 文件存储

  • 依赖 FileStorageService
  • 支持本地存储和 S3
  • 自动生成唯一文件名

相关文档

  • 需求文档:docs/requirements/backend/04-services/project/project-resource-service.md
  • 项目服务文档:docs/requirements/backend/04-services/project/project-service.md
  • 数据库设计:docs/requirements/database-design.md
  • API 设计:docs/requirements/api-design-specification.md

验证清单

  • 数据库迁移成功执行
  • API 路由注册成功
  • 模型定义正确
  • 仓储层实现完整
  • 服务层实现完整
  • Schema 定义完整
  • 子项目功能实现
  • 分镜素材关联服务实现
  • ffmpeg 依赖安装(需要重新构建镜像)
  • API 端点测试
  • 权限检查测试
  • 文件上传测试
  • AI 生成测试

下一步

  1. 重新构建 Docker 镜像(安装 ffmpeg)
  2. 实现分镜素材关联 API
  3. 编写测试用例
  4. 性能优化(异步任务、缓存)
  5. 前端集成