Files
junhong_cmp_fiber/AGENTS.md
huang 5556b1028c feat(role): 新增平台角色管理功能增强
- 权限表增加 available_for_role_types 字段,支持标记权限可用角色类型
- 权限列表和权限树接口支持按 available_for_role_type 过滤
- 新增角色状态切换接口 PUT /api/admin/roles/:id/status
- 角色分配权限时验证权限的可用角色类型
- 完善数据库迁移脚本和单元测试
- 补充数据库迁移相关开发规范文档
2026-01-14 12:15:57 +08:00

385 lines
10 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 格式,配置自动轮转
## 数据库迁移
### 迁移工具
项目使用 **golang-migrate** 进行数据库迁移管理。
### 基本命令
```bash
# 查看当前迁移版本
make migrate-version
# 执行所有待迁移
make migrate-up
# 回滚上一次迁移
make migrate-down
# 创建新迁移文件
make migrate-create
# 然后输入迁移名称,例如: add_user_email
```
### 迁移文件规范
迁移文件位于 `migrations/` 目录:
```
migrations/
├── 000001_initial_schema.up.sql
├── 000001_initial_schema.down.sql
├── 000002_add_user_email.up.sql
├── 000002_add_user_email.down.sql
```
**命名规范**:
- 格式: `{序号}_{描述}.{up|down}.sql`
- 序号: 6位数字从 000001 开始
- 描述: 小写英文,用下划线分隔
- up: 应用迁移(向前)
- down: 回滚迁移(向后)
**编写规范**:
```sql
-- up.sql 示例
-- 添加字段时必须考虑向后兼容
ALTER TABLE tb_users
ADD COLUMN email VARCHAR(100);
-- 添加注释
COMMENT ON COLUMN tb_users.email IS '用户邮箱';
-- 为现有数据设置默认值(如果需要)
UPDATE tb_users SET email = '' WHERE email IS NULL;
-- down.sql 示例
ALTER TABLE tb_users
DROP COLUMN IF EXISTS email;
```
### 迁移执行流程(必须遵守)
当你创建迁移文件后,**必须**执行以下验证步骤:
1. **执行迁移**:
```bash
make migrate-up
```
2. **验证迁移状态**:
```bash
make migrate-version
# 确认版本号已更新且 dirty=false
```
3. **验证数据库结构**:
使用 PostgreSQL MCP 工具检查:
- 字段是否正确创建
- 类型是否符合预期
- 默认值是否正确
- 注释是否存在
4. **验证查询功能**:
编写临时脚本测试新字段的查询功能
5. **更新 Model**:
在 `internal/model/` 中添加对应字段
6. **清理测试数据**:
如果插入了测试数据,记得清理
### 迁移失败处理
如果迁移执行失败,数据库会被标记为 dirty 状态:
```bash
# 1. 检查错误原因
make migrate-version
# 如果显示 dirty=true说明迁移失败
# 2. 手动修复数据库状态
# 使用 PostgreSQL MCP 连接数据库
# 检查失败的迁移是否部分执行
# 手动清理或完成迁移
# 3. 清除 dirty 标记
UPDATE schema_migrations SET dirty = false WHERE version = {失败的版本号};
# 4. 修复迁移文件中的错误
# 5. 重新执行迁移
make migrate-up
```
### 使用 PostgreSQL MCP 访问数据库
项目配置了 PostgreSQL MCP 工具,用于直接访问和查询数据库。
**可用工具**:
1. **查看表结构**:
```
PostgresGetObjectDetails:
- schema_name: "public"
- object_name: "tb_permission"
- object_type: "table"
```
2. **列出所有表**:
```
PostgresListObjects:
- schema_name: "public"
- object_type: "table"
```
3. **执行查询**:
```
PostgresExecuteSql:
- sql: "SELECT * FROM tb_permission LIMIT 5"
```
**使用场景**:
- ✅ 验证迁移是否成功执行
- ✅ 检查字段类型、默认值、约束
- ✅ 查看现有数据
- ✅ 测试新增字段的查询功能
- ✅ 调试数据库问题
**注意事项**:
- ⚠️ MCP 工具只支持只读查询SELECT
- ⚠️ 不要直接修改数据,修改必须通过迁移文件
- ⚠️ 测试数据可以通过临时 Go 脚本插入
### 迁移最佳实践
1. **向后兼容**:
- 添加字段时使用 `DEFAULT` 或允许 NULL
- 删除字段前确保代码已不再使用
- 修改字段类型要考虑数据转换
2. **原子性**:
- 每个迁移文件只做一件事
- 复杂变更拆分成多个迁移
3. **可回滚**:
- down.sql 必须能完整回滚 up.sql 的所有变更
- 测试回滚功能: `make migrate-down && make migrate-up`
4. **注释完整**:
- 迁移文件顶部说明变更原因
- 关键 SQL 添加行内注释
- 数据库字段使用 COMMENT 添加说明
5. **测试数据**:
- 不要在迁移文件中插入业务数据
- 可以插入配置数据或枚举值
- 测试数据用临时脚本处理
## OpenSpec 工作流
创建提案前的检查清单:
1. ✅ 技术栈合规
2. ✅ 架构分层正确
3. ✅ 使用统一错误处理
4. ✅ 常量定义在 pkg/constants/
5. ✅ Go 惯用法(非 Java 风格)
6. ✅ 包含测试计划
7. ✅ 性能考虑
8. ✅ 文档更新计划
9. ✅ 中文优先
**详细规范和 OpenSpec 工作流请查看**: `@/openspec/AGENTS.md`