从 PHP 到 AI + Golang,程序员自救转型手记(四十八):菜单规则管理实现
这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-admingithub | gitee开源项目的制作全程记录分享。在上一期我们进行了 “列表通用排序接口实现增量重排法”本期将完成菜单规则管理实现菜单规则管理实现我们之前已经写好了AdminRule模型这里提供向 AI 详细的提供模型位置和新文件位置并提供参考代码基于internal/model/admin.go的AdminRule模型在internal/handler/admin/auth/建立AuthAdminRuleHandler控制器并建立对应的仓储、服务等可参考已有的AuthAdminHandler及其仓储、服务。已完成 AdminRule 的 CRUD 骨架搭建新增4个文件并通过 go build、go vet、gotest校验。 新增文件 internal/repository/admin/rule.go — AdminRuleRepository internal/service/admin/auth/rule.go — AuthAdminRuleService internal/handler/admin/auth/rule.go — AuthAdminRuleHandler internal/router/admin/auth/rule.go — 路由注册# ......先简单检查了一下还行好家伙考虑未来不做可视化CRUD了。数据效验目前 AI 写的效验全部是在服务层新增了一个validateRule函数里边写了大量if用来检查name不能为空、pid不能为自身等这当然不太合理gin的ShouldBindJSON方法本身就支持数据绑定同时完成效验而且我们在基控制器已经调用过该方法了所以必填、格式正确性等验证直接在模型上加bindingtag 即可。也可以写validatetag它是专门做验证的包https://github.com/go-playground/validator的语法该依赖已随gin框架内置可直接使用。还有一些涉及数据库、父子关系、唯一性、业务联动的效验必须抽到服务层这里有两个选择使用validatetag然后在服务层完成效验或直接代码里边if这里选择后者因为这次验证不算多且对验证消息的要求比较高如下// 主要就是因为这个验证选择统一使用 if这里的验证消息定制化较高ifentity.Typemenu(entity.Path||entity.Component){returnerrors.New(规则类型为菜单时菜单路由路径和菜单组件路径不能为空)}// 名称唯一校验排除自身existing,err:s.repo.FindByName(c,entity.Name)iferr!nil!errors.Is(err,gorm.ErrRecordNotFound){returnerr}ifexisting!nilstrconv.FormatUint(uint64(existing.ID),10)!pk{returnerrors.New(规则名称已存在)}// 路由路径的唯一性验证// ......// 不能将自身设为自己的上级 上级存在性检查// ......方法位置错误findByName根据规则名称查询和findByPath根据菜单路由路径查询方法AI 给放在了服务层可能是因为目前这两个方法仅用于 数据效验 时查数据。这里让它移动至仓储层一是因为职能规划二是这两个方法未来其他地方需要使用的可能性很大仓储里边有它们非常合理。完成移动只需要一句话然后已移至 internal/repository/admin/rule.go FindByName 和 FindByPath 已移至 internal/repository/admin/rule.go。 两个仓储方法均使用 GORM Generics API。 服务层改为调用 s.repo.FindByName(c, entity.Name)s.repo.FindByPath(c, entity.Path)删除服务层原有的 findByName、findByPath 私有方法。 服务层仍负责唯一性判断和业务错误消息。 已格式化并通过仓储层、服务层相关包测试。菜单规则管理定制功能菜单规则作为权限系统的基础此功能当然不是一个CRUD就能搞定的接下来基于已有CRUD进行一系列定制控制器层自定义扩展数据和列表数据适配器菜单规则管理的菜单列表需要组装为可以展开折叠的树状表格数据使用tree.Build即可选择器如远程下拉读取菜单列表时需要组装为另外一种树状列表在title字段上渲染树状分支符号使用tree.Render即可只读取当前登录管理员拥有权限的菜单规则使用handler.WithExtension自定义扩展数据传递当前登录管理员的数据到服务层供后续使用// NewAuthAdminRuleHandler 创建菜单和权限规则管理控制器实例funcNewAuthAdminRuleHandler(svc*svcAuth.AuthAdminRuleService)*AuthAdminRuleHandler{returnAuthAdminRuleHandler{Handler:handler.NewHandler(svc,handler.WithAdapter(handler.Adapter{// 定义控制器层的数据适配器就不需要重写控制器层的 List 方法了List:func(data any,opts service.Options)(any,error){rules,ok:data.([]model.AdminRule)if!ok{returndata,nil}ruleData:make([]map[string]any,len(rules))fori:rangerules{ruleData[i]rules[i].ToMap()}ifopts.Selector{returntree.Render(ruleData,id,pid,title),nil}else{returntree.Build(ruleData,id,pid,children),nil}},}),handler.WithExtension(func(c*gin.Context)any{returnsvcAuth.AuthAdminRuleExtension{AdminSession:middleware.GetAdmin(c),}}),),svc:svc,}}服务层List 方法读取自定义扩展中的管理员数据并使用Permission包读取当前登录管理员拥有权限的菜单规则。// List 覆写通用查询全部记录方法: 根据管理员权限过滤func(s*AuthAdminRuleService)List(c*gin.Context,opts service.Options)([]model.AdminRule,error){// 从控制器传来的 管理员信息 扩展数据extension,ok:opts.Extension.(*AuthAdminRuleExtension)if!ok||extension.AdminSessionnil{returnnil,errors.New(参数错误缺少 AdminSession 扩展数据)}perm:permission.New()// 是否超级管理员super,err:perm.IsSuperAdmin(c.Request.Context(),extension.AdminSession.ID)iferr!nil{returnnil,err}// 树状表格无翻页设定无限 limitopts.Limit999999// 来自选择器则只查 dir、menu不查 nodeifopts.Selector{opts.Wheresappend(opts.Wheres,service.WhereGroup{Wheres:[]service.Where{{Field:type,Operator:IN,Value:[]string{dir,menu},}},})}// 非超管读取当前管理员拥有的权限规则 IDsif!super{ruleIDs,err:perm.GetRuleIds(c.Request.Context(),extension.AdminSession.ID,nil)iferr!nil{returnnil,err}iflen(ruleIDs)0{returnnil,nil}// 添加 IN IDs 的 where 以确保只读取到当前管理员拥有的权限规则opts.Wheresappend(opts.Wheres,service.WhereGroup{Wheres:[]service.Where{{Field:id,Operator:IN,Value:ruleIDs,}},})}rules,err:s.repo.List(c,s.BuildRepoOpts(opts))returnrules,err}Count 方法做类似以上的改造只读取拥有权限的菜单规则的数量前端受益于我们的table组件和useTableManager.ts表格管家按部就班的写好列定义及表单即可自动完成对服务端数状表格的兼容没啥特殊的不再赘述。

