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

剧本管理服务完整实现

变更日期:2026-02-04
变更类型:功能实现
影响范围:后端 - 剧本管理模块


变更概述

完整实现剧本管理服务(Screenplay Service)的所有功能,包括 Repository 层、Service 层、Schema 层和 API 层,覆盖剧本 CRUD、版本管理、默认标签设置等核心功能。


变更详情

1. Repository 层补充

文件server/app/repositories/screenplay_repository.py

新增方法

  1. get_by_project() - 获取项目的剧本列表(分页)
  2. count_by_project() - 统计项目剧本数量
  3. create_version() - 创建版本记录
  4. 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

新增方法

  1. get_screenplays() - 获取剧本列表
  2. create_screenplay() - 创建文本剧本
  3. update_screenplay() - 更新剧本
  4. approve_screenplay() - 审批剧本
  5. get_screenplay_versions() - 获取版本历史
  6. set_character_default_tag() - 设置角色默认标签
  7. set_location_default_tag() - 设置场景默认标签
  8. set_prop_default_tag() - 设置道具默认标签
  9. _get_default_thumbnail() - 获取默认缩略图
  10. _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

  1. VersionResponse - 版本响应模型
  2. ScreenplayListItem - 剧本列表项模型
  3. ScreenplayListResponse - 剧本列表响应模型

已存在 Schema

  • ScreenplayCreate - 创建剧本请求
  • ScreenplayUpdate - 更新剧本请求
  • ScreenplayResponse - 剧本响应
  • SetDefaultTagRequest - 设置默认标签请求(在 screenplay_tag.py)
  • SetDefaultTagResponse - 设置默认标签响应(在 screenplay_tag.py)

5. API 层补充

文件server/app/api/v1/screenplays.py

新增 API 端点

剧本 CRUD

  1. GET /api/v1/screenplays - 获取剧本列表
  2. POST /api/v1/screenplays - 创建文本剧本
  3. GET /api/v1/screenplays/{id} - 获取剧本详情
  4. PATCH /api/v1/screenplays/{id} - 更新剧本
  5. POST /api/v1/screenplays/{id}/approve - 审批剧本
  6. GET /api/v1/screenplays/{id}/versions - 获取版本历史

默认标签管理

  1. PUT /api/v1/screenplays/characters/{id}/default-tag - 设置角色默认标签
  2. PUT /api/v1/screenplays/locations/{id}/default-tag - 设置场景默认标签
  3. 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"
}

测试建议

单元测试

  1. test_screenplay_repository.py - Repository 层测试

    • 测试 get_by_project() 分页和过滤
    • 测试 count_by_project() 统计
    • 测试 create_version() 版本创建
    • 测试 get_versions() 版本查询
  2. test_screenplay_service.py - Service 层测试

    • 测试 create_screenplay() 创建剧本
    • 测试 update_screenplay() 更新剧本(内容变化时创建版本)
    • 测试 set_character_default_tag() 设置默认标签
    • 测试 _get_default_thumbnail() 获取缩略图

集成测试

  1. test_screenplay_api.py - API 集成测试
    • 测试剧本 CRUD 完整流程
    • 测试版本管理流程
    • 测试默认标签设置流程
    • 测试权限控制

相关文档


后续工作

1. 测试编写

  • 编写 Repository 层单元测试
  • 编写 Service 层单元测试
  • 编写 API 集成测试

2. 功能增强

  • 实现剧本搜索功能(全文搜索)
  • 实现剧本导出功能(PDF/DOCX)
  • 实现剧本对比功能(版本对比)
  • 实现剧本协作功能(多人编辑)

3. 性能优化

  • 添加剧本列表缓存
  • 优化版本历史查询(分页)
  • 优化默认缩略图查询(缓存)

变更影响

影响范围

  • 后端 - 剧本管理模块
  • 数据库 - screenplay_versions 表
  • ⚠️ 前端 - 需要对接新增的 API 端点

兼容性

  • 向后兼容:所有新增功能不影响现有功能
  • 数据库兼容:使用已存在的表结构
  • API 兼容:新增端点不影响现有端点

风险评估

  • 🟢 低风险:所有功能都是新增,不修改现有逻辑
  • 🟢 低风险:完全符合技术栈规范
  • 🟢 低风险:日志完善,便于调试

变更人:AI Assistant
审核人:待审核
变更日期:2026-02-04