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.
 

4.6 KiB

API 响应字段 camelCase 规范化修复

变更信息

  • 日期:2026-02-06
  • 类型:Bug 修复 / API 规范统一
  • 影响范围:文件存储 API (file_storage.py)
  • Breaking Change:否(向前兼容,字段名修正)

问题描述

在对 server/app/api/v1 目录进行 API 响应字段检查时,发现 file_storage.py 中的两个端点直接返回了 snake_case 字段名,不符合项目 API 响应字段使用 camelCase 的规范。

不符合规范的端点

  1. GET /api/v1/file-storage/presigned-url - 返回 expires_in 而非 expiresIn
  2. POST /api/v1/file-storage/cleanup - 返回 deleted_count 而非 deletedCount

参考标准screenplays.py 等其他 API 文件均通过 Schema 层或手动构建 camelCase 字典返回响应。

解决方案

修改文件

  • server/app/api/v1/file_storage.py

详细改动

1. 预签名 URL 端点

修复前

@router.get("/presigned-url", response_model=dict, summary="获取预签名 URL")
async def get_presigned_url(...):
    url = await service.get_presigned_url(storage_path, expires)
    return {"url": url, "expires_in": expires}  # ❌ snake_case

修复后

@router.get("/presigned-url", response_model=dict, summary="获取预签名 URL")
async def get_presigned_url(...):
    url = await service.get_presigned_url(storage_path, expires)
    return {"url": url, "expiresIn": expires}  # ✅ camelCase

2. 文件清理端点

修复前

@router.post("/cleanup", response_model=dict, summary="清理无引用文件")
async def cleanup_unused_files(...):
    deleted_count = await service.cleanup_unused_files(days)
    return {"deleted_count": deleted_count, "message": f"成功清理 {deleted_count} 个文件"}  # ❌ snake_case

修复后

@router.post("/cleanup", response_model=dict, summary="清理无引用文件")
async def cleanup_unused_files(...):
    deleted_count = await service.cleanup_unused_files(days)
    return {"deletedCount": deleted_count, "message": f"成功清理 {deleted_count} 个文件"}  # ✅ camelCase

全面检查结果

检查范围server/app/api/v1 目录下所有 API 文件(23 个)

检查结果

  • screenplays.py - 通过 Schema 层返回,标准参考
  • folders.py - 手动构建字典,已使用 camelCase
  • projects.py - 手动构建字典,已使用 camelCase
  • users.py - 手动构建字典,已使用 camelCase
  • storyboards.py - 通过 Schema 层返回
  • ai_conversations.py - 已使用 camelCase 转换
  • recharge.py - 已使用 camelCase 转换
  • 其他 API 文件 - 均符合规范
  • file_storage.py - 已修复

API 响应示例

预签名 URL

修复前

{
  "code": 200,
  "data": {
    "url": "https://...",
    "expires_in": 3600
  }
}

修复后

{
  "code": 200,
  "data": {
    "url": "https://...",
    "expiresIn": 3600
  }
}

文件清理

修复前

{
  "code": 200,
  "data": {
    "deleted_count": 5,
    "message": "成功清理 5 个文件"
  }
}

修复后

{
  "code": 200,
  "data": {
    "deletedCount": 5,
    "message": "成功清理 5 个文件"
  }
}

相关文档

验证结果

代码检查

# 检查所有 API 文件中直接返回字典的 snake_case 字段
grep -rn "return.*{.*_.*:" server/app/api/v1/*.py

结果 仅剩 file_storage.py 的 2 处(已修复)

全面集成测试

docker exec jointo-server-app pytest tests/integration/test_storyboard_api.py \
  tests/integration/test_folder_api.py tests/integration/test_project_api.py -v --tb=short

结果 99 passed in 4.30s

测试覆盖

  • Storyboard API (28 个测试)
  • Folder API (27 个测试)
  • Project API (44 个测试)
  • 所有 API 响应字段正确使用 camelCase 格式

详细测试日志docs/server/test-results/2026-02-06-api-camelcase-integration-tests.txt (3734 行)

总结

修复完成

  • 修复 1 个 API 文件(file_storage.py
  • 修正 2 个端点的响应字段
  • 统一使用 camelCase 命名规范
  • 符合项目 API 规范要求

收益

  1. API 响应字段命名统一
  2. 符合前端 JavaScript/TypeScript 命名习惯
  3. 提升 API 一致性和可维护性
  4. 与其他 API 端点保持一致