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.
 

7.9 KiB

API 标准化迁移 - Storyboards/Resources/Recharge 模块

日期: 2026-02-11
类型: 重构
影响范围: 后端 API
Breaking Changes: 无(兼容性升级)

概述

storyboards.pystoryboard_resources.pystoryboard_board.pyscreenplays.pyresource_library.pyrecharge.py 等 6 个 API 文件迁移到统一的响应格式和异常处理规范,确保与项目整体架构一致。

变更内容

1. resource_library.py - 完整迁移

响应格式迁移

  • 旧格式:使用 success_response() 函数
  • 新格式:使用 SuccessResponse[T] 泛型类

变更前:

from app.schemas.response import success_response

@router.get("/characters", response_model=None)
async def get_characters(...):
    return success_response(data=response_data, code=200)

变更后:

from app.schemas.common import SuccessResponse

@router.get("/characters", response_model=SuccessResponse[ResourceLibraryListResponse])
async def get_characters(...):
    return SuccessResponse(data=response_data, message="角色列表获取成功")

查询参数 camelCase 支持

所有分页参数添加 alias 支持:

  • page_size → 支持 pageSize

示例:

page_size: int = Query(20, ge=1, le=100, alias="pageSize", description="每页数量")

日志规范化

添加结构化日志记录:

logger.info(
    "API: 获取角色列表 | 用户: %s | 项目: %s",
    current_user.user_id,
    project_id
)

Schema 增强

新增 ResourceLibraryListResponse 统一分页响应:

class ResourceLibraryListResponse(BaseModel):
    items: List[Any] = Field(..., description="资源列表")
    total: int = Field(..., description="总数")
    page: int = Field(..., description="当前页码")
    page_size: int = Field(..., alias="pageSize", description="每页数量")
    total_pages: int = Field(..., alias="totalPages", description="总页数")

2. recharge.py - 完整迁移

响应格式迁移

  • 旧格式:使用 ApiResponsesuccess_response()error_response()
  • 新格式:使用 SuccessResponse[T]

变更前:

from app.schemas.response import ApiResponse, success_response, error_response

@router.post("/orders", response_model=ApiResponse[RechargeOrderCreateResponse])
async def create_order(...):
    return success_response(data=result)

变更后:

from app.schemas.common import SuccessResponse

@router.post("/orders", response_model=SuccessResponse[RechargeOrderCreateResponse])
async def create_order(...):
    return SuccessResponse(data=order_response, message="充值订单创建成功")

异常处理标准化

  • 旧方式:返回 error_response(message="...", code=403)
  • 新方式:使用自定义异常类

变更前:

if order.user_id != current_user.user_id:
    return error_response(message="无权查看此订单", code=403)

变更后:

from app.core.exceptions import PermissionError

if order.user_id != current_user.user_id:
    raise PermissionError("无权查看此订单")

查询参数优化

将 Pydantic model 依赖注入改为独立的 Query 参数(更符合 FastAPI 规范):

变更前:

@router.get("/orders")
async def get_orders(
    query: Annotated[RechargeOrderQueryRequest, Depends()],
    ...
):
    payment_status=query.payment_status,
    page=query.page,
    page_size=query.page_size

变更后:

@router.get("/orders")
async def get_orders(
    payment_status: str = Query(None, alias="paymentStatus", description="支付状态筛选"),
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(20, ge=1, le=100, alias="pageSize", description="每页数量"),
    ...
):

3. screenplays.py - 查询参数增强

添加 camelCase 别名支持:

  • project_id → 支持 projectId
  • page_size → 支持 pageSize
  • auto_create_subproject → 支持 autoCreateSubproject

示例:

project_id: UUID = Query(..., alias="projectId", description="项目 ID")
auto_create_subproject: bool = Form(True, alias="autoCreateSubproject", description="是否自动创建子项目")

4. 其他文件状态检查

  • storyboards.py: 已符合规范(使用 SuccessResponse,camelCase alias 完整)
  • storyboard_resources.py: 已符合规范(使用 SuccessResponse,无 Query 参数)
  • storyboard_board.py: 已符合规范(使用 SuccessResponse,camelCase alias 完整)

技术细节

异常处理规范

所有业务异常统一使用 app.core.exceptions 中的自定义异常类:

场景 异常类 状态码
资源不存在 NotFoundError 404
数据验证失败 ValidationError 400
权限不足 PermissionError 403
认证失败 AuthenticationError 401
积分不足 InsufficientCreditsError 402

查询参数规范

所有查询参数必须支持 camelCase(前端规范):

page_size: int = Query(20, alias="pageSize", description="每页数量")

前端可以使用:

  • ?page_size=20 snake_case(后端兼容)
  • ?pageSize=20 camelCase(前端首选)

响应格式规范

所有 API 统一返回 SuccessResponse[T]

{
    "success": true,
    "data": { ... },
    "message": "操作成功",
    "timestamp": "2026-02-11T10:30:00Z"
}

兼容性

向后兼容

  • 查询参数同时支持 snake_casecamelCase
  • 响应格式结构保持一致(仅规范化字段命名)
  • 无 Breaking Changes

前端影响

  • 无需修改前端代码(已使用 camelCase)
  • 响应格式保持一致
  • 错误处理逻辑无变化(HTTP 状态码不变)

测试建议

1. API 响应格式验证

# 资源库 API
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:6170/api/v1/projects/{project_id}/resource-library/characters?pageSize=10"

# 充值订单 API
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:6170/api/v1/recharge/orders?paymentStatus=pending&pageSize=20"

2. 异常处理验证

# 测试权限异常(403)
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:6170/api/v1/recharge/orders/{other_user_order_id}"

# 预期响应:
# {
#   "success": false,
#   "message": "无权查看此订单",
#   "timestamp": "..."
# }

3. 查询参数兼容性测试

# snake_case(旧格式,应该仍然工作)
curl "...?page_size=20"

# camelCase(新格式,应该工作)
curl "...?pageSize=20"

文件清单

修改的文件

  • server/app/api/v1/resource_library.py - 完整迁移(响应格式 + 查询参数 + 日志)
  • server/app/api/v1/recharge.py - 完整迁移(响应格式 + 异常处理 + 查询参数)
  • server/app/api/v1/screenplays.py - 查询参数增强(添加 camelCase alias)
  • server/app/schemas/resource_library.py - 新增分页响应 Schema

已检查的文件(无需修改)

  • server/app/api/v1/storyboards.py - 已符合规范
  • server/app/api/v1/storyboard_resources.py - 已符合规范
  • server/app/api/v1/storyboard_board.py - 已符合规范

参考文档

后续工作

  • 监控生产环境日志,确认无异常
  • 更新 API 文档(Swagger)
  • 通知前端团队(如有必要)
  • 考虑将旧的 app.schemas.response 标记为废弃(Deprecated)

总结

本次迁移将 6 个 API 文件统一到标准的响应格式和异常处理规范,提升了代码一致性和可维护性。所有变更向后兼容,无需修改前端代码,可以安全部署。