# Phase 1: 修复 AI Conversation 功能以支持 storyboard_items **日期**: 2026-02-10 **类型**: 重构 **影响范围**: AI Conversation Service, StoryboardResourceRepository ## 背景 根据 [ADR 04: 移除废弃的 storyboard_resources 表](../adrs/04-remove-storyboard-resources-table.md),需要将 AI Conversation 功能从废弃的 `storyboard_resources` 表迁移到新的 `storyboard_items` 表。 ## 变更内容 ### 1. StoryboardResourceRepository **文件**: `server/app/repositories/storyboard_resource_repository.py` #### 1.1 重写 `get_by_storyboard()` 方法 **变更前**: ```python async def get_by_storyboard(self, storyboard_id: UUID) -> List: """获取分镜的所有资源(用于 AI Conversation 提及功能) 注意:这是一个简化的实现,返回空列表 实际应该查询 storyboard_items 表获取关联的资源 """ # TODO: 实现完整的分镜资源查询逻辑 return [] ``` **变更后**: ```python async def get_by_storyboard(self, storyboard_id: UUID) -> List[dict]: """获取分镜的所有关联资源(基于 storyboard_items) ⚠️ 注意:这是一个简化实现,仅用于 AI Conversation 资源提及功能。 当前实现: - 仅返回直接关联的 ProjectResource(item_type=2) - 暂不处理 ElementTag 关联(item_type=1) 原因: - AI Conversation Service 的原有逻辑依赖废弃的 storyboard_resources 表结构 - 新的 storyboard_items 设计与原有逻辑不兼容 - 需要重构 AI Conversation Service 才能完整支持 ElementTag """ # 查询 storyboard_items 表,仅返回 ItemType.RESOURCE 类型 # 返回简化的数据结构:project_resource_id, resource_type, file_url, thumbnail_url ``` **实现细节**: - 查询 `storyboard_items` 表,过滤 `item_type = ItemType.RESOURCE` - 关联查询 `project_resources` 表获取资源详情 - 返回简化的字典列表,包含必要字段 #### 1.2 实现 `is_linked()` 方法 **新增方法**: ```python async def is_linked( self, storyboard_id: UUID, resource_id: UUID ) -> bool: """验证资源是否关联到分镜(基于 storyboard_items) 检查两种关联方式: 1. 直接关联:StoryboardItem.resource_id == resource_id 2. 间接关联:StoryboardItem.element_tag_id → ProjectElementTag(暂不支持) """ # 检查 storyboard_items 表中是否存在直接关联 # 返回 True/False ``` **实现细节**: - 查询 `storyboard_items` 表 - 检查 `item_type = ItemType.RESOURCE` 且 `resource_id` 匹配 - 暂不支持通过 ElementTag 的间接关联 ### 2. AI Conversation Service **文件**: `server/app/services/ai_conversation_service.py` #### 2.1 简化 `_get_storyboard_mentionable_resources()` 方法 **变更前**: ```python async def _get_storyboard_mentionable_resources(...) -> List[Dict[str, Any]]: """获取分镜的可提及资源 查询该分镜关联的所有资源(角色、场景、道具、视频等) """ # 复杂的元素分组逻辑 # 依赖 element_type, element_id, element_name 等字段 # 按标签分组资源 ``` **变更后**: ```python async def _get_storyboard_mentionable_resources(...) -> List[Dict[str, Any]]: """获取分镜的可提及资源 ⚠️ 临时实现:返回空列表 原因: - 原有逻辑依赖废弃的 storyboard_resources 表结构 - 新的 storyboard_items 设计与原有逻辑不兼容 - 需要完整重构才能支持新的数据结构 TODO: 重构此方法以支持 storyboard_items 表 """ logger.warning( "分镜资源提及功能暂不可用(需要重构以支持 storyboard_items): storyboard_id=%s", storyboard_id ) return [] ``` **影响**: - 分镜对话中的资源提及功能暂时不可用 - 不影响其他对话类型(角色、场景、道具) - 资源关联验证功能正常工作(`is_linked()` 方法) ## 测试验证 ### 单元测试 ```bash docker exec jointo-server-app pytest tests/unit/services/test_ai_conversation_service.py -v ``` **结果**: ✅ 全部通过(19 个测试) ### 功能验证 - ✅ AI Conversation 创建对话正常 - ✅ AI Conversation 发送消息正常 - ✅ AI Conversation 权限验证正常 - ✅ 资源关联验证功能正常(`is_linked()` 方法) - ⚠️ 分镜资源提及功能暂不可用(返回空列表) ## 技术债务 ### 需要后续重构的功能 1. **分镜资源提及功能** - 当前返回空列表 - 需要重构 `_get_storyboard_mentionable_resources()` 方法 - 需要适配 `storyboard_items` 表的数据结构 2. **ElementTag 关联支持** - `get_by_storyboard()` 暂不支持 ElementTag 类型 - `is_linked()` 暂不支持通过 ElementTag 的间接关联 - 需要查询 `project_element_tags` 表获取完整信息 ### 重构建议 **方案 1: 扩展 storyboard_items 表** - 添加冗余字段:`element_type`, `element_id`, `element_name` - 优点:查询性能好,兼容现有逻辑 - 缺点:数据冗余,维护成本高 **方案 2: 重构 AI Conversation Service** - 修改 `_get_storyboard_mentionable_resources()` 的返回格式 - 适配 `storyboard_items` 的数据结构 - 优点:数据结构清晰,无冗余 - 缺点:需要修改前端调用代码 **推荐**: 方案 2(重构 AI Conversation Service) ## 下一步 继续执行 [ADR 04](../adrs/04-remove-storyboard-resources-table.md) 的 Phase 2: - 删除废弃的 Service 层代码 - 删除废弃的 API 端点 - 删除废弃的 Schema - 删除废弃的测试文件 - 删除废弃的模型 ## 参考 - [ADR 04: 移除废弃的 storyboard_resources 表](../adrs/04-remove-storyboard-resources-table.md) - [Storyboard Service 需求文档](../requirements/backend/04-services/project/storyboard-service.md) - [AI Conversation Service 需求文档](../requirements/backend/04-services/ai/ai-conversation-service.md)