Files
EasyGoAdmin_GoFrame_EleVue/CLAUDE.md
T
2026-10-20 11:37:25 +08:00

10 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Status

GoFrame v2 后端已按 document/architecture.md(唯一权威定稿)完整落地:

  • 25 张业务表 → 27 个模块全部实现(auth/index + system7 + data7 + content3 + monitor4 + tool4);目录平铺、不分域层级:api/v1/{m}.go(单包 v1)、internal/controller/{m}.go(单包 controller)、internal/logic/{m}.go(单包 logic)、internal/service/{m}.go(接口+注册,手维护,勿整体运行 gf gen service);跨模块直接同包调用(如 user 使用 ResolveCityNames 无需 import)
  • 中间件链:CORS → Response → RateLimit → Demo → JWT → Tenant → OperationLog;RateLimit 为固定窗口限流(rateLimit.* 配置,登录/验证码独立更严阈值 authLimit,计数经 utility/cache 共享,仅限 /api/ 路径);app.demo=true 时 Demo 拦截全部写操作(提示"演示环境,禁止操作!"),读操作与公开白名单路径放行;权限与日志经 gmeta 标签在 internal/router/bind.go 反射为路由元数据统一处理(bind 同时补注册进 gf goai,/api.json 原生 OpenAPI + /swagger UI)
  • 全局钩子 internal/model/hooks:审计字段盖章、软删除改写、租户隔离(dao.{X}.Ctx 是唯一查询入口)
  • 代码生成器(tool 域):读表结构渲染 templates/(后端 {{ }} 定界;templates/ui* 前端模板因 Vue 插值冲突用 [[ ]] 定界)产出 后端八件套(api/controller/logic/service + dao/index、dao/internal、model/entity、model/do,与 gf gen dao 产出同构,生成后统一 gofmt) + 前端文件,并同步创建菜单+权限节点、字典数据、router.go 注册行(幂等);支持 HTTP 与 CLI 两种方式
  • 整库迁移(internal/migrate + cmd/migrator):源库内省(表/列/索引/注释)→ 中间表示 → 目标方言 DDL(mysql/pgsql/sqlite/mssql/oracle 五 renderer,对齐 resource/sql 定稿)→ 分批搬运 → pgsql 序列修复;纯 CLI、gdb 动态建连裸读裸写(不走 dao,不触发全局钩子);-drop-target-first 清空目标库全部表

