# API 标准化迁移 - Storyboards/Resources/Recharge 模块 **日期**: 2026-02-11 **类型**: 重构 **影响范围**: 后端 API **Breaking Changes**: ❌ 无(兼容性升级) ## 概述 将 `storyboards.py`、`storyboard_resources.py`、`storyboard_board.py`、`screenplays.py`、`resource_library.py`、`recharge.py` 等 6 个 API 文件迁移到统一的响应格式和异常处理规范,确保与项目整体架构一致。 ## 变更内容 ### 1. resource_library.py - 完整迁移 #### 响应格式迁移 - ❌ 旧格式:使用 `success_response()` 函数 - ✅ 新格式:使用 `SuccessResponse[T]` 泛型类 **变更前:** ```python 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) ``` **变更后:** ```python 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` **示例:** ```python page_size: int = Query(20, ge=1, le=100, alias="pageSize", description="每页数量") ``` #### 日志规范化 添加结构化日志记录: ```python logger.info( "API: 获取角色列表 | 用户: %s | 项目: %s", current_user.user_id, project_id ) ``` #### Schema 增强 新增 `ResourceLibraryListResponse` 统一分页响应: ```python 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 - 完整迁移 #### 响应格式迁移 - ❌ 旧格式:使用 `ApiResponse`、`success_response()`、`error_response()` - ✅ 新格式:使用 `SuccessResponse[T]` **变更前:** ```python 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) ``` **变更后:** ```python 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)` - ✅ 新方式:使用自定义异常类 **变更前:** ```python if order.user_id != current_user.user_id: return error_response(message="无权查看此订单", code=403) ``` **变更后:** ```python from app.core.exceptions import PermissionError if order.user_id != current_user.user_id: raise PermissionError("无权查看此订单") ``` #### 查询参数优化 将 Pydantic model 依赖注入改为独立的 Query 参数(更符合 FastAPI 规范): **变更前:** ```python @router.get("/orders") async def get_orders( query: Annotated[RechargeOrderQueryRequest, Depends()], ... ): payment_status=query.payment_status, page=query.page, page_size=query.page_size ``` **变更后:** ```python @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` **示例:** ```python 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(前端规范): ```python page_size: int = Query(20, alias="pageSize", description="每页数量") ``` 前端可以使用: - `?page_size=20` ✅ snake_case(后端兼容) - `?pageSize=20` ✅ camelCase(前端首选) ### 响应格式规范 所有 API 统一返回 `SuccessResponse[T]`: ```python { "success": true, "data": { ... }, "message": "操作成功", "timestamp": "2026-02-11T10:30:00Z" } ``` ## 兼容性 ### ✅ 向后兼容 - 查询参数同时支持 `snake_case` 和 `camelCase` - 响应格式结构保持一致(仅规范化字段命名) - 无 Breaking Changes ### 前端影响 - ✅ 无需修改前端代码(已使用 camelCase) - ✅ 响应格式保持一致 - ✅ 错误处理逻辑无变化(HTTP 状态码不变) ## 测试建议 ### 1. API 响应格式验证 ```bash # 资源库 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. 异常处理验证 ```bash # 测试权限异常(403) curl -H "Authorization: Bearer $TOKEN" \ "http://localhost:6170/api/v1/recharge/orders/{other_user_order_id}" # 预期响应: # { # "success": false, # "message": "无权查看此订单", # "timestamp": "..." # } ``` ### 3. 查询参数兼容性测试 ```bash # 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 设计规范](../../references/backend.md#api-设计规范) - [异常处理规范](../../references/backend.md#异常处理) - [日志规范](../../references/logging.md) - [参考实现](../../../server/app/api/v1/ai_conversations.py) ## 后续工作 - [ ] 监控生产环境日志,确认无异常 - [ ] 更新 API 文档(Swagger) - [ ] 通知前端团队(如有必要) - [ ] 考虑将旧的 `app.schemas.response` 标记为废弃(Deprecated) ## 总结 本次迁移将 6 个 API 文件统一到标准的响应格式和异常处理规范,提升了代码一致性和可维护性。所有变更向后兼容,无需修改前端代码,可以安全部署。