All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m33s
主要改动: - 新增交互式环境配置脚本 (scripts/setup-env.sh) - 新增本地启动快捷脚本 (scripts/run-local.sh) - 新增环境变量模板文件 (.env.example) - 部署模式改版:使用嵌入式配置 + 环境变量覆盖 - 添加对象存储功能支持 - 改进 IoT 卡片导入任务 - 优化 OpenAPI 文档生成 - 删除旧的配置文件,改用嵌入式默认配置
3.3 KiB
3.3 KiB
Context
当前项目使用 github.com/swaggest/openapi-go/openapi3 库生成 OpenAPI 3.0.3 规范文档。路由注册通过 RouteSpec 结构体传递元数据,但目前只支持 Summary 字段作为接口的简短描述。
OpenAPI 规范的 Operation 对象包含两个描述字段:
summary: 简短摘要(通常一行)description: 详细说明,支持 CommonMark Markdown 语法
swaggest 库的 openapi3.Operation 结构体已包含 Description *string 字段,只需在代码中设置即可。
Goals / Non-Goals
Goals:
- 在
RouteSpec中新增Description字段 - 支持在接口文档中添加 Markdown 格式的详细说明
- 保持向后兼容,Description 为可选字段
- 更新 API 文档规范
Non-Goals:
- 不修改 DTO 字段的 description 标签处理逻辑
- 不修改现有路由注册代码(新字段可选)
- 不扩展其他 OpenAPI 字段(如 externalDocs、deprecated 等)
Decisions
决策 1: Description 字段类型
选择: 使用 string 类型
原因:
- 与
Summary字段保持一致 - 空字符串表示无描述,语义清晰
- 避免指针类型带来的 nil 检查复杂度
备选方案:
*string指针类型 - 增加使用复杂度,无实际收益
决策 2: 函数签名变更策略
选择: 不修改 AddOperation 函数签名,通过 RouteSpec.Description 传递
原因:
- 保持 API 稳定性
Register函数已封装了RouteSpec,只需从中提取 Description- 避免破坏性变更
备选方案:
- 修改
AddOperation增加 description 参数 - 需要修改所有调用点,不必要
决策 3: 空值处理
选择: 空字符串时不设置 OpenAPI 的 description 字段
原因:
- 生成更简洁的 YAML
- 与 swaggest 库的 omitempty 行为一致
- 保持现有生成文件格式不变
Risks / Trade-offs
[风险] Markdown 语法在不同工具中渲染差异 → 缓解: 建议使用 CommonMark 基础语法(标题、列表、表格、代码块),避免扩展语法
[风险] 过长的 Description 影响文档可读性 → 缓解: 在规范文档中建议控制长度,复杂说明可使用折叠或链接到外部文档
[权衡] 不修改函数签名 vs 显式参数 → 选择封装在 RouteSpec 中,牺牲一定的显式性换取稳定性
实现方案
文件变更清单
-
internal/routes/registry.go- RouteSpec 新增 Description 字段
-
pkg/openapi/generator.go- AddOperation: 设置 op.Description
- AddMultipartOperation: 设置 op.Description
-
docs/api-documentation-guide.md- 新增 Description 字段使用说明
- 补充 Markdown 语法示例
代码变更示例
// internal/routes/registry.go
type RouteSpec struct {
Summary string // 简短摘要
Description string // 详细说明,支持 Markdown
Input interface{}
Output interface{}
Tags []string
Auth bool
FileUploads []FileUploadField
}
// pkg/openapi/generator.go - AddOperation
func (g *Generator) AddOperation(...) {
op := openapi3.Operation{
Summary: &summary,
Tags: tags,
}
// 新增: 设置 Description
if description != "" {
op.Description = &description
}
// ...
}