- Implemented API endpoints for listing tenant contents and updating content status.
- Added Swagger documentation for new endpoints:
- GET /super/v1/tenants/{tenantID}/contents
- PATCH /super/v1/tenants/{tenantID}/contents/{contentID}/status
- Created DTOs for content item and status update form.
- Enhanced frontend to support content management in the tenant detail page.
- Added search and filter functionalities for tenant contents.
- Implemented unpublish functionality with confirmation dialog.
- Updated service layer to handle new content management logic.
路由生成(gen route)
通过在控制器方法上编写注释,解析器从 Go AST 中读取注释、方法签名与参数列表,自动生成路由注册与参数绑定代码。
- 核心标签:
@Router定义路径与方法;@Bind定义方法参数的来源与键名。 - 生成行为:输出
router.<METHOD>(path, FuncN(...))或DataFuncN(...)包装调用,并自动汇聚所需 imports 与控制器注入字段。
快速开始
atomctl gen route [path]
- 生成文件:当前包目录下
routes.gen.go - 分组与排序:按控制器分组,导入、方法、路由项稳定排序,便于审阅 diff。
注释语法
-
@Router <path> [<method>]- 示例:
@Router /users/:id [get]
- 示例:
-
@Bind <paramName> <position> [key(<key>)] [model(<field>|<model>[:<field>])]paramName与方法参数名一致(大小写敏感)position:path、query、body、header、cookie、local、file- 可选:
key()覆盖默认键名;model()详见“模型绑定”。
参数绑定规则(按 position)
- query:标量用
QueryParam[T]("key"),非标量用Query[T]("key") - path:标量用
PathParam[T]("key"),非标量用Path[T]("key")- 若使用
model()(仅在 path 有效),会按字段值查询并绑定为T,详见下文
- 若使用
- header:
Header[T]("key") - body:
Body[T]("key") - cookie:
string用CookieParam("key"),其他用Cookie[T]("key") - file:
File[multipart.FileHeader]("key") - local:
Local[T]("key")
说明:
- 标量类型集合:
string、int、int32、int64、float32、float64、bool key默认等于paramName;设置key(...)后以其为准file使用固定类型multipart.FileHeader
类型与指针处理
- 支持
T、*T、pkg.T、*pkg.T;会正确收集选择子表达式对应 import - 忽略结尾为
Context或Ctx的参数(框架上下文) - 指针处理:除
local外会去掉前导*作为泛型实参;local保留指针(便于写回)
解析与匹配
- 先收集注释中的多条
@Bind,再按“方法参数列表顺序”匹配并输出绑定器,确保调用顺序与方法签名一致 - 未在方法参数中的
@Bind会被忽略;缺失@Router或方法无注释将跳过该方法 - import 自动收集去重;控制器注入字段名为类型名的小驼峰形式,例如
userController *UserController
返回值与包装函数
- 返回值个数 > 1:使用
DataFuncN - 否则使用
FuncN N为参与绑定的参数个数
模型绑定(path + model)
当 @Bind ... model(...) 配合 position=path 使用时,将根据路径参数值查询模型并绑定为方法参数类型的实例(T 来自方法参数)。
- 语法:
- 仅字段:
model(id)(推荐) - 指定字段与类型:
model(id:int)、model(code:string)(用于非字符串路径参数) - 指定类型与字段:
model(pkg.Type:field)或model(pkg.Type)(字段缺省为id)
- 仅字段:
- 行为:
- 生成的绑定器会按给定字段构造查询条件并返回首条记录
- 自动注入 import:
field "go.ipao.vip/gen/field",用于构造字段条件表达式
示例:
// @Router /users/:id [get]
// @Bind user path key(id) model(id)
func (uc *UserController) Show(ctx context.Context, user *models.User) (*UserDTO, error)
完整示例
注释与方法签名:
// @Router /users/:id [get]
// @Bind user path key(id) model(id)
// @Bind fields query
// @Bind token header key(Authorization)
// @Bind sess cookie key(session_id)
// @Bind cfg local
func (uc *UserController) GetUser(ctx context.Context, user *models.User, fields []string, token string, sess string, cfg *AppConfig) (*User, error)
生成的路由注册(示意):
router.Get("/users/:id", DataFunc4(
r.userController.GetUser,
PathModel[models.User]("id", "id"),
Query[[]string]("fields"),
Header[string]("Authorization"),
CookieParam("session_id"),
))
错误与限制
- 无效的
@Router语法会报错;无效的position会在解析阶段触发错误 file仅支持单文件头;model()仅在position=path时参与代码生成- 请确保路由段变量名与
key(...)保持一致