关键约定(与直觉相反的点)

  • 主键统一 int 数据库自增(2026-10-13 定稿):禁用雪花算法(utility/id 已删除);新增后用 result.LastInsertId() 回读;hooks 不填 id
  • 软删列统一 del_flag;表前缀 goframe_
  • 新增模块四件套平铺放置(api/v1、controller、logic、service 各一文件,同包 init 自动注册,无需 blank import);service 接口手维护;路由注册由生成器自动写入或手动 router.go Bind(controller.CXxx)
  • 定时任务处理方法在 internal/task:调度器与注册表在 internal/logic 的 job 模块(logic.RegisterJobHandler);任务实现平铺 internal/task/{任务名}.go,init 中自注册(注册名=url 字段值,http(s) 地址除外),依赖单向 task→logic(任务可复用 base 共享能力,logic 禁止反向 import task);由 internal/cmd 空白导入触发加载;调度消费 execute_policy(1并行/2单例/3放弃)与 is_sync(1同步/0异步),策略2/3叠加 job:lock:{id} 执行锁(utility/cache SET NX,多实例共享,TTL 300s 兜底);内置 LogClean 任务每日 02:30 分批物理清理三张日志表(保留天数 job.logRetentionDays 默认90,任务参数 retentionDays 可覆盖)
  • monitor 域三个无表模块:在线用户(/onlineUser/page+forceLogout,登录 MarkOnline/登出 MarkOffline 写 online:jti zset+info 键,踢出=拉黑 jti)、服务器监控(/server/info:runtime/磁盘分平台文件 server_monitor_windows/other.go/MySQL/Redis 连通)、缓存监控(/cache/info:Redis INFO 解析,内存降级时返回 mode=memory);前端 ui/src/views/monitor/{online,server,cache};OpenAPI 经 bind.go 补注册后 /api.json 全量可用
  • 文件命名对齐 dao(snake_case):api/v1/{模块}.go、internal/controller/{模块}.go、internal/logic/{模块}.go、internal/service/{模块}.go 均用表名去前缀形式(如 config_item.go/file_template.go/operation_log.go),生成器后端目标同步此规则(前端文件仍用驼峰如 fileTemplate.ts)
  • log_type 值固定(前端按此映射显示):add=1 update=2 delete=3 query=4 import=5 export=6 … generate=19 reset=24(见 consts/log_type.go,前端按此映射显示)
  • 筛选对齐三件套(2026-10-14 定稿):前端 querySchemas.ts 每个输入框 ↔ XxxPageReq 同名驼峰字段 ↔ spec 声明——字符串 Input → LikeFields(逐列模糊,列名声明、值取 req 同名驼峰json),Select/InputNumber → EqFields(零值跳过);KeywordFields(req.keyword 多列 OR)能力保留在基座,模块不声明,未来需要时再用;导出统一走 xxxSpec.applyFilters 与列表同套筛选
  • 超管角色编码 ROLE_SUPER_ADMIN;超管 getUser 返回通配权限 *:*:*
  • 角色数据权限(role.data_scope 四档:1-全部 2-本部门及以下 3-本部门 4-仅本人):模块在 spec 声明 DataScope: ApplyDataScope("dept_id") 即生效(internal/logic/data_scope.go,共享工厂);多角色在身份加载层取最宽松,超管/平台绕过,未分配部门用户挂部门档降级为仅本人;仅作用于 Page/List/导出(applyFilters 链),Detail/Update/Delete 不过滤;档位文案走字典 role_data_scope;身份缓存(300s)含 data_scope+deptId,角色/用户变更主动清
  • 定时任务 cron 用 gf gcron 的 # 前缀 6 段式(# */5 * * * * = 标准5段忽略秒)
  • multipart 上传字段用 *ghttp.UploadFile + p:"file" 标签
  • 上传两段式:upload.SaveTemp 先入 resource/upload/temp/日期/(白名单+大小+图片嗅探校验),表单保存时 upload.SaveFromTemp 移动到正式子目录(user/article/notice/link/example/tenant 等);静态访问 /upload/** 由 SetServerRoot("resource") 提供
  • 命名:入参/出参 json 一律驼峰;例外:登录/令牌接口返回 access_token/refresh_token/expires_in/token_type(OAuth2 惯例,前端按此读取,勿改驼峰)
  • IP 归属地:utility/ip2region(xdb 于 manifest/data/ip2region.xdb,配置 ip2region.path),登录日志/操作日志 location 自动填充;受信代理列表 api.proxyIps(支持 CIDR,信任 X-Forwarded-For)
  • logic 共享能力层 internal/logic/base.go(横切能力,组合式复用):文件字段(SaveFileField/SaveFileFields/SaveMultiFileField)、富文本占位符(LocalizeContentFields/ExpandContentFields,[IMG_URL] 为持久化契约)、枚举文本(DictGetText/SerializeMapOnRead)、唯一校验(CheckUnique,仅为 UX 层,唯一性真值靠 uk_* 索引)、事务(WithTrans,事务内禁 HTTP/文件IO、bcrypt 先算)、分块查询(ChunkQuery)、泛型树(BuildTree)、临时目录清理(CleanTemp,每日 03:30 gcron 触发,file.tempExpireDays 控制保留天数);纪律:只依赖 dao/utility/consts,导出函数上限15个
  • {field}Text 字典驱动:枚举字段显示名从 dict_item 解析(唯一真相),模块头部声明 xxxSerializeMaps = map[字段]字典编码(编码规范 {模块snake}_{字段snake},如 user_status、job_execute_policy),响应行用 DictGetText(ctx, code, value) 填充;字典由生成器 createDict 按列注释枚举自动创建(支持 1-正常 与 1=正常 两种写法),文案在字典管理页修改;进程内缓存300s。例外:operation_log.type 存注解常量值,用静态表 LogTypeText(consts.LogTypeNames)
  • 生成器保护 skipTables:仅关联表(role_menu/user_role)整表跳过;其余表统一文件级处理——缺失补生成、存在跳过、generator.overwrite: true 时覆盖(唯一开关在 config.yaml,覆盖结果单独计入 Overwritten),菜单/字典/路由等幂等副作用照常执行
  • 城市编解码:ResolveCityNames / ResolveCityCodes(internal/logic 包级函数),user 模块 Add/Update/Import/Detail 已接入
  • 代码生成器 CLI:go run ./cmd/generator -tables "goframe_x|注释" [-preview|-batch];覆盖模式由 generator.overwrite 配置统一控制;dao/entity/do 四件由生成器直接产出,生成后只需 go build ./... 并重启(gf gen dao 仅在表结构变更时用于刷新已实现模块的 dao)

Commands

Windows 环境(无 make,直接用 gf/go):

go build ./...                          # 编译
go test ./...                           # 测试(sqlite 集成 + hooks MySQL 集成)
go vet ./... && gofmt -l .              # 静态检查
gf gen dao -c hack/config.yaml          # 表结构变更后重新生成 dao(service 手维护,勿用 gf gen)
go run ./cmd/generator -tables "goframe_order|订单表"   # 代码生成(文件+菜单+字典+路由)
go run ./cmd/migrator -src-type=mysql -src-host=127.0.0.1 -src-hostport=3306 -src-database=easygoadmin.goframe.elevue -src-username=root -src-password=root -dst-type=pgsql -dst-host=127.0.0.1 -dst-hostport=5432 -dst-database=easygoadmin.goframe.elevue -dst-username=postgres -dst-password=123456 -drop-target-first   # 整库迁移(源→目标方言,含结构+注释+索引+数据+序列)
go build -o bin/admin-server.exe main.go && ./bin/admin-server.exe   # 运行(:8000)

环境

  • MySQL 127.0.0.1:3306 root/root 库 easygoadmin.goframe.elevue;定稿脚本 document/easygoadmin.goframe.elevue.sql(人工导入维护)
  • Redis 127.0.0.1:6379(缓存降级内存);本地测试账号 admin/admin123
  • 方言 DDL resource/sql/{mysql,pgsql,sqlite,mssql,oracle}.sql(后四份转换生成,待人工校对)
  • 前端 ui/(Element Plus;接口统一 /api/v1/*(/api 为通用网关前缀,/v1 为版本前缀)——gmeta 路径/公开白名单/健康检查均按此注册,前端 baseURL /api + 版本前缀 /v1 拼接;登录返回读 data.access_token。例外:公开路由(middleware/public.go 的 publicPaths:/api/login、/api/register、/api/captcha、/api/oauth2/token、/api/health)一律不带 /v1(网关免版本路径,gmeta path / router.go / 白名单三处须一致,勿加 /v1)
  • 生成器配置 generator.parentMenuId=189、generator.overwrite=false(覆盖开关);上传配置 file.*