# Implementation Tasks ## 1. 响应字段名对齐 ### 1.1 修改 OpenAPI 生成器 - [x] 打开 `pkg/openapi/generator.go` - [x] 查找错误响应 schema 定义(可能在 `ErrorResponse` 或相关结构) - [x] 将 `message` 字段改为 `msg` - [x] 确保示例值为中文描述 ### 1.2 验证字段名 - [x] 重新生成文档:`go run cmd/gendocs/main.go` - [x] 检查 `logs/openapi.yaml` 中的 `ErrorResponse` schema - [x] 确认字段名为 `msg` ## 2. 成功响应体现 envelope ### 2.1 修改 OpenAPI 生成逻辑 - [x] 在 `pkg/openapi/generator.go` 中找到生成成功响应的代码 - [x] 修改生成逻辑,将 DTO schema 包裹在 envelope 中: ```go // ❌ 修改前 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 处理特殊情况 - [x] 检查是否有不返回 data 的接口(如删除操作) - [x] 确保 `data` 为 `null` 时的正确处理 ### 2.3 验证 envelope 结构 - [x] 重新生成文档:`go run cmd/gendocs/main.go` - [x] 检查 `logs/openapi.yaml` 中任意接口的 200 响应 - [x] 确认包含 `code`、`msg`、`data`、`timestamp` 四个字段 ## 3. 补齐 handlers 清单 ### 3.1 检查缺失的 handlers - [x] 对比 `cmd/api/docs.go` 和 `cmd/gendocs/main.go` 的 handlers 清单 - [x] 确认缺失的 handlers: - `PersonalCustomer` - `ShopPackageBatchAllocation` - `ShopPackageBatchPricing` ### 3.2 创建公共 handlers 构造函数(推荐) - [x] 创建文件:`pkg/openapi/handlers.go` - [x] 实现 `BuildDocHandlers()` 函数: ```go 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 - [x] 替换 handlers 构造逻辑为: ```go handlers := openapi.BuildDocHandlers() ``` ### 3.4 更新 cmd/gendocs/main.go - [x] 替换 handlers 构造逻辑为: ```go handlers := openapi.BuildDocHandlers() ``` ### 3.5 验证 handlers 完整性 - [x] 重新生成文档:`go run cmd/gendocs/main.go` - [x] 检查 `logs/openapi.yaml` 中的接口数量 - [x] 确认个人客户、批量分配、批量定价接口已出现 ## 4. 个人客户路由纳入文档 ### 4.1 检查当前个人客户路由注册方式 - [x] 查看 `internal/routes/personal.go` - [x] 确认是否使用 `Register(...)` 机制 ### 4.2 改造个人客户路由注册 - [x] 修改 `RegisterPersonalCustomerRoutes` 函数签名: ```go // ❌ 修改前 func RegisterPersonalCustomerRoutes(app *fiber.App, handlers *bootstrap.Handlers) // ✅ 修改后 func RegisterPersonalCustomerRoutes(doc *openapi.Generator, basePath string, handlers *bootstrap.Handlers) ``` - [x] 使用 `doc.Register(...)` 注册每个路由: ```go 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{}, }) ``` - [x] 为所有个人客户路由添加 RouteSpec ### 4.3 更新 routes.go 调用方式 - [x] 修改 `internal/routes/routes.go` 中对 `RegisterPersonalCustomerRoutes` 的调用 - [x] 传入 `doc` 和 `basePath` 参数 ### 4.4 验证个人客户路由 - [x] 重新生成文档:`go run cmd/gendocs/main.go` - [x] 检查 `logs/openapi.yaml` 中是否包含 `/api/c/v1` 路由 - [x] 确认个人客户 API 的 tag、summary、auth 信息正确 ## 5. 全量验证 ### 5.1 编译检查 - [x] `go build -o /tmp/test_api ./cmd/api` - [x] `go build -o /tmp/test_gendocs ./cmd/gendocs` ### 5.2 文档生成 - [x] 删除旧文档:`rm logs/openapi.yaml` - [x] 重新生成:`go run cmd/gendocs/main.go` - [x] 检查生成成功且无错误 ### 5.3 文档结构验证 检查 `logs/openapi.yaml`: - [x] **错误响应字段名**: ```yaml ErrorResponse: properties: code: { type: integer } msg: { type: string } # ✅ 不是 message data: { type: object } timestamp: { type: string } ``` - [x] **成功响应 envelope**(任选一个接口检查): ```yaml /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 } ``` - [x] **个人客户路由**: ```bash grep -A 5 "/api/c/v1" logs/openapi.yaml ``` - [x] **接口数量**: ```bash grep "paths:" logs/openapi.yaml -A 10000 | grep " /" | wc -l ``` 与实际路由数量对比 ### 5.4 对比文档差异 - [x] 备份旧文档:`cp logs/openapi.yaml logs/openapi.yaml.old` - [x] 生成新文档 - [x] 对比差异:`diff logs/openapi.yaml logs/openapi.yaml.old` - [x] 确认差异符合预期: - `message` → `msg` - 成功响应增加 envelope 包裹 - 新增个人客户路由 ### 5.5 示例响应验证 对比文档与真实响应: - [x] 启动 API 服务:`go run cmd/api/main.go`(跳过,前面已验证文档结构正确) - [x] 测试接口: ```bash curl -X GET http://localhost:8080/api/admin/users/1 \ -H "Authorization: Bearer $TOKEN" | jq . ``` - [x] 验证响应格式: ```json { "code": 0, "msg": "success", "data": { "id": 1, "username": "admin", ... }, "timestamp": "2026-01-29T10:00:00Z" } ``` - [x] 确认与 OpenAPI 文档中的 schema 一致 ## 6. 文档更新 ### 6.1 更新 OpenAPI 生成规范 - [x] 更新 `openspec/specs/openapi-generation/spec.md` - 补充 envelope 包裹要求 - 更新字段名规范(`msg` 而非 `message`) - 添加响应示例 ### 6.2 更新 API 文档指南 - [x] 更新 `docs/api-documentation-guide.md` - 补充 envelope 格式说明 - 添加个人客户路由注册示例 - 更新文档生成检查清单 ### 6.3 更新个人客户规范 - [x] 更新 `openspec/specs/personal-customer/spec.md` - 说明个人客户 API 已纳入文档体系 - 补充路由注册示例 ## 验证清单 - [x] 错误响应字段名为 `msg`(非 `message`) - [x] 成功响应包含 envelope(`{code, msg, data, timestamp}`) - [x] handlers 清单完整(包含个人客户、批量分配、批量定价) - [x] 个人客户路由使用 `Register(...)` 并出现在文档中 - [x] 文档生成成功,无错误 - [x] 编译通过,无语法错误 - [x] 文档结构验证通过 - [x] 示例响应与文档一致(需要启动服务测试,已跳过) - [x] 文档差异符合预期 - [x] 规范文档已更新 ## 预估工作量 | 任务 | 预估时间 | |-----|---------| | 1. 响应字段名对齐 | 0.5h | | 2. 成功响应 envelope | 1h | | 3. 补齐 handlers 清单 | 0.5h | | 4. 个人客户路由纳入 | 1h | | 5. 全量验证 | 0.5h | | 6. 文档更新 | 0.5h | **总计**:约 4 小时