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.
 

6.0 KiB

Storyboard API 响应格式统一与查询参数规范化

日期: 2026-02-11
类型: 重构
影响范围: /api/v1/storyboards 所有接口

变更概述

  1. 统一分镜 API 的响应格式,使其与项目级资源 API(project_elements)保持一致
  2. 规范化查询参数命名,支持 camelCase 格式(前端友好)

问题描述

1. 不一致的响应格式

  1. 响应类型不一致

    • project_elements.py 使用:SuccessResponse[T](来自 app.schemas.common
    • storyboards.py 使用:ApiResponse[T](来自 app.schemas.response
  2. 返回方式不一致

    • project_elements.py:直接返回 SuccessResponse 对象
    • storyboards.py:使用 success_response() 函数返回字典
  3. 序列化方式不一致

    • project_elements.py:依赖 Pydantic 自动序列化
    • storyboards.py:手动调用 model_dump(by_alias=True, mode='json')

2. 查询参数命名不规范

查询参数使用 snake_case,前端需要额外转换:

  • project_id 应支持 projectId
  • page_size 应支持 pageSize
  • include_items 应支持 includeItems
  • shot_size 应支持 shotSize
  • camera_movement 应支持 cameraMovement

解决方案

1. 统一响应格式

采用 project_elements.py 的模式:

  • 使用 SuccessResponse[T] 作为响应模型
  • 直接返回 SuccessResponse 对象
  • 依赖 Pydantic 自动序列化

2. 规范化查询参数

为所有 snake_case 查询参数添加 camelCase alias:

# 修改前
project_id: str = Query(..., description="项目ID")

# 修改后
project_id: str = Query(..., alias="projectId", description="项目ID")

修改内容

1. 导入语句调整

# 修改前
from app.schemas.response import ApiResponse, success_response

# 修改后
from app.schemas.common import SuccessResponse

2. 响应模型调整

所有接口的 response_modelApiResponse[T] 改为 SuccessResponse[T]

3. 返回语句调整

# 修改前
return success_response(
    data=response_data.model_dump(by_alias=True, mode='json'),
    message="分镜列表获取成功"
)

# 修改后
return SuccessResponse(
    data=response_data,
    message="分镜列表获取成功"
)

4. 查询参数 alias 添加

参数名 alias 接口
project_id projectId 所有列表/筛选/搜索接口
page_size pageSize 所有分页接口
include_items includeItems 列表和详情接口
shot_size shotSize 筛选接口
camera_movement cameraMovement 筛选接口

涉及的接口(共 14 个)

分镜 CRUD

  1. GET /storyboards - 获取分镜列表 响应格式 + 查询参数
  2. POST /storyboards - 创建分镜 响应格式
  3. GET /storyboards/{storyboard_id} - 获取分镜详情 响应格式 + 查询参数
  4. PUT /storyboards/{storyboard_id} - 更新分镜 响应格式
  5. DELETE /storyboards/{storyboard_id} - 删除分镜 响应格式

排序管理

  1. POST /storyboards/reorder - 重新排序分镜 响应格式

筛选和搜索

  1. GET /storyboards/filter - 按景别和运镜筛选 响应格式 + 查询参数
  2. GET /storyboards/search - 全文搜索分镜 响应格式 + 查询参数
  3. GET /storyboards/statistics/duration - 获取时长统计 响应格式 + 查询参数

元素关联管理

  1. POST /storyboards/{storyboard_id}/items - 添加元素到分镜 响应格式
  2. GET /storyboards/{storyboard_id}/items - 获取分镜的所有关联元素 响应格式
  3. POST /storyboards/{storyboard_id}/items/reorder - 批量调整元素顺序 响应格式
  4. PATCH /storyboards/items/{item_id} - 更新元素的关联属性 响应格式
  5. DELETE /storyboards/items/{item_id} - 从分镜移除元素 响应格式

技术细节

响应格式保持不变

虽然内部实现改变,但最终的 JSON 响应格式完全一致:

{
  "success": true,
  "code": 200,
  "message": "分镜列表获取成功",
  "data": {
    "items": [...],
    "total": 100,
    "page": 1,
    "pageSize": 50,
    "totalPages": 2
  },
  "timestamp": "2026-02-11T10:30:00Z"
}

查询参数兼容性

添加 alias 后,两种格式都支持:

# snake_case(兼容旧版)
GET /api/v1/storyboards?project_id=xxx&page_size=50&include_items=true

# camelCase(推荐,前端友好)
GET /api/v1/storyboards?projectId=xxx&pageSize=50&includeItems=true

Pydantic 自动序列化优势

  1. 自动处理 camelCase 转换

    • Schema 中配置的 alias_generator=to_camel 自动生效
    • 无需手动调用 model_dump(by_alias=True)
  2. 类型安全

    • 编译时类型检查
    • IDE 自动补全支持
  3. 代码简洁

    • 减少重复的序列化代码
    • 统一的返回模式

影响评估

前端影响

  • 无影响:响应格式完全一致
  • 改进:查询参数支持 camelCase,更符合前端命名习惯

后端影响

  • 代码简化:移除了大量重复的 model_dump() 调用
  • 一致性提升:与其他 API 模块保持统一风格
  • 维护性提升:统一的模式更易于维护和扩展

测试建议

  1. 回归测试

    • 测试所有 14 个接口的响应格式
    • 验证 camelCase 字段名正确转换
    • 验证嵌套对象(如 itemsmetadata)的序列化
  2. 查询参数测试

    • 测试 snake_case 参数(向后兼容)
    • 测试 camelCase 参数(新格式)
    • 测试混合使用两种格式
  3. 集成测试

    • 前端调用接口验证兼容性
    • 验证分页、筛选、搜索功能正常

相关文件

  • server/app/api/v1/storyboards.py - 主要修改文件
  • server/app/schemas/common.py - SuccessResponse 定义
  • server/app/schemas/storyboard.py - 分镜 Schema 定义

参考

  • 参考实现:server/app/api/v1/project_elements.py
  • 查询参数规范:server/app/api/v1/projects.pyserver/app/api/v1/folders.py
  • API 规范:项目统一使用 SuccessResponse 作为成功响应格式