10 KiB
10 KiB
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 +/swaggerUI) - 全局钩子
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.goBind(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:jtizset+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:3306root/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.*