Files
junhong_cmp_fiber/.claude/skills/dto-standards/SKILL.md
huang e9ff14df0e
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
规范: 新增枚举与状态字段规范并修复代理充值状态描述错误
- 新增 docs/enum-status-standards.md:完整的枚举/状态规范,涵盖 int vs string 选择、起始值约定、description 格式统一、constants 唯一真相来源、Response DTO 必须提供 status_name
- 更新 dto-standards SKILL.md:加入枚举规范要点,AI 写 DTO 时自动触发
- 更新 AGENTS.md:常量管理章节和 Code Review 检查清单各加入枚举检查项
- 修复 agent_recharge_dto.go:description 从错误的 3 个状态改为正确的 5 个状态(原 3:已取消 实为 3:已完成)
- 修复 agent_recharge service:toResponse 补充 StatusName 中文字段,防止前端映射出错
2026-04-11 11:25:58 +08:00

247 lines
7.9 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.
---
name: dto-standards
description: DTO 数据传输对象规范。创建或修改 DTO 文件、请求/响应结构时使用。包含 description 标签、枚举字段、验证标签等规范。
---
# DTO 规范
**所有 DTO 文件必须遵循以下规范,这是 API 文档生成的基础。**
## 触发条件
在以下情况下必须遵守本规范:
- 创建或修改 `internal/model/` 下的请求/响应 DTO
- 创建 `XXXRequest``XXXResponse``XXXReq``XXXResp` 结构体
- 添加或修改 API 接口的输入输出参数
---
## 必须项MUST
### 1. Description 标签规范
**所有字段必须使用 `description` 标签,禁止使用行内注释**
**错误**
```go
type CreateUserRequest struct {
Username string `json:"username"` // 用户名
Status int `json:"status"` // 状态
}
```
**正确**
```go
type CreateUserRequest struct {
Username string `json:"username" description:"用户名"`
Status int `json:"status" description:"状态 (0:禁用, 1:启用)"`
}
```
### 2. 枚举字段int vs string 选择
**必须按以下规则选择类型,禁止混用:**
| 场景 | 类型 | 示例 |
|------|------|------|
| 状态类(生命周期阶段) | `int` | 待支付→已完成→已关闭 |
| 布尔状态(启用/禁用) | `int` | `0=禁用, 1=启用` |
| 类型/方式类(种类) | `string` | `"wechat"`, `"single_card"` |
| 平台/标识符类 | `string` | `"web"`, `"h5"`, `"all"` |
```go
// ✅ 状态 → int
Status int `json:"status"`
PaymentStatus int `json:"payment_status"`
// ✅ 类型/方式 → string
PaymentMethod string `json:"payment_method" validate:"required,oneof=wechat offline"`
OrderType string `json:"order_type" validate:"required,oneof=single_card device"`
```
### 3. Int 状态值约定
#### 3.1 通用禁用/启用
**必须用全局常量,禁止自定义(尤其禁止 1=启用 2=禁用 这种反向写法)**
```go
// pkg/constants/constants.go 已定义,直接使用
StatusDisabled = 0 // 禁用
StatusEnabled = 1 // 启用
```
✅ 正确:`description:"状态 (0:禁用, 1:启用)"`
❌ 禁止:`description:"状态 (1:启用, 2:禁用)"`
#### 3.2 生命周期状态
**1** 开始递增0 不使用(避免与 Go 零值混淆):
```go
const (
RechargeStatusPending = 1 // 待支付
RechargeStatusPaid = 2 // 已支付
RechargeStatusCompleted = 3 // 已完成
RechargeStatusClosed = 4 // 已关闭
)
```
### 4. 枚举列表必须从 constants 原文抄写
**DTO description 的枚举列表必须与 `pkg/constants/` 定义完全一致,不可凭记忆填写。**
操作步骤:
1. 先查/定义 `pkg/constants/` 中的枚举常量
2. 将常量注释**原文抄写**到 description
```go
// constants.go 中:
RechargeStatusPending = 1 // 待支付
RechargeStatusPaid = 2 // 已支付
RechargeStatusCompleted = 3 // 已完成
RechargeStatusClosed = 4 // 已关闭
RechargeStatusRefunded = 5 // 已退款
// DTO description 从上面抄:
Status int `json:"status" description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"`
```
❌ 禁止description 与 constants 不一致,是历史 bug 的根因):
```go
// constants 说 3=已完成description 却写 3:已取消
Status int `json:"status" description:"状态 (1:待支付, 2:已完成, 3:已取消)"`
```
### 5. description 格式标准
**统一格式**`字段含义 (值1:中文含义1, 值2:中文含义2)`
- 值与含义之间用**冒号** `:`(禁止用等号 `=`
- 多个值之间用**逗号加空格** `, `
- 含义必须是**中文**
```go
// ✅ 统一格式
Status int `description:"状态 (1:待支付, 2:已支付, 3:已完成)"`
Platform string `description:"适用端口 (all:全部, web:Web后台, h5:H5端)"`
// ❌ 格式混乱
Status int `description:"状态 (0=禁用, 1=启用)"` // 用等号
Status int `description:"0=禁用 1=启用"` // 无括号无逗号
```
### 6. Response DTO 的状态字段必须同时返回 int 和 text
**所有 Response DTO 中的 int 状态字段,必须同时提供对应的 `_name` 文字字段。**
原因:防止前端维护映射表出错(历史上已有因此产生 bug 的案例)。
```go
// ✅ Response DTO 标准写法
type XxxResponse struct {
Status int `json:"status" description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"`
StatusName string `json:"status_name" description:"状态名称(中文)"`
}
// toResponse 函数中赋值
func rechargeStatusName(status int) string {
switch status {
case constants.RechargeStatusPending:
return "待支付"
case constants.RechargeStatusCompleted:
return "已完成"
// ...
default:
return "未知"
}
}
```
字段命名约定:`status``status_name``payment_status``payment_status_name`
**例外**Request DTO查询过滤、创建请求不需要 `_name` 字段。
### 7. 验证标签与 OpenAPI 标签一致
```go
Username string `json:"username" validate:"required,min=3,max=50" required:"true" minLength:"3" maxLength:"50" description:"用户名"`
```
| validate 标签 | OpenAPI 标签 |
|--------------|--------------|
| `required` | `required:"true"` |
| `min=N,max=M`(数值) | `minimum:"N" maximum:"M"` |
| `min=N,max=M`(字符串) | `minLength:"N" maxLength:"M"` |
| `oneof=A B C` | description 中说明枚举值 |
### 8. 请求参数类型标签
```go
// Query 参数
type ListRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"`
Status *int `json:"status" query:"status" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭)"`
}
// Path 参数
type IDReq struct {
ID uint `path:"id" description:"ID" required:"true"`
}
```
### 9. 响应 DTO 完整性
```go
type AccountResponse struct {
ID uint `json:"id" description:"账号ID"`
Username string `json:"username" description:"用户名"`
UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"`
Status int `json:"status" description:"状态 (0:禁用, 1:启用)"`
StatusName string `json:"status_name" description:"状态名称(中文)"`
CreatedAt string `json:"created_at" description:"创建时间"`
UpdatedAt string `json:"updated_at" description:"更新时间"`
}
```
---
## AI 助手必须执行的检查
**在创建或修改任何 DTO 文件后,必须执行以下检查:**
1. ✅ 所有字段有 `description` 标签(无行内注释)
2. ✅ 枚举类型选择正确(状态用 int类型/方式用 string
3. ✅ 禁用/启用使用 `0=禁用, 1=启用`(禁止 1=启用 2=禁用)
4. ✅ description 枚举列表已从 `pkg/constants/` 原文抄写,无遗漏
5. ✅ description 格式统一(冒号 `:`,括号,逗号)
6. ✅ Response DTO 有 `_name` 伴生字段
7. ✅ validate 标签与 OpenAPI 标签一致
8. ✅ 重新生成 OpenAPI 文档验证:`go run cmd/gendocs/main.go`
**完整枚举规范**: 参见 [`docs/enum-status-standards.md`](../../docs/enum-status-standards.md)
---
## 常见枚举字段标准值
```go
// 用户类型(从 constants.UserType* 抄)
description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"
// 通用启用/禁用(从 constants.StatusEnabled/Disabled 抄)
description:"状态 (0:禁用, 1:启用)"
// 充值状态(从 constants.RechargeStatus* 抄)
description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"
// 权限类型
description:"权限类型 (1:菜单, 2:按钮)"
// 适用端口
description:"适用端口 (all:全部, web:Web后台, h5:H5端)"
// 店铺层级
description:"店铺层级 (1-7级)"
```