Golang实战系列:实现无限级菜单(Echo框架)

menu 模型:

type Menu struct {
	Id        int    `gorm:"primary_key;AUTO_INCREMENT" json:"id"`
	Pid       int    `json:"pid"`                                    // 父级menu
	Label     string `gorm:"type:varchar(50);not null" json:"label"` // menu名称
	Sort      int    `json:"sort"`                                   // 排序值
	Path      string `gorm:"type:varchar(30);not null" json:"path"`  // 跳转路由
	Icon      string `gorm:"type:varchar(20);" json:"icon"`          // 图标
	Component string `gorm:"type:varchar(50);" json:"component"`     // 组件路径
}

插入几条记录(下面的icon、component为随意虚构,根据自己的环境对应设置即可):

# 有子菜单的一级菜单
INSERT INTO `menus` VALUES ('1', '0', '用户管理', '1', '/user', 'icon-users', '');
INSERT INTO `menus` VALUES ('2', '0', '实例管理', '1', '/instance', 'icon-instances', '');
# 二级菜单
INSERT INTO `menus` VALUES ('3', '1', '用户列表', '2', 'user', 'icon-user', 'views/user/user/index');
INSERT INTO `menus` VALUES ('4', '1', '角色列表', '2', 'role', 'icon-role', 'views/user/role/index');
INSERT INTO `menus` VALUES ('5', '1', '权限列表', '2', 'permission', 'icon-perm', 'views/user/permission/index');
INSERT INTO `menus` VALUES ('6', '2', '实例列表', '3', 'instance', 'icon-instance', 'views/instance/instance/index');
INSERT INTO `menus` VALUES ('7', '2', '集群列表', '3', 'cluster', 'icon-cluster', 'views/instance/cluster/index');
# 没有子菜单的一级菜单
INSERT INTO `menus` VALUES ('8', '0', '文档', '1', '/opsdoc', 'icon-doc', 'views/doc/index');

注意:如果没有父级菜单,则pid为0.

 

定义一个序列化数据的结构体:

type TreeList struct {
	Id        int         `json:"id"`
	Label     string      `json:"label"`
	Pid       int         `json:"pid"`
	Sort      int         `json:"sort"`
	Path      string      `json:"path"`
	Component string      `json:"component"`
	Icon      string      `json:"icon"`
	Children  []*TreeList `json:"children"`
}

定义一个response结构体,用于构造返回数据:

type DataRes struct {
	Data []*TreeList `json:"data"`
}

使用递归的方式构造树形菜单:

/*
递归获取树形菜单
*/
func getMenu(pid int) []*TreeList {

	var menu []model.Menu
	model.DB().Where("pid = ?", pid).Order("sort").Find(&menu)
	treeList := []*TreeList{}
	for _, v := range menu {
		child := getMenu(v.Id)
		node := &TreeList{
			Id:    v.Id,
			Name:  v.Name,
			Sort:  v.Sort,
			Route: v.Route,
			Pid:   v.Pid,
		}
		node.Children = child
		treeList = append(treeList, node)
	}
	return treeList
}

api方法:

func HandlerMenuListGet(c echo.Context) (err error) {
	treeList := getMenu(0)
	return c.JSON(200, DataRes{
		Data: treeList,
	})
}

 

最后调用接口返回的数据json格式:

{
    "data": [
        {
            "id": 1,
            "label": "用户管理",
            "pid": 0,
            "sort": 1,
            "path": "/user",
            "component": "",
            "icon": "icon-users",
            "children": [
                {
                    "id": 3,
                    "label": "用户列表",
                    "pid": 1,
                    "sort": 2,
                    "path": "user/user",
                    "component": "views/user/user/index",
                    "icon": "icon-user",
                    "children": []
                },
                {
                    "id": 4,
                    "label": "角色列表",
                    "pid": 1,
                    "sort": 2,
                    "path": "user/role",
                    "component": "views/user/role/index",
                    "icon": "icon-role",
                    "children": []
                },
                {
                    "id": 5,
                    "label": "权限列表",
                    "pid": 1,
                    "sort": 2,
                    "path": "user/permission",
                    "component": "views/user/permission/index",
                    "icon": "icon-perm",
                    "children": []
                }
            ]
        },
        {
            "id": 2,
            "label": "实例管理",
            "pid": 0,
            "sort": 1,
            "path": "/instance",
            "component": "",
            "icon": "icon-instances",
            "children": [
                {
                    "id": 6,
                    "label": "实例列表",
                    "pid": 2,
                    "sort": 3,
                    "path": "instance/instance",
                    "component": "views/instance/instance/index",
                    "icon": "icon-instance",
                    "children": []
                },
                {
                    "id": 7,
                    "label": "集群列表",
                    "pid": 2,
                    "sort": 3,
                    "path": "instance/cluster",
                    "component": "views/instance/cluster/index",
                    "icon": "icon-cluster",
                    "children": []
                }
            ]
        },
        {
            "id": 8,
            "label": "文档",
            "pid": 0,
            "sort": 1,
            "path": "/opsdoc",
            "component": "views/doc/index",
            "icon": "icon-doc",
            "children": []
        }
    ]
}

 

转载于:https://my.oschina.net/u/264284/blog/3101275

你可能感兴趣的:(Golang实战系列:实现无限级菜单(Echo框架))