Golang实战系列:mysql数据库查询 -- 实现无限级菜单(beego orm)

我们开发会遇到类似于获取菜单这种情况,架构大体类似如下:

  • 人事管理
    • 员工资历
    • 员工奖惩
  • 统计管理
    • 统计列表
  • 系统管理
    • 我的设置
    • 权限管理
    • 角色列表

我这里用的是双层结构,我们搜索的时候用的是递归查询,所以理论上可以无限级添加(不考虑数据库的感受的话)。

数据表如下:


-- Table structure for tbl_auth_menu


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
DROP TABLE IF EXISTS `tbl_auth_menu`;
CREATE TABLE `tbl_auth_menu` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(11) NOT NULL COMMENT '父级菜单id',
  `name` char(20) NOT NULL COMMENT '菜单名单',
  `sort` tinyint(4) DEFAULT '0' COMMENT '排序值',
  `route` varchar(60) DEFAULT '' COMMENT '跳转链接',
  PRIMARY KEY (`id`),
  KEY `pid` (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COMMENT='权限管理_菜单表';

-- Records of tbl_auth_menu


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
BEGIN;
INSERT INTO `tbl_auth_menu` VALUES (14, -1, '人事管理', 1, '');
INSERT INTO `tbl_auth_menu` VALUES (15, -1, '统计管理', 2, '');
INSERT INTO `tbl_auth_menu` VALUES (16, -1, '系统管理', 3, '');
INSERT INTO `tbl_auth_menu` VALUES (17, 14, '员工资料', 1, '/user/info');
INSERT INTO `tbl_auth_menu` VALUES (18, 14, '员工奖惩', 2, '/user/award');
INSERT INTO `tbl_auth_menu` VALUES (19, 15, '统计列表', 1, '/statis/list');
INSERT INTO `tbl_auth_menu` VALUES (20, 16, '我的设置', 1, '/sys/setting');
INSERT INTO `tbl_auth_menu` VALUES (21, 16, '权限管理', 2, '/sys/auth');
INSERT INTO `tbl_auth_menu` VALUES (22, 16, '角色列表', 3, '/sys/role');
COMMIT;

我这里第一级目录的 父菜单 id (pid)使用的是 -1, 因为 id 默认是从 0开始的,使用0的话,这个菜单有可能不是第一级目录,而是 pid = 0 的二级目录了

  • 父菜单 id = 0
    • 子菜单 pid = 0 (pid=0,它就是二级目录了)

代码

文件 menu.go (使用 beego orm)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
type Menu struct {
	Id       int     `json:"id"`
	Pid      int     `json:"pid"`
	Name     string  `json:"name"`
	Sort     int     `json:"sort"`
	Route    string  `json:"route"`
	//这里是子菜单,结构是 menu数组,因为是menu类型,所以数据库不做处理
	// orm:"-"注解
	Children []*Menu `json:"children" orm:"-"`	
}

func (m *Menu) TableName() string {
	return "auth_menu"
}

在数据库层,注册模型

1
2
3
4
5
6
7
8
9
//注册 数据库的时候
//我这里数据库都使用了 tbl_ 前缀。 
//所以上面的数据库, return auth_menu 表名, 但是实际上使用的时候是 tbl_auth_menu , 这里一定要注意,
//写代码的时候,提示错误,数据库表 不存在这个的时候,记得来这里看看
func init() {
	orm.RegisterModelWithPrefix("tbl_",
		new(models.Menu),
	)
}

递归查询

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

/**
递归获取树形菜单
*/
//func (m *Menu) GetMenu(pid int) []*TreeList {
func GetMenu(pid int) []*Menu {
	o := orm.NewOrm()
	var menuList []*Menu
	//根据 pid 查询数据库
	_, _ = o.QueryTable("tbl_auth_menu").Filter("pid", pid).OrderBy("sort").All(&menuList)
	//查询到结果后,遍历该层菜单
	//查询都有哪些菜单是使用自己的id作为pid的
	//也就是查询该菜单的子菜单,查询到后赋值就可以了
	for _, v := range menuList {
		child := GetMenu(v.Id)
		v.Children = child
	}
	return menuList
}

api方法

1
2
3
4
5
6
7
8
9
// 获取所有部门
func (c *DepartmentController) GetAll() {
	//我方法写在了 models 包里,根据具体情况,引入包,
	//或者是同级包下,不写包名
	// -1  第一级部门  parentId
	departments := models.DepartmentGetAll(-1)
	c.Data["json"] = util.NewRespMsg(0, "获取部门成功", departments)
	c.ServeJSON()
}
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy