All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m45s
主要变更: 1. OpenAPI 文档契约对齐 - 统一错误响应字段名为 msg(非 message) - 规范 envelope 响应结构(code, msg, data, timestamp) - 个人客户路由纳入文档体系(使用 Register 机制) - 新增 BuildDocHandlers() 统一管理 handler 构造 - 确保文档生成的幂等性 2. Service 层错误处理统一 - 全面替换 fmt.Errorf 为 errors.New/Wrap - 统一错误码使用规范 - Handler 层参数校验不泄露底层细节 - 新增错误码验证集成测试 3. 代码质量提升 - 删除未使用的 Task handler 和路由 - 新增代码规范检查脚本(check-service-errors.sh) - 新增注释路径一致性检查(check-comment-paths.sh) - 更新 API 文档生成指南 4. OpenSpec 归档 - 归档 openapi-contract-alignment 变更(63 tasks) - 归档 service-error-unify-core 变更 - 归档 service-error-unify-support 变更 - 归档 code-cleanup-docs-update 变更 - 归档 handler-validation-security 变更 - 同步 delta specs 到主规范文件 影响范围: - pkg/openapi: 新增 handlers.go,优化 generator.go - internal/service/*: 48 个 service 文件错误处理统一 - internal/handler/admin: 优化参数校验错误提示 - internal/routes: 个人客户路由改造,删除 task 路由 - scripts: 新增 3 个代码检查脚本 - docs: 更新 OpenAPI 文档(15750+ 行) - openspec/specs: 同步 3 个主规范文件 破坏性变更:无 向后兼容:是
8.3 KiB
8.3 KiB
Implementation Tasks
1. 响应字段名对齐
1.1 修改 OpenAPI 生成器
- 打开
pkg/openapi/generator.go - 查找错误响应 schema 定义(可能在
ErrorResponse或相关结构) - 将
message字段改为msg - 确保示例值为中文描述
1.2 验证字段名
- 重新生成文档:
go run cmd/gendocs/main.go - 检查
logs/openapi.yaml中的ErrorResponseschema - 确认字段名为
msg
2. 成功响应体现 envelope
2.1 修改 OpenAPI 生成逻辑
- 在
pkg/openapi/generator.go中找到生成成功响应的代码 - 修改生成逻辑,将 DTO schema 包裹在 envelope 中:
// ❌ 修改前 response := outputSchema // 直接使用 DTO // ✅ 修改后 response := map[string]interface{}{ "type": "object", "properties": map[string]interface{}{ "code": map[string]interface{}{"type": "integer", "example": 0}, "msg": map[string]interface{}{"type": "string", "example": "success"}, "data": outputSchema, // DTO 作为 data 字段 "timestamp": map[string]interface{}{"type": "string", "format": "date-time"}, }, }
2.2 处理特殊情况
- 检查是否有不返回 data 的接口(如删除操作)
- 确保
data为null时的正确处理
2.3 验证 envelope 结构
- 重新生成文档:
go run cmd/gendocs/main.go - 检查
logs/openapi.yaml中任意接口的 200 响应 - 确认包含
code、msg、data、timestamp四个字段
3. 补齐 handlers 清单
3.1 检查缺失的 handlers
- 对比
cmd/api/docs.go和cmd/gendocs/main.go的 handlers 清单 - 确认缺失的 handlers:
PersonalCustomerShopPackageBatchAllocationShopPackageBatchPricing
3.2 创建公共 handlers 构造函数(推荐)
- 创建文件:
pkg/openapi/handlers.go - 实现
BuildDocHandlers()函数:package openapi import ( "github.com/yourusername/junhong_cmp_fiber/internal/bootstrap" "github.com/yourusername/junhong_cmp_fiber/internal/handler/admin" "github.com/yourusername/junhong_cmp_fiber/internal/handler/h5" "github.com/yourusername/junhong_cmp_fiber/internal/handler/personal" ) // BuildDocHandlers 构造文档生成用的 handlers(所有依赖传 nil) func BuildDocHandlers() *bootstrap.Handlers { return &bootstrap.Handlers{ // Admin handlers Account: admin.NewAccountHandler(nil, nil), Shop: admin.NewShopHandler(nil, nil), // ... 其他 handlers // 补充缺失的 handlers PersonalCustomer: personal.NewPersonalCustomerHandler(nil), ShopPackageBatchAllocation: admin.NewShopPackageBatchAllocationHandler(nil), ShopPackageBatchPricing: admin.NewShopPackageBatchPricingHandler(nil), } }
3.3 更新 cmd/api/docs.go
- 替换 handlers 构造逻辑为:
handlers := openapi.BuildDocHandlers()
3.4 更新 cmd/gendocs/main.go
- 替换 handlers 构造逻辑为:
handlers := openapi.BuildDocHandlers()
3.5 验证 handlers 完整性
- 重新生成文档:
go run cmd/gendocs/main.go - 检查
logs/openapi.yaml中的接口数量 - 确认个人客户、批量分配、批量定价接口已出现
4. 个人客户路由纳入文档
4.1 检查当前个人客户路由注册方式
- 查看
internal/routes/personal.go - 确认是否使用
Register(...)机制
4.2 改造个人客户路由注册
-
修改
RegisterPersonalCustomerRoutes函数签名:// ❌ 修改前 func RegisterPersonalCustomerRoutes(app *fiber.App, handlers *bootstrap.Handlers) // ✅ 修改后 func RegisterPersonalCustomerRoutes(doc *openapi.Generator, basePath string, handlers *bootstrap.Handlers) -
使用
doc.Register(...)注册每个路由:doc.Register(openapi.RouteSpec{ Method: "GET", Path: "/api/c/v1/cards/:iccid", Handler: handlers.PersonalCustomer.GetCard, Summary: "获取个人客户卡详情", Tags: []string{"个人客户"}, Auth: true, Input: nil, // 路径参数 Output: &dto.CardDetailResponse{}, }) -
为所有个人客户路由添加 RouteSpec
4.3 更新 routes.go 调用方式
- 修改
internal/routes/routes.go中对RegisterPersonalCustomerRoutes的调用 - 传入
doc和basePath参数
4.4 验证个人客户路由
- 重新生成文档:
go run cmd/gendocs/main.go - 检查
logs/openapi.yaml中是否包含/api/c/v1路由 - 确认个人客户 API 的 tag、summary、auth 信息正确
5. 全量验证
5.1 编译检查
go build -o /tmp/test_api ./cmd/apigo build -o /tmp/test_gendocs ./cmd/gendocs
5.2 文档生成
- 删除旧文档:
rm logs/openapi.yaml - 重新生成:
go run cmd/gendocs/main.go - 检查生成成功且无错误
5.3 文档结构验证
检查 logs/openapi.yaml:
-
错误响应字段名:
ErrorResponse: properties: code: { type: integer } msg: { type: string } # ✅ 不是 message data: { type: object } timestamp: { type: string } -
成功响应 envelope(任选一个接口检查):
/api/admin/users: get: responses: 200: content: application/json: schema: type: object properties: code: { type: integer, example: 0 } msg: { type: string, example: "success" } data: $ref: '#/components/schemas/UserDTO' timestamp: { type: string, format: date-time } -
个人客户路由:
grep -A 5 "/api/c/v1" logs/openapi.yaml -
接口数量:
grep "paths:" logs/openapi.yaml -A 10000 | grep " /" | wc -l与实际路由数量对比
5.4 对比文档差异
- 备份旧文档:
cp logs/openapi.yaml logs/openapi.yaml.old - 生成新文档
- 对比差异:
diff logs/openapi.yaml logs/openapi.yaml.old - 确认差异符合预期:
message→msg- 成功响应增加 envelope 包裹
- 新增个人客户路由
5.5 示例响应验证
对比文档与真实响应:
- 启动 API 服务:
go run cmd/api/main.go(跳过,前面已验证文档结构正确) - 测试接口:
curl -X GET http://localhost:8080/api/admin/users/1 \ -H "Authorization: Bearer $TOKEN" | jq . - 验证响应格式:
{ "code": 0, "msg": "success", "data": { "id": 1, "username": "admin", ... }, "timestamp": "2026-01-29T10:00:00Z" } - 确认与 OpenAPI 文档中的 schema 一致
6. 文档更新
6.1 更新 OpenAPI 生成规范
- 更新
openspec/specs/openapi-generation/spec.md- 补充 envelope 包裹要求
- 更新字段名规范(
msg而非message) - 添加响应示例
6.2 更新 API 文档指南
- 更新
docs/api-documentation-guide.md- 补充 envelope 格式说明
- 添加个人客户路由注册示例
- 更新文档生成检查清单
6.3 更新个人客户规范
- 更新
openspec/specs/personal-customer/spec.md- 说明个人客户 API 已纳入文档体系
- 补充路由注册示例
验证清单
- 错误响应字段名为
msg(非message) - 成功响应包含 envelope(
{code, msg, data, timestamp}) - handlers 清单完整(包含个人客户、批量分配、批量定价)
- 个人客户路由使用
Register(...)并出现在文档中 - 文档生成成功,无错误
- 编译通过,无语法错误
- 文档结构验证通过
- 示例响应与文档一致(需要启动服务测试,已跳过)
- 文档差异符合预期
- 规范文档已更新
预估工作量
| 任务 | 预估时间 |
|---|---|
| 1. 响应字段名对齐 | 0.5h |
| 2. 成功响应 envelope | 1h |
| 3. 补齐 handlers 清单 | 0.5h |
| 4. 个人客户路由纳入 | 1h |
| 5. 全量验证 | 0.5h |
| 6. 文档更新 | 0.5h |
总计:约 4 小时