一个 monorepo 风格的小型模块化单体 Go 项目骨架,面向快速业务开发:Gin + Gorm + SQLite/PostgreSQL + Redis + JWT + RBAC + 定时任务 + 双 Vue 前端嵌入。
当前稳定基线为 v0.5.0。项目开发约定、功能边界、SDK 入口、运行方式和测试模式见 .skills/mono-rbac-development。
- Go + Gin + Gorm
- SQLite / PostgreSQL
- Redis
- JWT + Redis Session
- Vue 3 + Vite,分为
client和admin两个前端项目 - Make + Python 项目编排(Node/npm 仅用于两个 Vue 前端)
- Docker Compose
cmd/api/ API、worker、migrate 启动入口,使用 -mode=api|worker|migrate 切换运行模式
cmd/manual/ 手工任务入口,初始化 DB、Redis、service 和中间件但不启动 HTTP
internal/app/ API 应用组装、路由和静态资源挂载
internal/bootstrap/ 自动迁移和默认数据初始化
internal/config/ app.yaml、环境覆盖、本地配置和统一配置键覆盖
internal/infra/ DB、Redis、日志基础设施
internal/middleware/ JWT 鉴权和 RBAC 中间件
internal/modules/ auth、user、rbac、monitor 业务模块
internal/pkg/ 响应、错误、密码、Redis 锁等公共工具
internal/tasks/ 定时任务注册和调度
internal/pkg/util/ 跨模块通用工具和工具依赖示例
frontend/client/ 客户端 Vue 前端,挂载到 /
frontend/admin/ 后台 Vue 前端,挂载到 /admin
deploy/ Dockerfile、docker-compose、Nginx 示例
docs/ API、RBAC、任务说明
scripts/ 本地开发脚本
.skills/ 面向 Codex 的项目开发 Skill 与参考资料
项目采用模块化单体的依赖组装方式:业务代码不要使用全局 service locator,也不要在模块内部重新调用 config.Load()。统一在 internal/app 中创建 repo、service、handler,再通过构造函数把依赖传入具体模块。
config.Config 由启动入口加载后传入 app.NewContainerWithConfig,需要读取配置的 service 应在构造函数中接收 config.Config 并保存为结构体字段:
type Service struct {
cfg config.Config
}
func NewService(cfg config.Config) *Service {
return &Service{cfg: cfg}
}访问其他 service 也通过构造函数注入,例如 user.Service 需要清理 RBAC 权限缓存时接收 *rbac.Service:
type Service struct {
rbacService *rbac.Service
}
func NewService(rbacService *rbac.Service) *Service {
return &Service{rbacService: rbacService}
}新增跨模块依赖时,通常需要同步修改:
- 当前 service 结构体字段。
- 当前 service 的
NewService构造函数参数。 internal/app/app.go中的依赖创建和传入顺序。
路由和中间件层从 Container 读取配置和 service,例如 container.Config、container.AuthService、container.RBACService。避免 service 之间形成双向依赖;如果出现循环依赖,优先把共用能力下沉到 repo 或 internal/pkg。
- 默认可直接使用 SQLite 和 Redis;如需 PostgreSQL,可通过
datasource.driver=postgres切换。 - 按需复制本地私人配置:
Copy-Item app-local.example.yaml app-local.yaml- 启动 API:
make run-api ARGS="-env=local"- 启动 worker:
make run-worker- 单独执行迁移和种子数据:
make migrate- 运行手工任务入口,不启动 HTTP 服务:
make manual默认手工入口会启动一个单体 agent 循环,用固定的 gpt-5.4-mini 和本地 OpenAI 兼容服务执行项目需求扩写模拟:
npm run manual- 指定配置文件、覆盖环境或单项配置:
go run ./cmd/api -f app.yaml -env=local --server.addr=:9090访问地址:
- 客户端:
http://localhost:8081/#/ - 后台:
http://localhost:8081/admin#/
配置读取顺序:
- 代码默认值。
- 主配置文件,默认
app.yaml,也可通过-f指定。 - 根据
profiles.active尝试加载app-<profile>.yaml和env-<profile>.yaml,例如local会尝试加载app-local.yaml和env-local.yaml。 -env启动参数或--profiles.active=<profile>覆盖 active profile,并影响环境覆盖文件选择。- 命令行统一配置键覆盖最终值,例如
--server.addr=:9090。
核心配置键不在 README 中完整枚举,避免文档过长;以 app.yaml、app-*.yaml、env-*.yaml 和 internal/config/config.go 为准。
配置文件采用层级 YAML,键名用 kebab-case;命令行覆盖使用同一套层级键,格式为 --配置键=值。环境变量名由配置键转大写并把 . / - 替换为 _,例如:
server.addr:--server.addr=:9090/SERVER_ADDRprofiles.active:--profiles.active=local/PROFILES_ACTIVEdatasource.host:--datasource.host=postgres/DATASOURCE_HOSTsecurity.jwt.expire-seconds:--security.jwt.expire-seconds=86400/SECURITY_JWT_EXPIRE_SECONDSapp.tasks.cleanup-session.cron:--app.tasks.cleanup-session.cron="@every 1m"/APP_TASKS_CLEANUP_SESSION_CRON
datasource.driver 用于切换数据库驱动,支持 sqlite 和 postgres。
datasource.dsn、DATASOURCE_DSN 和 POSTGRES_DSN 仍可作为完整 PostgreSQL DSN 覆盖项;datasource.sqlite-path / DATASOURCE_SQLITE_PATH 用于 SQLite 文件路径。旧的扁平 YAML 键和旧环境变量名仍兼容,但后续新增配置优先使用层级 YAML 命名。
监控配置位于 app.monitor:enabled 控制采集,interval-seconds 控制采样周期,retention-hours 控制快照保留时间。采样协程使用安全协程封装,容器关闭时会取消并等待退出。
- 用户名:
admin - 密码:
admin123456 - 角色:
admin
make build-client
make build-admin
make build-frontendGo 使用 frontend/embed.go 嵌入 frontend/client/dist 和 frontend/admin/dist。构建命令使用各前端 lockfile 执行 npm ci,并在 Go 编译前生成最新资源;/api/* 走后端接口,/admin 返回后台资源,其他路径返回客户端资源。
make build-api
make build运行模式:
bin/api
bin/api -mode=worker
bin/api -mode=migrate
go run ./cmd/manualcmd/manual 目前不接收额外 CLI 参数。模型、Base URL、对话日志路径和项目需求扩写 prompt 均在代码内固定,API Key 从 ~/.codex/auth.json 读取。
docker compose -f deploy/docker-compose.yml up --build本机直接运行默认监听 http://localhost:8081;Compose 对外监听 http://localhost:8080,并显式使用 Compose 中的 PostgreSQL 和 Redis。
生产模板:
Copy-Item app-prod.example.yaml app-prod.yaml
docker compose -f deploy/docker-compose.prod.example.yml up --build生产发布推荐先复制非敏感参数模板,并通过环境变量提供密钥:
Copy-Item scripts/deploy/configs/prod.example.json scripts/deploy/configs/prod.json
make deploy-check DEPLOY_CONFIG=scripts/deploy/configs/prod.json
make deploy DEPLOY_CONFIG=scripts/deploy/configs/prod.json发布脚本会校验 POSTGRES_PASSWORD、REDIS_PASSWORD、SECURITY_JWT_SECRET、APP_ADMIN_PASSWORD,使用排他锁防止并发发布,以 UTC 时间戳镜像标签保留最近版本,并等待 API 健康检查通过。
生产环境建议:
APP_BOOTSTRAP_AUTO_MIGRATE=false,由migrate服务或bin/api -mode=migrate -env=prod单独执行迁移。SECURITY_JWT_SECRET、POSTGRES_PASSWORD、REDIS_PASSWORD、APP_ADMIN_PASSWORD必须通过环境变量或密钥系统提供。- API 可多副本部署;登录限流、Session 和 RBAC 权限缓存依赖 Redis,适合横向扩容。
- 列表接口支持
page、page_size,服务端会限制最大分页大小。
登录:
curl -X POST http://localhost:8081/api/auth/login `
-H "Content-Type: application/json" `
-d '{"username":"admin","password":"admin123456"}'读取当前用户:
curl http://localhost:8081/api/auth/me -H "Authorization: Bearer <token>"主要接口:
POST /api/auth/loginPOST /api/auth/logoutGET /api/auth/meGET /api/user/pagePOST /api/user/createGET /api/role/pagePOST /api/role/createGET /api/permission/pagePOST /api/permission/createGET /api/audit/pageGET /api/package/pagePOST /api/package/createPUT /api/package/:idDELETE /api/package/:idGET /api/package/walletGET /api/package/order/pagePOST /api/package/:id/purchasePOST /api/package/consumeGET /api/monitor/summary?range=1h|6h|24h|7dGET /api/monitor/series?range=1h|6h|24h|7d
非生产环境快捷测试接口:
GET /api/_test/pingPOST /api/_test/echoGET /api/_test/configGET /api/_test/dbGET /api/_test/redisPOST /api/_test/login
go test ./...
make test
make build
gofmt -w <modified-go-files>