这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-admingithub | gitee开源项目的制作感谢 star ~全程记录分享。在上一期我们进行了 “多条件组筛选、字段白名单”本期将完成增加管理员角色组管理增加管理员角色组管理我们之前已经建立好了菜单规则管理和管理员账号管理下一步再制作好管理员角色组管理RBAC权限模型就基本完善了这个权限模型非常简单最核心的是用户、角色、权限的三层关联其中用户并不直接跟权限挂钩而是先建立角色组将具体的权限节点分配给角色组然后将角色组分配给用户它还有以下细节一个角色组可以有多个权限节点一个用户可以属于多个角色组一个权限也可以被分配给多个角色受益于之前已经准备好的服务端基类和前端的table组件及表格管家hook我们这次基本上只需要考虑核心业务其他的基本功能都是唾手可得的首先直接让 AI 参考之前已有的 CRUD 实现角色组管理的基本功能就像建立菜单规则管理实现时一样然后从基础的 CRUD 开始角色组功能特有的特性开发为了让读者脑海里有概念这里提供两张成品图重写服务层 Create 方法在基础的CRUD上额外对一个角色组设定的权限规则进行处理和检查首先是对分组基础信息中的上级分组不能是自身、上级分组不存在的检查。如果输入的权限节点包含了系统所有的权限节点则将权限节点直接折叠为*通配符号而不再单独的存储所有权限节点的 id 号即超管好处是新增的权限节点不再需要额外向超管级分组追加。这一点是重中之重对输入权限节点进行检查首先是非超管不能建立超管级分组其次是普通管理员能分配给新组的权限必需是自己拥有的。重写服务层 Update 方法和以上 Create 方法类似额外检查上级分组不能是自己的子级分组含直接子级、间接子级避免形成环。重写服务层 Delete 方法主要是防止出现游离分组能被删除的分组必需没有子级或使用批量删除连同所有子级一起删。重写服务层 List 方法这下基本上是全部重写了。List 方法这边主要也是权限相关即只读取当前管理员拥有全部权限的角色组但凡某个角色组有一个权限节点不属于他就不能让他查看。这里有个小坑不能是读取当前管理员拥有的分组因为管理员可以拥有多个分组只读取自己拥有的分组看起来是合理的但是会出现比如当前管理员有角色组管理的权限自己操作添加了一个分组那么这个分组就必须分配给当前管理员否则他查都查不到 等情况重写控制器 List 方法从图中可以看出来这次的列表也是支持树状表格的如果单这一点的话我们还可以使用List 数据适配函数对输出的数据进行格式化不过这次我们还得查出权限规则字段的摘要文本比如控制台等 29 项这种字样目前在List 数据适配函数中不能访问到服务层实例所以选择直接重写控制器 List 方法核心的代码如下// List 覆写通用列表方法: 追加 rules_title 摘要字段并渲染为树状结构func(h*AuthAdminGroupHandler)List(c*gin.Context){// ......// 批量构建每个分组的 rules 摘要文本例如: 控制台等 60 项titles,err:h.svc.BuildRulesTitles(c,groups)iferr!nil{httpx.Fail(c,httpx.WithMessage(规则标题查询失败: err.Error()))return}// 转 map 以备后续树状数据组装并注入 rules_titlegroupData:make([]map[string]any,len(groups))fori:rangegroups{m:groups[i].ToMap()m[rules_title]titles[groups[i].ID]groupData[i]m}varlist[]map[string]anyifopts.Selector{listtree.Render(groupData,id,pid,name)}else{listtree.Build(groupData,id,pid,children)}httpx.Success(c,httpx.WithData(gin.H{list:list,total:total,}))// ......}如上主要是调用了服务层的BuildRulesTitles方法以及最后输出时根据opts.Selector请求是否来自选择器输出为不同的树状数据其中BuildRulesTitles方法用于提取权限规则的中文摘要规则入库的是ids前台展示1,2,3肯定没有控制器等 20 项好看。重写控制器 Get 方法这一点是为了适配前端el-tree组件的数据格式在编辑一个角色组时特意将规则中的所有父级节点去除这些父级节点的选中状态由子级决定