签入版本

This commit is contained in:
小蚂蚁云
2026-10-20 21:53:26 +08:00
parent 5cc3da657c
commit b33799aa63
427 changed files with 32547 additions and 1 deletions
@@ -0,0 +1,83 @@
# 5.18 gmeta 注解系统总览
:::tip 概述
gmeta 注解是本项目的"声明即事实"机制:请求结构体上的一个 gmeta.Meta 标签同时驱动路由注册、权限校验、操作日志、OpenAPI 文档四件事。解析与分发在 internal/router/bind.go(反射绑定)与 meta/(路由元数据表)。
:::
## 一个标签,四份事实
```go
type UserPageReq struct {
gmeta.Meta `method:"get" path:"/api/user/page" summary:"用户分页"
permission:"sys:user:page" log:"用户管理-查询分页记录" logType:"query"`
// ...
}
```
```text
解析后同时产出:
① 路由注册 GET /api/user/page → CUser.Page
② 权限校验 HasPerm("sys:user:page")(包装层每请求判定)
③ 操作日志 标题"用户管理-查询分页记录"、类型 query
④ OpenAPI 文档 /api.json 的 path/summary/参数说明
```
不存在"代码改了忘改路由表/权限表/文档"——标签是唯一真相。
## 标签字段语义
| 标签 | 语义 |
|------|------|
| `method` | HTTP 方法(get/post/put/delete) |
| `path` | 完整路由模板(含 /api 前缀;`:id` 为路由参数,req 同名字段承接) |
| `summary` | OpenAPI 摘要 |
| `permission` | 权限节点 `sys:{module小驼峰}:{action}`;空 = 登录即可 |
| `log` | 操作日志标题 `"{模块中文名}-{动作}"`;空 = 不记录 |
| `logType` | 日志类型字符串(query/add/update/delete/import/export/reset/…),经 LogTypeMap 转 41 个枚举值 |
| `public` | `"true"` = 免登录(仍需与 middleware/public.go 白名单一致) |
## Bind 绑定流程(internal/router/bind.go)
```text
Bind(s, new(controller.CXxx)) 扫描控制器全部导出方法:
1) 校验签名:func (c *Xxx) Page(ctx, req *v1.XxxReq) (*v1.XxxRes, error)
(签名不符静默跳过——排障注意)
2) 解析请求结构体内嵌 gmeta.Meta 扩展标签
3) 按 method:path 注册路由 + meta.Register(rm) 写入路由元数据表
(键 "METHOD /path",读写锁保护;Lookup 供调试,All 供文档生成)
4) 补注册进 gf goai(闭包路由 gf 不会自动收集)→ /api.json 原生 OpenAPI
5) 生成统一包装 handler:
路由元数据写入 ctx(操作日志中间件读取)
→ 权限校验(403 短路;不设独立 Permission 中间件)
→ r.Parse(req)(路由参数+query+body,含 gvalid 校验)
→ 调用业务方法 → response.Ok/Fail 信封写出
```
## BodyUnmarshaler 逃生舱
```text
当请求体顶层形态无法用结构体标签表达(如平铺 map)时,
Req 实现 UnmarshalBody(r *ghttp.Request) error 接口:
→ 跳过默认 Parse,实现内自行完成解析与 gvalid 校验
```
## 注册验证
```sh
# OpenAPI 检查(gmeta 补注册后全量可用)
curl http://127.0.0.1:8000/api.json | grep "user/page"
# 启动路由表
# config.yaml: server.dumpRouterMap: true
```
## 开发规约
```text
* 每个接口必须有 gmeta——没有标签的方法不会注册路由
* permission 新码必须同步菜单节点 + 角色勾选(否则 403)
* public:"true" 必须同时出现在 middleware/public.go 白名单(三处一致)
* log 空 = 不记录(有意不记录才留空);logType 缺省按 HTTP 方法自动推断(0)
* path 一律 /api 开头、无 /v1 版本段
* 改 path/permission 等标签后重启生效(路由与元数据表启动期构建)
```