相关新闻

SQL Server日期时间函数全解析:从基础概念到高阶应用与性能优化

SQL Server日期时间函数全解析:从基础概念到高阶应用与性能优化

1. 项目概述:为什么你需要一份“最全”的日期时间函数指南干了这么多年数据库开发,我发现一个挺有意思的现象:无论是新手还是老手,但凡涉及到SQL Server里的日期时间处理,总免不了要去翻文档或者搜一下某个函数的具体用…

2026/10/13 10:49:10 阅读更多 →
B站视频下载终极指南:三步解锁大会员4K高清视频

B站视频下载终极指南:三步解锁大会员4K高清视频

B站视频下载终极指南:三步解锁大会员4K高清视频 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 还在为B站上的精彩视频无法…

2026/10/6 12:43:06 阅读更多 →
软件设计的一些感想

软件设计的一些感想

软件设计的一些感想 做了十几年软件,写过无数行代码,也重构过无数个深夜。回头看,软件设计这件事,最难的从来不是技术选型或者算法优化,而是如何在复杂中保持简单,在变化中守住稳定。今天不聊高深的理论&am…

2026/10/11 1:14:35 阅读更多 →

最新新闻

cangaroo USB-CAN上位机源码:编译、调试与二次开发指南

cangaroo USB-CAN上位机源码:编译、调试与二次开发指南

简介:这是一份Cangaroo USB-CAN上位机完整源码,采用Qt图形界面框架开发,面向需要进行CAN总线数据监控、报文分析与设备调试的软硬件工程师。压缩包共包含两百一十四份文件,其中C和C语言的头文件与实现文件占主要比例,还…

2026/10/13 22:01:45 阅读更多 →
烂番茄影评情感分类实战:Python实现从TF-IDF到BiLSTM

烂番茄影评情感分类实战:Python实现从TF-IDF到BiLSTM

简介:基于Python实现对烂番茄电影评论情感分类的完整实践项目,来源于华中科技大学大数据与人工智能课程大作业。项目包含源码、实验报告与数据集,覆盖评论获取、文本预处理、情感特征提取、模型训练与评估等环节,适合计算机、人工…

2026/10/13 22:01:45 阅读更多 →
开源AI工具实战:让大模型从聊天到本地自动化干活

开源AI工具实战:让大模型从聊天到本地自动化干活

1. 从聊天到干活:这个开源AI工具到底在解决什么问题大多数人第一次接触AI,都是通过对话框。你问一句,它答一句,聊得挺热闹,但聊完之后呢?该手动复制的还得手动复制,该自己打开软件操作的还得自己…

2026/10/13 22:00:44 阅读更多 →
OpenClaw本地AI助手:工具调用与插件化架构实战指南

OpenClaw本地AI助手:工具调用与插件化架构实战指南

1. 从"能聊天"到"能干活":个人智能助手到底缺了什么大多数人第一次接触AI助手,体验路径都差不多:打开一个对话框,问几个问题,得到几段回答,然后关掉。下次再打开,它不记得你…

2026/10/13 22:00:44 阅读更多 →
Petrel成本透明化:从黑盒到明白账的业务价值展示指南

Petrel成本透明化:从黑盒到明白账的业务价值展示指南

痛点很直接:Petrel这种专业建模软件,年度许可证费用不低,加上配套硬件、算力、数据存储,一年下来是一笔不小的开销。过去这笔钱怎么花的、谁用了多少、给业务带回了什么,基本是一笔糊涂账。业务部门看费用报表只看得到…

2026/10/13 22:00:44 阅读更多 →
Cadence许可证管理平台落地实践:从FlexNet监控到配额治理

Cadence许可证管理平台落地实践:从FlexNet监控到配额治理

做EDA工具管理的朋友应该都有过这种经历:上午十点,仿真任务刚提交,脚本就报出License checkout failed,群里马上炸锅;你随手敲一条lmstat -a,发现某个用户把几十个 feature 占得满满当当,但任务…

2026/10/13 22:00:44 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →