Files
junhong_cmp_fiber/AGENTS.md
huang 6e2dc325d7 新增钱包、换卡、标签系统的数据模型和规范
本次提交完成 add-wallet-transfer-tag-models 提案的实施和归档:

## 新增功能模块
- 钱包系统:用户/代理钱包管理,支持充值、扣款、退款、乐观锁防并发
- 换卡记录:物联卡更换历史追溯,包含套餐快照(JSONB)
- 标签系统:设备/IoT卡/号卡的统一标签管理
- 运营商渠道:四大运营商(CMCC/CUCC/CTCC/CBN)的渠道管理

## 数据库变更
- 新增 6 张表:tb_wallet, tb_wallet_transaction, tb_recharge_record, tb_card_replacement_record, tb_tag, tb_resource_tag
- 修改 2 张表:tb_carrier(新增渠道字段), tb_order(新增混合支付字段)
- 迁移版本:v6 → v7(执行时间 282.5ms)

## 代码变更
- 新增 8 个 Go 模型(符合统一规范:gorm.Model + BaseModel)
- 新增 40+ 个常量定义(含完整中文注释)
- 新增 7 个 Redis Key 生成函数
- 修复模型规范:移除重复字段,统一使用 gorm.Model 嵌入

## 文档变更
- 新增 3 个业务文档:数据模型设计、字段说明、迁移验证报告
- 更新 AGENTS.md:新增 Model 模型规范和常量注释规范
- 新增 4 个 OpenSpec 规范:wallet, carrier, card-replacement, tag
- 更新 1 个 OpenSpec 规范:iot-order(支持混合支付)

## 验证通过
-  LSP 诊断:所有模型和常量文件无错误
-  OpenSpec 验证:openspec validate --strict 通过
-  迁移执行:表结构创建成功,索引正确
-  提案归档:2026-01-13-add-wallet-transfer-tag-models

变更文件统计:29 个文件,新增 3682 行
2026-01-13 15:47:32 +08:00

