127 lines
8.8 KiB
Go
127 lines
8.8 KiB
Go
# AGENTS.md — 项目智能体说明书
|
||
|
||
> 本文件是给所有 AI 编程助手(CodeBuddy / WorkBuddy / Claude Code / Codex / Cursor 等)看的项目级上下文。
|
||
> 任何账号 clone 本仓库后,助手都应先读本文件与 `docs/change-log/` 下最近的记录,即可无缝衔接。
|
||
> 请保持本文件**长期稳定**:只写「架构、规范、约定」,不要写一次性事项。
|
||
|
||
## 项目简介
|
||
|
||
`service.xpcool.com`:个人多客户端(mini / h5 / app)后端服务,GoFrame v2 单体应用。
|
||
核心业务:用户认证(JWT)、内容、收藏、站内消息;后台管理(RBAC + 操作审计)。
|
||
|
||
## 技术栈
|
||
|
||
| 项 | 值 |
|
||
|---|---|
|
||
| 语言 | Go 1.23.0 |
|
||
| 框架 | github.com/gogf/gf/v2 v2.10.2 |
|
||
| 数据库 | MySQL(ORM 由 gf 生成 dao/do/entity) |
|
||
| 认证 | JWT(`internal/library/jwt`),admin 另有 `X-Permission` 校验 |
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
service.xpcool.com/
|
||
├── api/ # HTTP 契约与 Swagger 元数据
|
||
│ ├── user/v1/ # /api/v1 用户端 API(登录公开,其余走 UserAuth)
|
||
│ ├── admin/v1/ # /admin/v1 管理端 API(AdminAuth + X-Permission)
|
||
│ └── open/v1/ # /api/open/v1 开放接口(给前端调用,公开无鉴权)
|
||
│ └── tools/ # 工具子功能契约,每子功能一目录:tools/<name>/<name>.go
|
||
├── common/ # 公共可复用模块(不依赖 internal,可独立抽取成库)
|
||
│ └── tools/ # 工具模块,按子功能分包(见下文)
|
||
├── internal/
|
||
│ ├── cmd/ # 启动引导(路由分组注册在此)
|
||
│ ├── consts/ # 错误码与常量
|
||
│ ├── controller/ # API→service 适配层(不写业务;含 open/ 开放接口实现)
|
||
│ ├── service/ # 领域用例(业务逻辑直接写这里,不用 logic/)
|
||
│ ├── dao/ # gf gen dao 生成,禁止手改
|
||
│ ├── model/ # entity/ do/ dto/ vo/(entity、do 生成,禁止手改)
|
||
│ ├── middleware/ # 路由中间件
|
||
│ ├── library/ # jwt / page / response 等内部基础件
|
||
│ └── table/ # 表列名常量
|
||
├── manifest/ # config.dev/test/prod.yaml、sql 迁移
|
||
├── docs/change-log/ # 每次请求与变更的记录(重要!见「上下文记忆」)
|
||
└── utility/ # (预留)跨切面辅助
|
||
```
|
||
|
||
## 后台管理 API(api/admin/v1,按 base/system/admin 分组)
|
||
|
||
- **分组规则**:`api/admin/v1/{base,system,admin}/` 三个子包,路由前缀 `/admin/v1/{base,system,admin}`:
|
||
- **base**(基础常规):`/base/log/*`(服务器日志监控)
|
||
- **system**(系统管理):`/system/auth/*`(登录/信息/权限码)、`/system/menu/*`(菜单路由+CRUD)、`/system/role/*`(角色 CRUD)
|
||
- **admin**(后台管理):`/admin`(管理员账号 CRUD)
|
||
- 三层路由隔离(`internal/cmd/cmd.go`):
|
||
- **公开**(无鉴权):`POST /system/auth/login`
|
||
- **仅登录** `AdminAuthOnly`:`GET /system/auth/info`、`GET /system/auth/codes`、`GET /system/menu/routes`
|
||
- **接口级鉴权** `AdminAuth`:RBAC 管理、日志等
|
||
- **接口鉴权机制(重要)**:中间件按「请求方法+路径」从 `admin_menu`(type=2 行,path 存 `"METHOD /路径"`,`{id}` 为动态段)反查所需权限码,再校验用户是否拥有。**前端无需传 X-Permission**;未配置映射的接口一律拒绝。
|
||
- 权限码(permission)与路由分离:权限码保持 `system:admin:list` 等逻辑标识,路由路径按 base/system/admin 分组。
|
||
- 新增受保护接口三步:① `api/admin/v1/{分组}/<xxx>.go` 写 Req/Res;② `internal/controller/admin/<xxx>.go` 加方法;③ 在 `admin_menu` 加 type=2 行:`permission` 填权限码、`path` 填 `"METHOD /路径"` 映射。
|
||
- 迁移脚本:`003_schema_ext.sql`(admin_menu 加列)、`004_seed.sql`(初始账号/角色/菜单)、`005_menu_paths.sql`、`006_menu_paths_v2.sql`(按钮-接口路径映射,006 为分组重构后)。
|
||
|
||
## 开放接口(api/open/v1,前端调用)与命名规则
|
||
|
||
- **命名决策**:公共接口前缀用 **open**(不用 common)。理由:`common` 语义偏"内部公共代码",`open` 是开放接口业界惯例(支付宝 /open/api 等),更能表达"对外暴露、无鉴权"。同属"公开"语义的备选还有 `public`。
|
||
- 路由前缀 `/api/open/v1`,**公开、无鉴权**,实现于 `internal/controller/open`。
|
||
- **tools 子功能目录规则**:`api/open/v1/tools/<子功能名>/<子功能名>.go` 定义该子功能的 Req/Res 契约(目录名=包名=文件名三一致);控制器 `internal/controller/open/<子功能名>.go` 放对应方法(controller 统一 `package open`)。子功能变大后按端点/子领域在目录内**加文件**(如 ocr 目录下 `ocr.go` → `ocr.go + idcard.go + invoice.go`),不要堆在一个文件里。
|
||
- 当前端点:`GET/POST /tools/*`(uuid、md5、random、time、ip),底层复用 `common/tools` Go 包。
|
||
- **新增子功能三步**:① `api/open/v1/tools/<name>/<name>.go` 写 Req/Res(g.Meta 带 path/method);② `internal/controller/open/<name>.go` 加方法;③ 路由自动绑定,无需改 cmd.go。
|
||
|
||
## 公共工具模块 common/tools
|
||
|
||
- 规则:**不依赖 internal/**,只薄封装 GoFrame 内置组件;新工具优先复用内置(gmd5/gaes/gdes/guid/grand/gtime/gconv/gstr/gfile...),避免重复造轮子。
|
||
- 子功能:`md5`、`cryptox`(AES/DES)、`uuid`、`random`、`timex`、`convertx`、`strx`、`slicex`、`ip`、`filex`。
|
||
- 新增子功能:在 `common/tools/` 下建子包,更新 `common/tools/doc.go` 的布局清单。
|
||
|
||
## 分层与调用规范(必须遵守)
|
||
|
||
1. 调用链:`controller → service → dao → model(do)`;controller 不碰 dao。
|
||
2. DTO/VO 边界:跨层出入参走 `internal/model/dto` 与 `internal/model/vo`,API 类型与 entity 不得越界。
|
||
3. **数据库操作必须用 DO 对象**(`internal/model/do`),禁止 `g.Map`;未赋值字段保持 nil 自动忽略:
|
||
```go
|
||
dao.Users.Ctx(ctx).Where(cols.Id, id).Data(do.User{Uid: uid}).Update()
|
||
```
|
||
4. **时间字段自动维护**:`created_at/updated_at/deleted_at` 由 ORM 自动处理,禁止手动赋值;软删除用 `Delete()`,禁止手写 `WhereNull(cols.DeletedAt)`。
|
||
5. **错误处理一律用 gerror**(保留堆栈);响应统一走 `internal/library/response`。
|
||
6. 生成代码(dao/do/entity)**禁止手改**,改表后跑 `gf gen dao` 重新生成。
|
||
7. 声明 ≥3 个相关变量时,用 `var (...)` 块对齐。
|
||
|
||
## 常用命令
|
||
|
||
```bash
|
||
# 运行(dev)
|
||
GF_GCFG_FILE=config.dev.yaml DB_DSN="user:pass@tcp(127.0.0.1:3306)/db?loc=Local" JWT_SECRET=xxx go run main.go
|
||
# 数据库模型生成(唯一来源)
|
||
gf gen dao -p internal -g default -gt -c
|
||
# 构建 / 测试
|
||
go build ./...
|
||
go test ./...
|
||
```
|
||
|
||
## 上下文记忆(重要)
|
||
|
||
三层配合,保证「换个账号/换台机器也能无缝衔接」:
|
||
|
||
1. **本文件(AGENTS.md)**:长期稳定的架构与规范。
|
||
2. **`docs/change-log/YYYY-MM-DD.md`**:每次对话的「请求 + 变更 + 决策」记录,随 git 提交。
|
||
- 每次完成任务后,若 `docs/change-log/` 已有当日文件则**追加**,否则新建;
|
||
- 格式固定:`## 请求` / `## 变更`(含文件清单)/ `## 决策与理由` / `## 待办与风险`;
|
||
- 助手开工前先读最近 1-2 篇,快速恢复上下文。
|
||
3. **`.workbuddy/memory/`**:WorkBuddy 桌面端本机记忆(每日日志 + MEMORY.md),**已加入 .gitignore,不入库**,仅本机增强。
|
||
|
||
## 注意事项
|
||
|
||
- ⚠️ **gtime v2.10.2 格式化**:`Time.Format("Y-m-d H:i:s")` 是 PHP 风格;传 Go layout(`2006-01-02`)要用 `Time.Layout(...)`。工具包 `common/tools/timex` 已统一封装。
|
||
- ⚠️ **gf v2.10.2 包名与旧版不同**:AES/DES 在 `crypto/gaes`、`crypto/gdes`(无 gcrypto);UUID 在 `util/guid`(无 guuid);无 gslicer(用标准库 slices)。
|
||
- 配置文件按 `GF_GCFG_FILE` 切换;`manifest/config/config.yaml` 不入库。
|
||
- 生产环境强密码:`JWT_SECRET`、数据库口令。
|
||
- 变更涉及 API 时同步更新 `api/` 下的 Swagger 元数据注释。
|
||
|
||
## 统一工作约定(xpcool.com 中央规则)
|
||
|
||
> 与中央 `../workbuddy.xpcool.com/.workbuddy/memory/MEMORY.md` 保持一致;本项目变更流水在 `.workbuddy/memory/CHANGELOG.md`。
|
||
|
||
1. **中文注释**:写/改代码时,在应有处(函数、复杂逻辑、配置项、非显然分支)加中文注释。
|
||
2. **做记录**:每次请求/变更/修复/文档动作,都在本项目 `.workbuddy/memory/CHANGELOG.md` 顶部追加一条,格式 `YYYY-MM-DD | 类型 | 一句话摘要`(类型:REQ/CHG/FIX/DOC/CFG/DEP)。
|
||
3. **中文优先**:与用户的思考、输出、交流,能中文尽量中文。
|