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.
12 KiB
12 KiB
剧本管理服务完整实现
变更日期:2026-02-04
变更类型:功能实现
影响范围:后端 - 剧本管理模块
变更概述
完整实现剧本管理服务(Screenplay Service)的所有功能,包括 Repository 层、Service 层、Schema 层和 API 层,覆盖剧本 CRUD、版本管理、默认标签设置等核心功能。
变更详情
1. Repository 层补充
文件:server/app/repositories/screenplay_repository.py
新增方法:
get_by_project()- 获取项目的剧本列表(分页)count_by_project()- 统计项目剧本数量create_version()- 创建版本记录get_versions()- 获取版本历史
技术要点:
- 使用 SQLModel 的
select()构建查询 - 支持状态过滤和分页
- 按创建时间倒序排序
- 使用
flush()而非commit()(符合 Repository 职责)
2. Model 层补充
新增文件:server/app/models/screenplay_version.py
模型定义:
class ScreenplayVersion(SQLModel, table=True):
"""剧本版本表"""
version_id: UUID
screenplay_id: UUID
version_number: int
content_snapshot: Optional[str]
change_summary: Optional[str]
word_count: int
scene_count: int
character_count: int
created_by: UUID
created_at: datetime
技术要点:
- 使用 UUID v7 作为主键
- 使用 TIMESTAMPTZ 存储时间戳
- 使用
generate_uuid_v7()生成 UUID
3. Service 层补充
文件:server/app/services/screenplay_service.py
新增方法:
get_screenplays()- 获取剧本列表create_screenplay()- 创建文本剧本update_screenplay()- 更新剧本approve_screenplay()- 审批剧本get_screenplay_versions()- 获取版本历史set_character_default_tag()- 设置角色默认标签set_location_default_tag()- 设置场景默认标签set_prop_default_tag()- 设置道具默认标签_get_default_thumbnail()- 获取默认缩略图_create_version()- 创建版本记录
业务逻辑:
剧本创建
- 验证内容非空
- 计算字数统计
- 创建初始版本(version = 1)
- 使用
commit()提交事务
剧本更新
- 检测内容变化
- 内容变化时自动创建新版本
- 版本号自增
- 记录变更摘要
默认标签设置
- 验证标签属于该元素
- 更新
default_tag_id字段 - 自动计算默认缩略图(查询标签下的第一个资源)
- 优先使用
thumbnail_url,若为空则使用file_url
技术要点:
- 所有方法使用
async/await - 使用
%-formatting格式化日志 - 异常日志使用
exc_info=True - Service 层使用
commit()提交事务 - 权限检查使用
_check_project_permission()
4. Schema 层补充
文件:server/app/schemas/screenplay.py
新增 Schema:
VersionResponse- 版本响应模型ScreenplayListItem- 剧本列表项模型ScreenplayListResponse- 剧本列表响应模型
已存在 Schema:
ScreenplayCreate- 创建剧本请求ScreenplayUpdate- 更新剧本请求ScreenplayResponse- 剧本响应SetDefaultTagRequest- 设置默认标签请求(在 screenplay_tag.py)SetDefaultTagResponse- 设置默认标签响应(在 screenplay_tag.py)
5. API 层补充
文件:server/app/api/v1/screenplays.py
新增 API 端点:
剧本 CRUD
GET /api/v1/screenplays- 获取剧本列表POST /api/v1/screenplays- 创建文本剧本GET /api/v1/screenplays/{id}- 获取剧本详情PATCH /api/v1/screenplays/{id}- 更新剧本POST /api/v1/screenplays/{id}/approve- 审批剧本GET /api/v1/screenplays/{id}/versions- 获取版本历史
默认标签管理
PUT /api/v1/screenplays/characters/{id}/default-tag- 设置角色默认标签PUT /api/v1/screenplays/locations/{id}/default-tag- 设置场景默认标签PUT /api/v1/screenplays/props/{id}/default-tag- 设置道具默认标签
已存在 API 端点:
POST /api/v1/screenplays/{id}/characters- 创建角色GET /api/v1/screenplays/{id}/characters- 获取角色列表POST /api/v1/screenplays/{id}/locations- 创建场景GET /api/v1/screenplays/{id}/locations- 获取场景列表POST /api/v1/screenplays/{id}/props- 创建道具GET /api/v1/screenplays/{id}/props- 获取道具列表POST /api/v1/screenplays/{id}/parse- AI 解析剧本POST /api/v1/screenplays/upload-and-parse- 上传并解析文件POST /api/v1/screenplays/{id}/parse-file- 手动触发文件解析GET /api/v1/screenplays/{id}/parse-status- 查询解析状态
技术要点:
- 使用统一响应格式
success_response() - 所有端点都需要认证(
Depends(get_current_user)) - 使用 Query 参数进行分页和过滤
- 使用 Pydantic 模型验证请求体
- 日志记录关键操作
技术栈符合性
1. 异步编程
- ✅ 所有数据库操作使用
async/await - ✅ Repository 使用
flush(),Service 使用commit() - ✅ 使用
AsyncSession而非Session
2. 日志规范
- ✅ 使用
get_logger(__name__)获取模块级 logger - ✅ 使用
%-formatting格式化日志消息 - ✅ 异常日志使用
exc_info=True - ✅ 日志消息使用中文
3. 时间戳
- ✅ 使用
datetime.now(timezone.utc)生成 UTC 时间 - ✅ 数据库字段使用
TIMESTAMPTZ类型 - ✅ 模型使用
TIMESTAMP(timezone=True)
4. UUID 生成
- ✅ 使用
generate_uuid_v7()生成 UUID v7 - ✅ 数据库字段使用
PG_UUID(as_uuid=True)
5. API 响应格式
- ✅ 使用统一响应格式
success_response() - ✅ 包含
success,message,data字段 - ✅ 包含
timestamp字段
业务流程
1. 创建文本剧本流程
用户提交 → API 验证 → Service 检查权限 → Repository 创建剧本
→ Service 创建初始版本 → Service commit → 返回结果
2. 更新剧本流程
用户提交 → API 验证 → Service 检查权限 → Service 检测内容变化
→ Repository 更新剧本 → Service 创建新版本(如果内容变化)
→ Service commit → 返回结果
3. 设置默认标签流程
用户提交 → API 验证 → Service 检查权限 → Service 验证标签
→ Repository 更新 default_tag_id → Service 查询默认缩略图
→ Service commit → 返回结果(含缩略图 URL)
4. 获取剧本列表流程
用户请求 → API 验证 → Service 检查权限 → Repository 查询列表
→ Repository 统计总数 → Service 计算分页 → 返回结果
数据库影响
新增表
screenplay_versions- 剧本版本表(已在迁移中创建)
已存在表
screenplays- 剧本表screenplay_characters- 角色表screenplay_locations- 场景表screenplay_props- 道具表
字段说明
default_tag_id- 默认标签 ID(角色/场景/道具表)version- 版本号(剧本表)approved_by- 审批人 ID(剧本表)approved_at- 审批时间(剧本表)
API 示例
1. 获取剧本列表
请求:
GET /api/v1/screenplays?project_id=019d1234-5678-7abc-def0-111111111111&page=1&page_size=20
Authorization: Bearer {token}
响应:
{
"success": true,
"code": 200,
"message": "Success",
"data": {
"items": [
{
"screenplay_id": "019d1234-5678-7abc-def0-222222222222",
"project_id": "019d1234-5678-7abc-def0-111111111111",
"name": "第一集剧本",
"type": "text",
"version": 2,
"word_count": 5000,
"status": "draft",
"created_at": "2026-02-04T10:00:00Z",
"updated_at": "2026-02-04T11:00:00Z"
}
],
"total": 15,
"page": 1,
"page_size": 20,
"total_pages": 1
},
"timestamp": "2026-02-04T12:00:00+00:00"
}
2. 创建文本剧本
请求:
POST /api/v1/screenplays
Authorization: Bearer {token}
Content-Type: application/json
{
"project_id": "019d1234-5678-7abc-def0-111111111111",
"name": "第一集剧本",
"content": "场景1:室内 - 咖啡厅 - 白天\n\n张三坐在窗边..."
}
响应:
{
"success": true,
"code": 201,
"message": "剧本创建成功",
"data": {
"screenplay_id": "019d1234-5678-7abc-def0-222222222222",
"project_id": "019d1234-5678-7abc-def0-111111111111",
"name": "第一集剧本",
"type": "text",
"content": "场景1:室内 - 咖啡厅 - 白天\n\n张三坐在窗边...",
"version": 1,
"word_count": 5000,
"status": "draft",
"created_at": "2026-02-04T10:00:00Z",
"updated_at": "2026-02-04T10:00:00Z"
},
"timestamp": "2026-02-04T10:00:00+00:00"
}
3. 设置角色默认标签
请求:
PUT /api/v1/screenplays/characters/019d1234-5678-7abc-def0-333333333333/default-tag
Authorization: Bearer {token}
Content-Type: application/json
{
"tag_id": "019d1234-5678-7abc-def0-444444444444"
}
响应:
{
"success": true,
"code": 200,
"message": "角色默认标签设置成功",
"data": {
"character_id": "019d1234-5678-7abc-def0-333333333333",
"name": "孙悟空",
"default_tag_id": "019d1234-5678-7abc-def0-444444444444",
"default_thumbnail_url": "https://storage.jointo.ai/resources/abc123_thumb.jpg"
},
"timestamp": "2026-02-04T12:00:00+00:00"
}
测试建议
单元测试
-
test_screenplay_repository.py- Repository 层测试- 测试
get_by_project()分页和过滤 - 测试
count_by_project()统计 - 测试
create_version()版本创建 - 测试
get_versions()版本查询
- 测试
-
test_screenplay_service.py- Service 层测试- 测试
create_screenplay()创建剧本 - 测试
update_screenplay()更新剧本(内容变化时创建版本) - 测试
set_character_default_tag()设置默认标签 - 测试
_get_default_thumbnail()获取缩略图
- 测试
集成测试
test_screenplay_api.py- API 集成测试- 测试剧本 CRUD 完整流程
- 测试版本管理流程
- 测试默认标签设置流程
- 测试权限控制
相关文档
后续工作
1. 测试编写
- 编写 Repository 层单元测试
- 编写 Service 层单元测试
- 编写 API 集成测试
2. 功能增强
- 实现剧本搜索功能(全文搜索)
- 实现剧本导出功能(PDF/DOCX)
- 实现剧本对比功能(版本对比)
- 实现剧本协作功能(多人编辑)
3. 性能优化
- 添加剧本列表缓存
- 优化版本历史查询(分页)
- 优化默认缩略图查询(缓存)
变更影响
影响范围
- ✅ 后端 - 剧本管理模块
- ✅ 数据库 - screenplay_versions 表
- ⚠️ 前端 - 需要对接新增的 API 端点
兼容性
- ✅ 向后兼容:所有新增功能不影响现有功能
- ✅ 数据库兼容:使用已存在的表结构
- ✅ API 兼容:新增端点不影响现有端点
风险评估
- 🟢 低风险:所有功能都是新增,不修改现有逻辑
- 🟢 低风险:完全符合技术栈规范
- 🟢 低风险:日志完善,便于调试
变更人:AI Assistant
审核人:待审核
变更日期:2026-02-04