--- 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级)" ```