规范: 新增枚举与状态字段规范并修复代理充值状态描述错误
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
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 中文字段,防止前端映射出错
This commit is contained in:
250
docs/enum-status-standards.md
Normal file
250
docs/enum-status-standards.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# 枚举与状态字段规范
|
||||
|
||||
**背景**:系统历史上存在 int/string 枚举混用、description 与常量定义脱节、响应字段不统一等问题,导致前端映射错误、接口文档失真。本规范统一所有枚举相关写法。
|
||||
|
||||
---
|
||||
|
||||
## 1. 类型选择:int vs string
|
||||
|
||||
### 选择规则
|
||||
|
||||
| 场景 | 类型 | 理由 |
|
||||
|------|------|------|
|
||||
| **状态类**:表示生命周期阶段(待支付→已完成→已关闭) | `int` | 便于范围查询、数值比较、DB 索引优化 |
|
||||
| **布尔状态**:启用/禁用、激活/未激活 | `int` | 与全局常量统一,`0=禁用, 1=启用` |
|
||||
| **类型/方式类**:支付方式、订单类型、运营商、平台 | `string` | 语义更清晰,无需记忆数字含义 |
|
||||
| **标识符类**:平台类型(web/h5/all)、角色来源 | `string` | 约定字符串值,自文档化 |
|
||||
|
||||
### 判断依据
|
||||
|
||||
```
|
||||
这个字段表示"现在处于哪个阶段"? → int
|
||||
这个字段表示"它属于哪种类别/使用什么方式"? → string
|
||||
```
|
||||
|
||||
### ✅ 正确示例
|
||||
|
||||
```go
|
||||
// 状态类 → int
|
||||
Status int `json:"status"` // 充值状态:1=待支付, 2=已支付...
|
||||
PaymentStatus int `json:"payment_status"` // 订单支付状态
|
||||
|
||||
// 类型/方式类 → string
|
||||
PaymentMethod string `json:"payment_method"` // "wechat" | "offline"
|
||||
OrderType string `json:"order_type"` // "single_card" | "device"
|
||||
Platform string `json:"platform"` // "web" | "h5" | "all"
|
||||
```
|
||||
|
||||
### ❌ 错误示例
|
||||
|
||||
```go
|
||||
// ❌ 状态用 string(无法范围查询,数字对比失效)
|
||||
Status string `json:"status"` // "pending" | "completed"
|
||||
|
||||
// ❌ 支付方式用 int(前端必须维护不直观的数字映射)
|
||||
PaymentMethod int `json:"payment_method"` // 1=微信, 2=线下
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Int 状态值约定
|
||||
|
||||
### 2.1 通用禁用/启用
|
||||
|
||||
**必须使用全局常量,禁止自定义**:
|
||||
|
||||
```go
|
||||
// pkg/constants/constants.go
|
||||
StatusDisabled = 0 // 禁用
|
||||
StatusEnabled = 1 // 启用
|
||||
```
|
||||
|
||||
✅ 正确:
|
||||
|
||||
```go
|
||||
Status int `gorm:"comment:状态(0-禁用 1-启用);default:1"`
|
||||
```
|
||||
|
||||
❌ 禁止(与全局常量语义相反):
|
||||
|
||||
```go
|
||||
// ❌ 不可以用 1=启用 2=禁用 这种方式
|
||||
Status int `gorm:"comment:状态(1-启用 2-禁用)"`
|
||||
```
|
||||
|
||||
### 2.2 生命周期状态
|
||||
|
||||
从 **1** 开始递增(0 保留,避免与"未赋值/零值"混淆):
|
||||
|
||||
```go
|
||||
// 充值状态(标准示例)
|
||||
const (
|
||||
RechargeStatusPending = 1 // 待支付
|
||||
RechargeStatusPaid = 2 // 已支付
|
||||
RechargeStatusCompleted = 3 // 已完成
|
||||
RechargeStatusClosed = 4 // 已关闭
|
||||
RechargeStatusRefunded = 5 // 已退款
|
||||
)
|
||||
```
|
||||
|
||||
### 2.3 特殊值
|
||||
|
||||
- 跳跃值(如 `99`)仅用于明确需要人工干预的异常状态,必须加注释说明原因
|
||||
- 禁止在同一枚举中混用 0 起始和 1 起始
|
||||
|
||||
---
|
||||
|
||||
## 3. String 枚举值约定
|
||||
|
||||
- 全小写字母 + 下划线 `snake_case`(禁止驼峰、禁止大写)
|
||||
- 必须在 `pkg/constants/` 定义常量,禁止硬编码字符串
|
||||
- DTO 中必须加 `validate:"oneof=..."` 约束
|
||||
|
||||
```go
|
||||
// pkg/constants/constants.go
|
||||
const (
|
||||
PaymentMethodWechat = "wechat" // 微信支付
|
||||
PaymentMethodOffline = "offline" // 线下转账
|
||||
)
|
||||
|
||||
// DTO 中
|
||||
PaymentMethod string `json:"payment_method" validate:"required,oneof=wechat offline" description:"支付方式 (wechat:微信支付, offline:线下转账)"`
|
||||
```
|
||||
|
||||
❌ 禁止:
|
||||
|
||||
```go
|
||||
// ❌ 硬编码字符串
|
||||
if record.PaymentMethod == "wechat" { ... }
|
||||
|
||||
// ❌ 大写或驼峰
|
||||
const PaymentMethodWechat = "Wechat"
|
||||
const PaymentMethodWechat = "WECHAT"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Constants 是唯一真相来源
|
||||
|
||||
**DTO 的 description 枚举列表必须与 `pkg/constants/` 定义完全一致。**
|
||||
|
||||
### 操作规程
|
||||
|
||||
1. 先在 `pkg/constants/` 定义(或查找已有)枚举常量及注释
|
||||
2. 将常量的注释**原文抄写**到 DTO description
|
||||
|
||||
```go
|
||||
// 步骤1:constants.go 中定义
|
||||
const (
|
||||
RechargeStatusPending = 1 // 待支付
|
||||
RechargeStatusPaid = 2 // 已支付
|
||||
RechargeStatusCompleted = 3 // 已完成
|
||||
RechargeStatusClosed = 4 // 已关闭
|
||||
RechargeStatusRefunded = 5 // 已退款
|
||||
)
|
||||
|
||||
// 步骤2:DTO description 从上面抄写,格式统一
|
||||
Status int `json:"status" description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"`
|
||||
```
|
||||
|
||||
### 禁止行为
|
||||
|
||||
```go
|
||||
// ❌ description 中的枚举值与 constants 不一致(本次 bug 根因)
|
||||
// constants: RechargeStatusCompleted=3(已完成)
|
||||
// dto 写的: 3:已取消 ← 完全错误!
|
||||
Status int `json:"status" description:"状态 (1:待支付, 2:已完成, 3:已取消)"`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. description 格式标准
|
||||
|
||||
**统一格式**:`字段含义 (值1:中文含义1, 值2:中文含义2, ...)`
|
||||
|
||||
规则:
|
||||
- 必须用**中文圆括号外**、**英文括号内**
|
||||
- 值和含义之间用**冒号** `:`,不用等号 `=`
|
||||
- 多个值之间用**逗号加空格** `, `
|
||||
- 含义必须是**中文**,不可用英文
|
||||
|
||||
```go
|
||||
// ✅ 统一格式
|
||||
Status int `description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"`
|
||||
Platform string `description:"适用端口 (all:全部, web:Web后台, h5:H5端)"`
|
||||
UserType int `description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"`
|
||||
|
||||
// ❌ 格式混乱
|
||||
Status int `description:"状态 (0=禁用, 1=启用)"` // 用等号
|
||||
Status int `description:"0=禁用 1=启用"` // 无括号无逗号
|
||||
Status int `description:"状态:0待生效 1生效中 2已用完"` // 格式不统一
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Response DTO 的状态字段
|
||||
|
||||
**所有 Response DTO 中的 int 状态字段,必须同时提供对应的 `xxx_name` 文字字段。**
|
||||
|
||||
这是防止前端映射错误的关键措施。
|
||||
|
||||
```go
|
||||
// ✅ Response DTO 标准写法
|
||||
type AgentRechargeResponse struct {
|
||||
Status int `json:"status" description:"状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款)"`
|
||||
StatusName string `json:"status_name" description:"状态名称(中文)"`
|
||||
// ...
|
||||
}
|
||||
|
||||
// Service 层 toResponse 函数中赋值
|
||||
func statusName(status int) string {
|
||||
switch status {
|
||||
case constants.RechargeStatusPending:
|
||||
return "待支付"
|
||||
case constants.RechargeStatusPaid:
|
||||
return "已支付"
|
||||
case constants.RechargeStatusCompleted:
|
||||
return "已完成"
|
||||
case constants.RechargeStatusClosed:
|
||||
return "已关闭"
|
||||
case constants.RechargeStatusRefunded:
|
||||
return "已退款"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**字段命名约定**:
|
||||
- `status` → `status_name`
|
||||
- `payment_status` → `payment_status_name`
|
||||
- `commission_status` → `commission_status_name`
|
||||
|
||||
**例外**:Request DTO(查询过滤、创建请求)不需要 `_name` 字段。
|
||||
|
||||
---
|
||||
|
||||
## 7. Code Review 检查项
|
||||
|
||||
```
|
||||
□ int/string 类型选择是否符合规则?
|
||||
□ 禁/启用是否用了 0=禁用, 1=启用?(禁止 1=启用, 2=禁用)
|
||||
□ string 枚举常量是否在 pkg/constants/ 定义?
|
||||
□ dto description 是否从 constants 注释原文抄写?
|
||||
□ description 格式是否统一(冒号、逗号、括号)?
|
||||
□ Response DTO 是否同时有 status int 和 status_name string?
|
||||
□ 是否有遗漏的枚举值没有在 description 中列出?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 现存已知不一致(技术债,待修复)
|
||||
|
||||
| 文件 | 问题 | 正确值 |
|
||||
|------|------|--------|
|
||||
| `internal/model/shop_package_allocation.go` | `1-启用 2-禁用` | 应改为 `0-禁用 1-启用` |
|
||||
| `internal/model/system.go` | `1-启用 2-禁用` | 需确认是否改 DB |
|
||||
| `internal/model/dto/agent_recharge_dto.go` | description `2:已完成, 3:已取消` | 应为 `2:已支付, 3:已完成, 4:已关闭, 5:已退款` |
|
||||
| `internal/model/dto/asset_wallet_dto.go` | 只有 `status_text` 无 `status int` | 需补充 `status int` |
|
||||
|
||||
> ⚠️ 已有数据的状态起始值(如 `1-启用 2-禁用`)改变前必须做 DB 数据迁移,改动前先评估影响。
|
||||
Reference in New Issue
Block a user