206 lines
6.4 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.
<!-- OPENSPEC:START -->
# OpenSpec Instructions
These instructions are for AI assistants working in this project.
Always open `@/openspec/AGENTS.md` when the request:
- Mentions planning or proposals (words like proposal, spec, change, plan)
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
- Sounds ambiguous and you need the authoritative spec before coding
Use `@/openspec/AGENTS.md` to learn:
- How to create and apply change proposals
- Spec format and conventions
- Project structure and guidelines
Keep this managed block so 'openspec update' can refresh the instructions.
<!-- OPENSPEC:END -->
---
# junhong_cmp_fiber 项目开发规范
**重要提示**: 完整的开发规范和 OpenSpec 工作流详细说明请查看 `@/openspec/AGENTS.md`
## 语言要求
**必须遵守:**
- 永远用中文交互
- 注释必须使用中文
- 文档必须使用中文
- 日志消息必须使用中文
- 用户可见的错误消息必须使用中文
- 变量名、函数名、类型名必须使用英文(遵循 Go 命名规范)
- GIT提交的commit必须使用中文
## 技术栈
**必须严格遵守以下技术栈,禁止使用替代方案:**
- **HTTP 框架**: Fiber v2.x
- **ORM**: GORM v1.25.x
- **配置管理**: Viper
- **日志**: Zap + Lumberjack.v2
- **JSON 序列化**: sonic优先encoding/json必要时
- **验证**: Validator
- **任务队列**: Asynq v0.24.x
- **数据库**: PostgreSQL 14+
- **缓存**: Redis 6.0+
**禁止:**
- 直接使用 `database/sql`(必须通过 GORM
- 使用 `net/http` 替代 Fiber
- 使用 `encoding/json` 替代 sonic除非必要
## 架构分层
必须遵循以下分层架构:
```
Handler → Service → Store → Model
```
- **Handler**: 只处理 HTTP 请求/响应,不包含业务逻辑
- **Service**: 包含所有业务逻辑,支持跨模块调用
- **Store**: 统一管理所有数据访问,支持事务处理
- **Model**: 定义数据结构和 DTO
## 核心原则
### 错误处理
- 所有错误必须在 `pkg/errors/` 中定义
- 使用统一错误码系统
- Handler 层通过返回 `error` 传递给全局 ErrorHandler
### 响应格式
- 所有 API 响应使用 `pkg/response/` 的统一格式
- 格式: `{code, message, data, timestamp}`
### 常量管理
- 所有常量定义在 `pkg/constants/`
- Redis key 使用函数生成: `Redis{Module}{Purpose}Key(params...)`
- 格式: `{module}:{purpose}:{identifier}`
- 禁止硬编码字符串和 magic numbers
- **必须为所有常量添加中文注释**,参考 `pkg/constants/iot.go` 的注释风格
- 常量分组使用 `// ========` 分隔线和标题注释
- 每个常量值后必须添加行内注释说明含义
### Go 代码风格
- 使用 `gofmt` 格式化
- 遵循 [Effective Go](https://go.dev/doc/effective_go)
- 包名: 简短、小写、单数、无下划线
- 接口命名: 使用 `-er` 后缀Reader、Writer、Logger
- 缩写词: 全大写或全小写URL、ID、HTTP 或 url、id、http
## Model 模型规范
**必须遵守的模型结构:**
```go
// ModelName 模型名称模型
// 详细的业务说明2-3行
// 特殊说明(如果有)
type ModelName struct {
gorm.Model // 包含 ID、CreatedAt、UpdatedAt、DeletedAt
BaseModel `gorm:"embedded"` // 包含 Creator、Updater
Field1 string `gorm:"column:field1;type:varchar(50);not null;comment:字段1说明" json:"field1"`
// ... 其他字段
}
// TableName 指定表名
func (ModelName) TableName() string {
return "tb_model_name"
}
```
**关键要点:**
- ✅ **必须**嵌入 `gorm.Model``BaseModel`,不要手动定义 ID、CreatedAt、UpdatedAt、DeletedAt、Creator、Updater
- ✅ **必须**为模型添加中文注释,说明业务用途(参考 `internal/model/iot_card.go`
- ✅ **必须**在每个字段的 `comment` 标签中添加中文说明
- ✅ **必须**为导出的类型编写 godoc 格式的文档注释
- ✅ **必须**实现 `TableName()` 方法,表名使用 `tb_` 前缀
- ✅ 所有字段必须显式指定 `gorm:"column:field_name"` 标签
- ✅ 金额字段使用 `int64` 类型,单位为分
- ✅ 时间字段使用 `*time.Time`(可空)或 `time.Time`(必填)
- ✅ JSONB 字段需要实现 `driver.Valuer``sql.Scanner` 接口
## 数据库设计
**核心规则:**
- ❌ 禁止建立外键约束
- ❌ 禁止使用 GORM 关联关系标签foreignKey、hasMany、belongsTo
- ✅ 关联通过存储 ID 字段手动维护
- ✅ 关联数据在代码层面显式查询
**理由**: 灵活性、性能、可控性、分布式友好
## Go 惯用法 vs Java 风格
### ✅ Go 风格(推荐)
- 扁平化包结构(最多 2-3 层)
- 小而专注的接口1-3 个方法)
- 直接访问导出字段(不用 getter/setter
- 组合优于继承
- 显式错误返回和检查
- goroutines + channels不用线程池
### ❌ Java 风格(禁止)
- 过度抽象(不必要的接口、工厂)
- Getter/Setter 方法
- 深层继承层次
- 异常处理panic/recover
- 单例模式
- 类型前缀IService、AbstractBase、ServiceImpl
- Bean 风格
## 测试要求
- 核心业务逻辑Service 层)测试覆盖率 ≥ 90%
- 所有 API 端点必须有集成测试
- 使用 table-driven tests
- 单元测试 < 100ms集成测试 < 1s
## 性能要求
- API P95 响应时间 < 200ms
- API P99 响应时间 < 500ms
- 数据库查询 < 50ms
- 列表查询必须分页(默认 20最大 100
- 避免 N+1 查询,使用批量操作
## 文档要求
- 每个功能在 `docs/{feature-id}/` 创建总结文档
- 文档文件名和内容使用中文
- 同步更新 README.md
- 为导出的函数、类型编写文档注释
## 函数复杂度
- 函数长度 ≤ 100 行(核心逻辑建议 ≤ 50 行)
- `main()` 函数只做编排,不含具体实现
- 遵循单一职责原则
## 访问日志
- 所有 HTTP 请求记录到 `access.log`
- 记录完整的请求/响应(限制 50KB
- 包含: method, path, query, status, duration, request_id, ip, user_agent, user_id, bodies
- 使用 JSON 格式,配置自动轮转
## OpenSpec 工作流
创建提案前的检查清单:
1. ✅ 技术栈合规
2. ✅ 架构分层正确
3. ✅ 使用统一错误处理
4. ✅ 常量定义在 pkg/constants/
5. ✅ Go 惯用法(非 Java 风格)
6. ✅ 包含测试计划
7. ✅ 性能考虑
8. ✅ 文档更新计划
9. ✅ 中文优先
**详细规范和 OpenSpec 工作流请查看**: `@/openspec/AGENTS.md`