All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m42s
新增物联网卡独立管理模块,支持单卡查询、批量导入和状态管理。主要变更包括: 功能特性: - 新增物联网卡 CRUD 接口(查询、分页列表、删除) - 支持 CSV/Excel 批量导入物联网卡 - 实现异步导入任务处理和进度跟踪 - 新增 ICCID 号码格式校验器(支持 Luhn 算法) - 新增 CSV 文件解析工具(支持编码检测和错误处理) 数据库变更: - 移除 iot_card 和 device 表的 owner_id/owner_type 字段 - 新增 iot_card_import_task 导入任务表 - 为导入任务添加运营商类型字段 测试覆盖: - 新增 IoT 卡 Store 层单元测试 - 新增 IoT 卡导入任务单元测试 - 新增 IoT 卡集成测试(包含导入流程测试) - 新增 CSV 工具和 ICCID 校验器测试 文档更新: - 更新 OpenAPI 文档(新增 7 个 IoT 卡接口) - 归档 OpenSpec 变更提案 - 更新 API 文档规范和生成器指南 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
4.6 KiB
4.6 KiB
name, description
| name | description |
|---|---|
| api-routing | API 路由注册规范。注册新 API 路由、添加新 Handler 时使用。包含 Register() 函数用法、RouteSpec 必填项、文档生成器更新等规范。 |
API 路由注册规范
所有 HTTP 接口必须使用统一的 Register() 函数注册,以自动加入 OpenAPI 文档生成。
触发条件
在以下情况下必须遵守本规范:
- 注册新的 API 路由
- 修改现有路由配置
- 添加新的 Handler(必须同步更新文档生成器!)
新增 Handler 检查清单(⚠️ 最容易遗漏)
新增 Handler 时,必须完成以下 4 个步骤,否则接口不会出现在 OpenAPI 文档中:
| 步骤 | 文件 | 操作 |
|---|---|---|
| 1️⃣ | internal/bootstrap/types.go |
添加 Handler 字段 |
| 2️⃣ | internal/bootstrap/handlers.go |
实例化 Handler |
| 3️⃣ | internal/routes/admin.go |
调用路由注册函数 |
| 4️⃣ | cmd/api/docs.go + cmd/gendocs/main.go |
添加到文档生成器 |
步骤 4 详解(最常遗漏!)
// cmd/api/docs.go 和 cmd/gendocs/main.go 都要改!
handlers := &bootstrap.Handlers{
// ... 现有 Handler
IotCard: admin.NewIotCardHandler(nil), // 添加
IotCardImport: admin.NewIotCardImportHandler(nil), // 添加
}
核心规则
必须使用 Register() 函数
// ✅ 正确
Register(router, doc, basePath, "POST", "/shops", handler.Create, RouteSpec{
Summary: "创建店铺",
Tags: []string{"店铺管理"},
Input: new(model.CreateShopRequest),
Output: new(model.ShopResponse),
Auth: true,
})
// ❌ 错误:直接注册不会生成文档
router.Post("/shops", handler.Create)
RouteSpec 必填项
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
Summary |
string | 操作说明(中文,简短) | "创建店铺" |
Tags |
[]string | 分类标签(用于文档分组) | []string{"店铺管理"} |
Input |
interface{} | 请求 DTO(nil 表示无参数) |
new(model.CreateShopRequest) |
Output |
interface{} | 响应 DTO(nil 表示无返回) |
new(model.ShopResponse) |
Auth |
bool | 是否需要认证 | true |
常见路由模式
CRUD 路由组
// 列表查询
Register(router, doc, basePath, "GET", "/shops", handler.List, RouteSpec{
Summary: "获取店铺列表",
Tags: []string{"店铺管理"},
Input: new(model.ListShopRequest),
Output: new(model.ShopListResponse),
Auth: true,
})
// 详情查询
Register(router, doc, basePath, "GET", "/shops/:id", handler.Get, RouteSpec{
Summary: "获取店铺详情",
Tags: []string{"店铺管理"},
Input: new(model.IDReq),
Output: new(model.ShopResponse),
Auth: true,
})
// 创建
Register(router, doc, basePath, "POST", "/shops", handler.Create, RouteSpec{
Summary: "创建店铺",
Tags: []string{"店铺管理"},
Input: new(model.CreateShopRequest),
Output: new(model.ShopResponse),
Auth: true,
})
// 更新
Register(router, doc, basePath, "PUT", "/shops/:id", handler.Update, RouteSpec{
Summary: "更新店铺",
Tags: []string{"店铺管理"},
Input: new(model.UpdateShopRequest),
Output: new(model.ShopResponse),
Auth: true,
})
// 删除
Register(router, doc, basePath, "DELETE", "/shops/:id", handler.Delete, RouteSpec{
Summary: "删除店铺",
Tags: []string{"店铺管理"},
Input: new(model.IDReq),
Output: nil,
Auth: true,
})
无认证路由
// 公开接口(如健康检查)
Register(router, doc, basePath, "GET", "/health", handler.Health, RouteSpec{
Summary: "健康检查",
Tags: []string{"系统"},
Input: nil,
Output: new(model.HealthResponse),
Auth: false,
})
AI 助手检查清单
注册路由时
- ✅ 是否使用
Register()函数而非直接注册 - ✅
Summary是否使用中文简短描述 - ✅
Tags是否正确分组 - ✅
Input和Output是否指向正确的 DTO - ✅
Auth是否根据业务需求正确设置
新增 Handler 时(⚠️ 必查)
- ✅
internal/bootstrap/types.go添加了 Handler 字段 - ✅
internal/bootstrap/handlers.go实例化了 Handler - ✅
internal/routes/admin.go调用了路由注册函数 - ✅
cmd/api/docs.go添加了 Handler - ✅
cmd/gendocs/main.go添加了 Handler - ✅ 运行
go run cmd/gendocs/main.go验证文档生成 - ✅ 运行
grep "接口路径" docs/admin-openapi.yaml确认接口存在
完整指南: 参见 docs/api-documentation-guide.md