# ResourceLibraryService 实现 **日期**: 2026-02-03 **类型**: 新功能 **影响范围**: 后端服务层、API 层、数据模型 ## 概述 实现了 ResourceLibraryService 服务,用于整合剧本元素(角色、场景、道具)、标签和项目资源的数据,为前端提供统一的资源库接口。 ## 变更内容 ### 1. 新增服务层 **文件**: `server/app/services/resource_library_service.py` 实现了以下核心方法: - `get_characters()` - 获取所有角色列表(包含标签和资源) - `get_locations()` - 获取所有场景列表(包含标签和资源) - `get_props()` - 获取所有道具列表(包含标签和资源) - `get_footage_resources()` - 获取实拍资源列表 - `get_element_with_tags()` - 获取元素的所有标签和资源 **关键特性**: - 支持父子项目资源聚合(`include_subprojects` 参数) - 返回所有元素(包含有资源和无资源的) - 使用 `selectinload` 预加载关联数据,避免 N+1 查询 - 不感知 `storyboard_items` 表(职责分离) - 完整的权限检查和日志记录 ### 2. 新增 Schema 定义 **文件**: `server/app/schemas/resource_library.py` 定义了以下 Pydantic 模型: - `ResourceInTag` - 标签中的资源 - `ElementTag` - 元素标签 - `CharacterWithResources` - 角色(包含标签和资源) - `LocationWithResources` - 场景(包含标签和资源) - `PropWithResources` - 道具(包含标签和资源) - `FootageResource` - 实拍资源 - `ElementWithTags` - 元素详情(包含所有标签和资源) ### 3. 新增 API 路由 **文件**: `server/app/api/v1/resource_library.py` 实现了 5 个 API 端点: ``` GET /api/v1/projects/{project_id}/resource-library/characters GET /api/v1/projects/{project_id}/resource-library/locations GET /api/v1/projects/{project_id}/resource-library/props GET /api/v1/projects/{project_id}/resource-library/footage-resources GET /api/v1/projects/{project_id}/resource-library/elements/{element_type}/{element_id}/tags-with-resources ``` 所有端点支持 `include_subprojects` 查询参数。 ### 4. 新增数据模型 创建了以下 SQLModel 模型: - `server/app/models/screenplay.py` - 剧本主表模型 - `server/app/models/screenplay_character.py` - 剧本角色模型 - `server/app/models/screenplay_location.py` - 剧本场景模型 - `server/app/models/screenplay_prop.py` - 剧本道具模型 - `server/app/models/screenplay_element_tag.py` - 剧本元素标签模型 **关键设计**: - 使用 UUID v7 主键 - 使用 SMALLINT + IntEnum 替代 PostgreSQL ENUM - 使用 `selectinload` 配置关系预加载 - 提供 `*_str` 属性方法用于枚举值转字符串 ### 5. 路由注册 **文件**: `server/app/api/v1/__init__.py` 注册了 `resource_library` 路由到 API v1 路由器。 ## 技术规范遵循 ✅ **UUID v7**: 所有主键使用 UUID v7(应用层生成) ✅ **无物理外键**: 仅在模型层定义关系,数据库层无 FOREIGN KEY 约束 ✅ **SMALLINT 枚举**: 使用 SMALLINT + IntEnum 替代 PostgreSQL ENUM ✅ **日志格式**: 使用 %-formatting 格式化日志 ✅ **异常日志**: 异常日志添加 `exc_info=True` ✅ **API 响应**: 使用 `success_response()` 统一响应格式 ✅ **日志系统**: 使用 `app.core.logging.get_logger` 获取 logger ✅ **权限检查**: 所有方法都进行项目权限验证 ## 数据流程 ### 获取角色列表流程 1. 检查用户对项目的访问权限 2. 获取项目ID列表(包含子项目,如果 `include_subprojects=true`) 3. 查询项目的所有剧本ID 4. 查询剧本的所有角色(预加载标签) 5. 查询标签关联的项目资源 6. 组装返回数据(角色 → 标签 → 资源) ### 父子项目资源聚合 当 `include_subprojects=true` 时: 1. 查询父项目的所有子项目ID 2. 将父项目ID和子项目ID合并为项目ID列表 3. 查询所有项目的剧本和资源 4. 返回聚合后的数据 ## API 使用示例 ### 获取角色列表 ```bash GET /api/v1/projects/{project_id}/resource-library/characters?include_subprojects=false ``` **响应**: ```json { "success": true, "code": 200, "message": "success", "data": [ { "character_id": "uuid", "screenplay_id": "uuid", "name": "张三", "description": "主角", "role_type": "main", "is_offscreen": false, "has_tags": true, "tags": [ { "tag_id": "uuid", "tag_label": "少年", "description": "15岁", "display_order": 0, "resources": [ { "project_resource_id": "uuid", "name": "张三-少年形象", "type": "character", "file_url": "https://...", "thumbnail_url": "https://..." } ] } ] } ], "timestamp": "2026-02-03T10:00:00Z" } ``` ### 获取元素详情 ```bash GET /api/v1/projects/{project_id}/resource-library/elements/character/{character_id}/tags-with-resources ``` ## 依赖关系 ### 依赖的服务 - `ProjectRepository` - 项目权限检查 ### 依赖的模型 - `Screenplay` - 剧本主表 - `ScreenplayCharacter` - 剧本角色 - `ScreenplayLocation` - 剧本场景 - `ScreenplayProp` - 剧本道具 - `ScreenplayElementTag` - 剧本元素标签 - `ProjectResource` - 项目资源 - `Project` - 项目表 ## 性能优化 1. **预加载关联数据**: 使用 `selectinload()` 预加载标签,避免 N+1 查询 2. **批量查询资源**: 收集所有标签ID后批量查询资源,而非逐个查询 3. **索引优化**: 依赖数据库迁移中创建的索引(`screenplay_id`, `element_id`, `element_tag_id`) ## 测试建议 ### 单元测试 - 测试权限检查逻辑 - 测试父子项目资源聚合 - 测试空数据情况(无剧本、无标签、无资源) ### 集成测试 - 测试完整的数据查询流程 - 测试 `include_subprojects` 参数 - 测试不同元素类型的查询 ### 性能测试 - 测试大量角色/标签/资源的查询性能 - 测试预加载是否生效(检查 SQL 查询数量) ## 后续优化 1. **缓存**: 考虑对资源库数据添加 Redis 缓存 2. **分页**: 如果角色/场景/道具数量很大,考虑添加分页支持 3. **搜索**: 添加按名称搜索角色/场景/道具的功能 4. **排序**: 支持自定义排序(按名称、创建时间等) ## 相关文档 - 设计文档: `docs/requirements/backend/04-services/project/resource-library-service.md` - 技术栈规范: `docs/architecture/tech-stack.md` - 数据库迁移: `server/alembic/versions/20260203_1300_create_screenplay_tables.py` ## 作者 Kiro AI Assistant ## 审核状态 - [ ] 代码审核 - [ ] 测试验证 - [ ] 文档审核