Files
junhong_cmp_fiber/docs/api-documentation-guide.md
huang 573ef28237
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m32s
完善 API 文档生成规范:统一路由注册和 OpenAPI 文档自动生成
主要改进:
1. 新增 docs/api-documentation-guide.md 详细文档指南
2. 在 AGENTS.md 中添加路由注册规范章节
3. 更新 README.md 文档目录结构

路由注册改进:
- 统一使用 Register() 函数注册路由并自动生成文档
- 所有接口必须指定 RouteSpec(Summary, Tags, Input, Output, Auth)
- 修复 docs.go 和 gendocs/main.go 使用 RegisterRoutesWithDoc 统一注册

DTO 规范更新:
- shop_dto.go 和 shop_account_dto.go 补充完整的 description 标签
- 所有枚举字段必须列出可能值和中文说明

文档生成优化:
- admin-openapi.yaml 自动生成更新
- 健康检查和任务管理接口加入文档
- H5 认证接口完整文档化

规范文档管理:
- 添加规范文档管理流程说明
- 详细文档放在 docs/ 目录
- AGENTS.md 只保留核心规则和引导链接
2026-01-21 10:20:52 +08:00

390 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API 文档生成规范
**版本**: 1.0
**最后更新**: 2026-01-21
## 目录
- [核心原则](#核心原则)
- [路由注册规范](#路由注册规范)
- [DTO 规范](#dto-规范)
- [文档生成流程](#文档生成流程)
- [常见问题](#常见问题)
---
## 核心原则
### ✅ 强制要求
**所有 HTTP 接口必须使用统一的 `Register()` 函数注册,以确保自动加入 OpenAPI 文档生成。**
```go
// ✅ 正确:使用 Register() 函数
Register(router, doc, basePath, "POST", "/path", handler.Method, RouteSpec{
Summary: "操作说明",
Tags: []string{"分类"},
Input: new(model.RequestDTO),
Output: new(model.ResponseDTO),
Auth: true,
})
// ❌ 错误:直接注册(不会生成文档)
router.Post("/path", handler.Method)
```
### 为什么这样做?
1. **文档自动同步**:代码即文档,避免文档与实现脱节
2. **前后端协作**:生成标准 OpenAPI 规范,前端可直接导入
3. **API 测试**Swagger UI / Postman 可直接使用
4. **类型安全**:通过 DTO 结构体自动生成准确的字段定义
---
## 路由注册规范
### 1. 基本结构
所有路由注册必须在 `internal/routes/` 目录中完成:
```
internal/routes/
├── registry.go # Register() 函数定义
├── routes.go # 总入口
├── admin.go # Admin 域路由
├── h5.go # H5 域路由
├── account.go # 账号管理路由
├── role.go # 角色管理路由
└── ...
```
### 2. 注册函数签名
```go
func registerXxxRoutes(
api fiber.Router, // Fiber 路由组
h *admin.XxxHandler, // Handler 实例
doc *openapi.Generator, // 文档生成器(可能为 nil
basePath string, // 基础路径(如 "/api/admin"
) {
// 路由注册逻辑
}
```
### 3. RouteSpec 结构
```go
type RouteSpec struct {
Summary string // 操作摘要(中文,简短)
Input interface{} // 请求参数 DTO
Output interface{} // 响应结果 DTO
Tags []string // 分类标签(用于文档分组)
Auth bool // 是否需要认证
}
```
### 4. 完整示例
```go
func registerShopRoutes(router fiber.Router, handler *admin.ShopHandler, doc *openapi.Generator, basePath string) {
shops := router.Group("/shops")
groupPath := basePath + "/shops"
Register(shops, doc, groupPath, "GET", "", handler.List, RouteSpec{
Summary: "店铺列表",
Tags: []string{"店铺管理"},
Input: new(model.ShopListRequest),
Output: new(model.ShopPageResult),
Auth: true,
})
Register(shops, doc, groupPath, "POST", "", handler.Create, RouteSpec{
Summary: "创建店铺",
Tags: []string{"店铺管理"},
Input: new(model.CreateShopRequest),
Output: new(model.ShopResponse),
Auth: true,
})
Register(shops, doc, groupPath, "PUT", "/:id", handler.Update, RouteSpec{
Summary: "更新店铺",
Tags: []string{"店铺管理"},
Input: new(model.UpdateShopParams), // 组合参数(路径 + Body
Output: new(model.ShopResponse),
Auth: true,
})
Register(shops, doc, groupPath, "DELETE", "/:id", handler.Delete, RouteSpec{
Summary: "删除店铺",
Tags: []string{"店铺管理"},
Input: new(model.IDReq), // 仅路径参数
Output: nil,
Auth: true,
})
}
```
---
## DTO 规范
### 1. Description 标签(必须)
**所有字段必须使用 `description` 标签,禁止使用行内注释。**
```go
// ❌ 错误
type CreateShopRequest struct {
ShopName string `json:"shop_name" validate:"required,min=1,max=100"` // 店铺名称
}
// ✅ 正确
type CreateShopRequest struct {
ShopName string `json:"shop_name" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"店铺名称"`
}
```
### 2. 枚举字段规范
**必须在 `description` 中列出所有可能值(中文)。**
```go
type CreateShopRequest struct {
Status int `json:"status" validate:"required,oneof=0 1" required:"true" description:"状态 (0:禁用, 1:启用)"`
Level int `json:"level" validate:"required,min=1,max=7" required:"true" minimum:"1" maximum:"7" description:"店铺层级 (1-7级)"`
}
```
### 3. 验证标签与 OpenAPI 标签一致
| validate 标签 | OpenAPI 标签 | 说明 |
|--------------|--------------|------|
| `required` | `required:"true"` | 必填字段 |
| `min=N,max=M` | `minimum:"N" maximum:"M"` | 数值范围 |
| `min=N,max=M` (字符串) | `minLength:"N" maxLength:"M"` | 字符串长度 |
| `len=N` | `minLength:"N" maxLength:"N"` | 固定长度 |
| `oneof=A B C` | `description` 中说明 | 枚举值 |
### 4. 请求参数类型标签
```go
// Query 参数
type ListRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"`
}
// Path 参数
type IDReq struct {
ID uint `path:"id" description:"ID" required:"true"`
}
// Body 参数(默认)
type CreateRequest struct {
Name string `json:"name" validate:"required" required:"true" description:"名称"`
}
```
### 5. 组合参数(路径 + Body
对于 `PUT /:id` 类型的端点,需要创建组合参数 DTO
```go
// 定义在 internal/model/common.go
type UpdateShopParams struct {
IDReq // 路径参数
UpdateShopRequest // Body 参数
}
```
### 6. 分页响应规范
```go
type ShopPageResult struct {
Items []ShopResponse `json:"items" description:"店铺列表"`
Total int64 `json:"total" description:"总记录数"`
Page int `json:"page" description:"当前页码"`
Size int `json:"size" description:"每页数量"`
}
```
---
## 文档生成流程
### 1. 自动生成
```bash
# 方式1独立生成工具
go run cmd/gendocs/main.go
# 方式2启动 API 服务时自动生成
go run cmd/api/main.go
```
生成的文档位置:
- `docs/admin-openapi.yaml` - 独立生成
- `logs/openapi.yaml` - 运行时生成
### 2. 验证文档
```bash
# 1. 检查生成的路径数量
python3 -c "
import yaml
with open('docs/admin-openapi.yaml', 'r', encoding='utf-8') as f:
doc = yaml.safe_load(f)
paths = list(doc.get('paths', {}).keys())
print(f'总路径数: {len(paths)}')
for p in sorted(paths):
print(f' {p}')
"
# 2. 在 Swagger UI 中测试
# 访问 https://editor.swagger.io/
# 粘贴 docs/admin-openapi.yaml 内容
```
### 3. 更新文档生成器
如果新增了 Handler需要在 `cmd/gendocs/main.go` 中添加:
```go
// 3. 创建 Handler使用 nil 依赖,因为只需要路由结构)
newHandler := admin.NewXxxHandler(nil)
handlers := &bootstrap.Handlers{
// ... 其他 Handler
Xxx: newHandler, // 添加新 Handler
}
```
---
## 常见问题
### Q1: 为什么我的接口没有出现在文档中?
**检查清单**
1. ✅ 是否使用了 `Register()` 函数?
```go
// ❌ 错误
router.Post("/path", handler.Method)
// ✅ 正确
Register(router, doc, basePath, "POST", "/path", handler.Method, RouteSpec{...})
```
2. ✅ 路由注册函数是否接收了 `doc *openapi.Generator` 参数?
```go
func registerXxxRoutes(router fiber.Router, handler *admin.XxxHandler, doc *openapi.Generator, basePath string)
```
3. ✅ 是否在 `cmd/gendocs/main.go` 中创建了 Handler
```go
handlers := &bootstrap.Handlers{
Xxx: admin.NewXxxHandler(nil),
}
```
4. ✅ 是否调用了路由注册函数?
- 检查 `internal/routes/admin.go` 中是否调用了 `registerXxxRoutes()`
- 检查 `internal/routes/routes.go` 是否调用了 `RegisterAdminRoutes()`
### Q2: 文档生成时报错 "undefined path parameter"
**原因**:路径参数(如 `/:id`)的 DTO 缺少对应字段。
**解决方案**:创建组合参数 DTO
```go
// ❌ 错误:直接使用 Body DTO
Register(router, doc, basePath, "PUT", "/:id", handler.Update, RouteSpec{
Input: new(model.UpdateShopRequest), // 缺少 id 参数
})
// ✅ 正确:使用组合参数
type UpdateShopParams struct {
IDReq // 包含 id 参数
UpdateShopRequest // 包含 Body 参数
}
Register(router, doc, basePath, "PUT", "/:id", handler.Update, RouteSpec{
Input: new(model.UpdateShopParams),
})
```
### Q3: DTO 字段在文档中没有描述?
**检查**
1. ✅ 是否添加了 `description` 标签?
```go
ShopName string `json:"shop_name" description:"店铺名称"`
```
2. ✅ 是否使用了行内注释(不会被识别)?
```go
// ❌ 错误
ShopName string `json:"shop_name"` // 店铺名称
// ✅ 正确
ShopName string `json:"shop_name" description:"店铺名称"`
```
### Q4: 如何为新模块添加路由?
**步骤**
1. 创建路由文件 `internal/routes/xxx.go`
2. 定义注册函数:
```go
func registerXxxRoutes(api fiber.Router, h *admin.XxxHandler, doc *openapi.Generator, basePath string) {
// 使用 Register() 注册路由
}
```
3. 在 `internal/routes/admin.go` 中调用:
```go
if handlers.Xxx != nil {
registerXxxRoutes(authGroup, handlers.Xxx, doc, basePath)
}
```
4. 在 `cmd/gendocs/main.go` 中添加 Handler
5. 重新生成文档验证
### Q5: 如何调试文档生成?
```bash
# 1. 查看生成的 YAML 文件
cat docs/admin-openapi.yaml
# 2. 验证 YAML 格式
python3 -c "
import yaml
with open('docs/admin-openapi.yaml', 'r', encoding='utf-8') as f:
doc = yaml.safe_load(f)
print('YAML 格式正确')
"
# 3. 检查特定路径
python3 -c "
import yaml
with open('docs/admin-openapi.yaml', 'r', encoding='utf-8') as f:
doc = yaml.safe_load(f)
path = '/api/admin/shops'
if path in doc['paths']:
import json
print(json.dumps(doc['paths'][path], indent=2, ensure_ascii=False))
"
```
---
## 参考资料
- [OpenAPI 3.0 规范](https://swagger.io/specification/)
- [Swagger UI](https://swagger.io/tools/swagger-ui/)
- [项目 DTO 规范](../AGENTS.md#dto-规范重要)
- [已有实现示例](../internal/routes/account.go)