# 项目相关 API 响应格式与异常处理标准化 **变更日期**: 2026-02-11 **变更类型**: 重构 (Refactoring) **影响范围**: `projects.py`, `project_resources.py`, `project_elements.py`, `project_element_tags.py` **Breaking Change**: 否 ## 背景 为了统一后端 API 的响应格式和异常处理机制,需要将项目相关的 4 个 API 文件迁移到标准格式。参考 `ai_conversations.py` 的实现规范,确保: 1. 查询参数支持 camelCase(使用 `alias` 参数) 2. 响应格式使用 `SuccessResponse` 包装 3. 异常处理统一使用 `app.core.exceptions` 中的自定义异常类 ## 变更内容 ### 1. 统一异常处理 #### 之前 (使用 HTTPException) ```python from fastapi import HTTPException, status raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="该项目下已存在同名角色" ) ``` #### 之后 (使用自定义异常) ```python from app.core.exceptions import NotFoundError, ValidationError, InternalServerError raise ValidationError("该项目下已存在同名角色") ``` ### 2. 查询参数支持 camelCase #### project_element_tags.py ```python # 之前 element_type: Optional[str] = None # 之后 element_type: Optional[str] = Query(None, alias="elementType", description="元素类型过滤") ``` ### 3. 异常映射规则 | 场景 | 之前 | 之后 | |------|------|------| | 资源不存在 | `HTTPException(404)` | `NotFoundError()` | | 参数验证失败 | `HTTPException(400)` | `ValidationError()` | | 权限不足 | `HTTPException(403)` | `PermissionError()` | | 服务器错误 | `HTTPException(500)` | `InternalServerError()` | | 唯一约束冲突 | `HTTPException(409)` | `ValidationError()` | ## 修改文件列表 ### 1. `server/app/api/v1/projects.py` - ✅ 添加自定义异常导入 - ✅ 响应格式已使用 `SuccessResponse`(无需修改) - ✅ 查询参数已支持 camelCase(无需修改) ### 2. `server/app/api/v1/project_resources.py` - ✅ 添加自定义异常导入 - ✅ 响应格式已使用 `SuccessResponse`(无需修改) - ✅ 查询参数已支持 camelCase(无需修改) ### 3. `server/app/api/v1/project_elements.py` - ✅ 移除 `HTTPException` 导入 - ✅ 添加自定义异常导入 - ✅ 替换角色创建异常:`HTTPException(409)` → `ValidationError()` - ✅ 替换场景创建异常:`HTTPException(409)` → `ValidationError()` - ✅ 替换道具创建异常:`HTTPException(409)` → `ValidationError()` ### 4. `server/app/api/v1/project_element_tags.py` - ✅ 移除 `HTTPException` 导入 - ✅ 添加自定义异常导入 (`NotFoundError`, `ValidationError`, `InternalServerError`) - ✅ 替换创建标签异常:`HTTPException(400)` → `ValidationError()`, `HTTPException(500)` → `InternalServerError()` - ✅ 替换获取标签异常:`HTTPException(500)` → `InternalServerError()` - ✅ 替换更新标签异常:`HTTPException(404)` → `NotFoundError()`, `HTTPException(500)` → `InternalServerError()` - ✅ 替换删除标签异常:`HTTPException(404)` → `NotFoundError()`, `HTTPException(500)` → `InternalServerError()` - ✅ 替换设置默认标签异常:`HTTPException(404)` → `NotFoundError()`, `HTTPException(500)` → `InternalServerError()` - ✅ 查询参数添加 camelCase 支持:`element_type` → `Query(None, alias="elementType")` ## 影响评估 ### 前端影响 - **无影响**: 响应格式保持一致(SuccessResponse 包装) - **无影响**: HTTP 状态码保持一致(自定义异常类已映射正确状态码) ### 后端影响 - **代码质量提升**: 异常处理更加统一和规范 - **可维护性提升**: 集中管理异常类型,便于后续扩展 - **日志记录改进**: 自定义异常类可以更好地集成日志系统 ## 测试建议 ### 1. 功能测试 - ✅ 创建角色/场景/道具时,验证唯一约束冲突返回 400(ValidationError) - ✅ 访问不存在的资源时,验证返回 404(NotFoundError) - ✅ 无权限操作时,验证返回 403(PermissionError) ### 2. 接口测试 ```bash # 测试角色创建(重复名称) curl -X POST "http://localhost:8000/api/v1/projects/{project_id}/characters" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{"name": "主角", "role_type": "protagonist"}' # 预期: HTTP 400, message: "该项目下已存在同名角色,请使用其他名称" ``` ### 3. 查询参数测试(camelCase) ```bash # 测试标签查询(使用 camelCase) curl "http://localhost:8000/api/v1/projects/{project_id}/element-tags?elementType=character" # 预期: 返回角色类型的标签列表 ``` ## 兼容性说明 - ✅ **向后兼容**: HTTP 状态码未改变 - ✅ **向后兼容**: 响应格式未改变(已使用 SuccessResponse) - ✅ **向后兼容**: 查询参数同时支持 snake_case 和 camelCase ## 后续改进 1. 考虑在全局异常处理器中统一记录异常日志 2. 为 `ValidationError` 增加结构化错误详情支持(如字段级错误) 3. 考虑为不同业务场景创建更具体的异常子类 ## 参考文档 - [API 设计规范](../../.claude/skills/jointo-tech-stack/references/api-design.md) - [后端开发规范](../../.claude/skills/jointo-tech-stack/references/backend.md) - [异常处理规范](../../server/app/core/exceptions.py) - [参考实现](../../server/app/api/v1/ai_conversations.py)