activity-openapi-from-code
SKILL.md
活动 OpenAPI 文档(由代码生成)
核心原则
- 一切有据:每个 path、每个 query/form/json 字段、每个响应字段,都能在代码中找到定义或推导来源(含嵌入字段的父类型)。
- 不 Mock:不写虚构的
example值为主张;若代码无注释,说明含义应来自service层逻辑、命名、conf、常量或调用链,并注明推导依据(如internal/service/service.go:GetXxx)。 - 路径与网关一致:
paths的 key 必须是可与servers拼接的完整路径(以/开头)。客户端实际请求路径为:{servers 中选定项的 url}+{path key}(两段之间按 URL 规则拼接,避免重复或缺省斜杠)。参考实现:servers为- url: /时,paths写活动完整前缀,如/activity_v2/<domain>/<action>。
代码溯源顺序(按此顺序阅读)
| 步骤 | 文件/位置 | 提取内容 |
|---|---|---|
| 1 | <活动>/sale_model.go 或等价 *Model |
GetActId()、GetRouter() 的 Domain、SubRouters[].Action |
| 2 | SubRouters[].Handler 指向的 internal/route/*.go |
HTTP 方法、绑定类型 c.ShouldBind、成功/失败响应封装 |
| 3 | internal/store/req.go(及同包其它 req) |
form / json / uri 标签 → OpenAPI 属性名;binding 与嵌入的 actutil.CommonReq |
| 4 | internal/store/rsp.go 或 route 中 SuccessResponse 的变量类型 |
响应 result 的结构与 json 标签 |
| 5 | internal/service/*.go 中对应函数 |
summary/description 的补充语义(状态机、时间窗、错误分支、枚举含义) |
| 6 | internal/conf/conf.go |
活动在文档 info.description 中可写的 ActID、域名等客观配置 |
| 7 | 公共层 | app/activity/common/actutil/http_req.go(CommonReq)、http_rsp.go(统一响应外层) |
活动 HTTP 路由惯例:路径形如 /activity_v2/{Domain}/{action},其中 action 与 GetRouter() 里 SubRouters 的 Action 一致;若代码中另有常量或中间件改写路径,以框架注册结果为准(可检索 Domain / activity_v2 的注册处)。
OpenAPI 文件结构(对齐参考格式)
参考:app/activity/2026/europe/rus_my_ideal_ring/openapi.yaml。
openapi: 3.0.3
info:
title: <活动标识> API
version: 1.0.0
description: |
说明文档由哪些目录的代码推导;
活动 Domain、ActID、路由来源(如 sale_model.go -> GetRouter);
统一请求/响应约定( Content-Type 、成功/失败与 HTTP 状态码关系等)。
servers:
- url: /
description: Root path
paths:
/activity_v2/<domain>/<action>:
post:
tags: [<domain>]
summary: <简短中文>
description: |
多行业务说明 + 主要逻辑文件(精确到 `path:Func`)。
operationId: <camelCase,与 Handler 或 action 对应>
requestBody:
required: true
content:
application/x-www-form-urlencoded: # 若 route 使用 ShouldBind + form 标签
schema:
$ref: "#/components/schemas/<Xxx>Request"
responses:
"200":
description: 与代码中 actutil 封装一致的中文说明
content:
application/json:
schema:
$ref: "#/components/schemas/<Xxx>ResponseEnvelope"
tags:
- name: <domain>
description: <活动一句话说明>
components:
schemas:
ResponseEnvelopeBase:
# 与 actutil 统一响应一致:code / msg / result
CommonRequest:
# 与 actutil.CommonReq 的 form/binding 一致;required 仅根据 binding 必填项
<PerOperation>Request:
allOf:
- $ref: "#/components/schemas/CommonRequest"
- type: object
description: 定义于 `internal/store/...:<GoType>`
properties: ...
<PerOperation>Result:
type: object
description定义于 `internal/store/...:<GoType>`
properties: ...
<PerOperation>ResponseEnvelope:
allOf:
- $ref: "#/components/schemas/ResponseEnvelopeBase"
- type: object
properties:
result:
$ref: "#/components/schemas/<PerOperation>Result"
请求体 Content-Type
- 以 route 为准:
ShouldBind+form标签 →application/x-www-form-urlencoded;ShouldBindJSON→application/json。 - 同一活动混用时按接口分别声明,不得统一猜。
Go 类型到 OpenAPI 类型
int/int32/int64→integer(必要时format: int32/int64)。string/bool/float64→ 对应 JSON Schema 类型。[]T→array+items;指针与值类型在文档中按非指针列出字段即可(与 JSON 序列化一致)。- 嵌入
CommonReq的字段:在CommonRequest或allOf第一层体现,禁止遗漏。
description 写法要求
- 每个 schema、每个 property 应有中文说明,并尽量标注:含义、取值约束(binding、是否必填)、与业务的关系。
- 枚举类整数:必须在代码中出现(常量、
iota、配置 map、注释);列出字面量与符号名;禁止编造未在代码中出现的取值。 required数组:仅当 Go 侧binding:"required"或业务层强依赖且无默认、或 JSON 必输出且omitempty未省略时可写;与omitempty行为矛盾时以序列化结果为准并在 description 说明。
工作流检查清单
生成或修改后自检:
- 每个
paths条目均能在GetRouter+route中找到 Handler 与 Action。 - 每个 Request schema 字段与
form/json标签名一致(含下划线命名)。 - 每个 Response
result与SuccessResponse(c, result)的类型一致。 -
ResponseEnvelopeBase/CommonRequest与actutil当前实现一致(有变更则同步文档)。 -
info.description标明活动目录、Domain、ActID来源文件。 - 无凭空字段、无未在代码中出现的枚举;未覆盖的逻辑写「以代码为准」并指向文件而非敷衍描述。
反例(禁止)
- 为「好看」添加示例用户 ID、帖子 ID、或与代码不符的
example:。 - 未读
service就把复杂字段写成「字符串,随便填」。 paths只写/vote而省略/activity_v2/...(在与参考一致且servers.url为/时,应写完整路径)。- 假设全是
application/json请求而 route 实际为form。
可选:与代码生成器协作
若仓库内已有从 ApiFox 生成 route/service/store 的流程,OpenAPI 仍以当前 Go 源码为终审;发现生成代码与 OpenAPI 冲突时,改文档或改代码需与用户确认,默认以源码为准。