- 将 admin 相关服务移动到 internal/service/admin 目录下 - 更新控制器中的服务导入路径引用 - 移除已合并的服务文件 - 添加统一工作约定文档 - 更新 API 接口定义的包路径
8.8 KiB
8.8 KiB
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)
- base(基础常规):
- 三层路由隔离(
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/toolsGo 包。 - 新增子功能三步:①
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的布局清单。
分层与调用规范(必须遵守)
- 调用链:
controller → service → dao → model(do);controller 不碰 dao。 - DTO/VO 边界:跨层出入参走
internal/model/dto与internal/model/vo,API 类型与 entity 不得越界。 - 数据库操作必须用 DO 对象(
internal/model/do),禁止g.Map;未赋值字段保持 nil 自动忽略:dao.Users.Ctx(ctx).Where(cols.Id, id).Data(do.User{Uid: uid}).Update() - 时间字段自动维护:
created_at/updated_at/deleted_at由 ORM 自动处理,禁止手动赋值;软删除用Delete(),禁止手写WhereNull(cols.DeletedAt)。 - 错误处理一律用 gerror(保留堆栈);响应统一走
internal/library/response。 - 生成代码(dao/do/entity)禁止手改,改表后跑
gf gen dao重新生成。 - 声明 ≥3 个相关变量时,用
var (...)块对齐。
常用命令
# 运行(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 ./...
上下文记忆(重要)
三层配合,保证「换个账号/换台机器也能无缝衔接」:
- 本文件(AGENTS.md):长期稳定的架构与规范。
docs/change-log/YYYY-MM-DD.md:每次对话的「请求 + 变更 + 决策」记录,随 git 提交。- 每次完成任务后,若
docs/change-log/已有当日文件则追加,否则新建; - 格式固定:
## 请求/## 变更(含文件清单)/## 决策与理由/## 待办与风险; - 助手开工前先读最近 1-2 篇,快速恢复上下文。
- 每次完成任务后,若
.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 中央规则)
与中央
xpcool.com/.workbuddy/memory/MEMORY.md保持一致;本项目变更流水在.workbuddy/memory/CHANGELOG.md。
- 中文注释:写/改代码时,在应有处(函数、复杂逻辑、配置项、非显然分支)加中文注释。
- 做记录:每次请求/变更/修复/文档动作,都在本项目
.workbuddy/memory/CHANGELOG.md顶部追加一条,格式YYYY-MM-DD | 类型 | 一句话摘要(类型:REQ/CHG/FIX/DOC/CFG/DEP)。 - 中文优先:与用户的思考、输出、交流,能中文尽量中文。