golang
实现菜单树的生成,包括菜单节点的选中状态、半选中状态,菜单的搜索。
1 该包提供两个方法根接口
1.1 GenerateTree(nodes, selectedNodes []INode) (trees []Tree)
GenerateTreeINode
1.2 FindRelationNode(nodes, allNodes []INode) (respNodes []INode)
FindRelationNodeallTreenodesrespNodesnodes
1.3 接口 INode
// ConvertToINodeArray 其他的结构体想要生成菜单树,直接实现这个接口
type INode interface {// GetTitle 获取显示名字GetTitle() string// GetId获取idGetId() int// GetFatherId 获取父idGetFatherId() int// GetData 获取附加数据GetData() interface{}// IsRoot 判断当前节点是否是顶层根节点IsRoot() bool
}
2 使用
go get github.com/azhengyongqin/golang-tree-menu
INode
// 定义我们自己的菜单对象
type SystemMenu struct {Id int `json:"id"` //idFatherId int `json:"father_id"` //上级菜单idName string `json:"name"` //菜单名Route string `json:"route"` //页面路径Icon string `json:"icon"` //图标路径
}func (s SystemMenu) GetTitle() string {return s.Name
}
func (s SystemMenu) GetId() int {return s.Id
}
func (s SystemMenu) GetFatherId() int {return s.FatherId
}
func (s SystemMenu) GetData() interface{} {return s
}
func (s SystemMenu) IsRoot() bool {// 这里通过FatherId等于0 或者 FatherId等于自身Id表示顶层根节点return s.FatherId == 0 || s.FatherId == s.Id
}
SystemMenuINode
type SystemMenus []SystemMenu
// ConvertToINodeArray 将当前数组转换成父类 INode 接口 数组
func (s SystemMenus) ConvertToINodeArray() (nodes []INode) {for _, v := range s {nodes = append(nodes, v)}return
}
3 测试效果
3.1 添加测试数据
// 模拟获取数据库中所有菜单,在其它所有的查询中,也是首先将数据库中所有数据查询出来放到数组中,// 后面的遍历递归,都在这个 allMenu中进行,而不是在数据库中进行递归查询,减小数据库压力。allMenu := []SystemMenu{{Id: 1, FatherId: 0, Name: "系统总览", Route: "/systemOverview", Icon: "icon-system"},{Id: 2, FatherId: 0, Name: "系统配置", Route: "/systemConfig", Icon: "icon-config"},{Id: 3, FatherId: 1, Name: "资产", Route: "/asset", Icon: "icon-asset"},{Id: 4, FatherId: 1, Name: "动环", Route: "/pe", Icon: "icon-pe"},{Id: 5, FatherId: 2, Name: "菜单配置", Route: "/menuConfig", Icon: "icon-menu-config"},{Id: 6, FatherId: 3, Name: "设备", Route: "/device", Icon: "icon-device"},{Id: 7, FatherId: 3, Name: "机柜", Route: "/device", Icon: "icon-device"},}
3.2 生成完全树
// 生成完全树
resp := GenerateTree(SystemMenus.ConvertToINodeArray(allMenu), nil)
bytes, _ := json.MarshalIndent(resp, "", "\t")
fmt.Println(string(bytes))
[{"title": "系统总览","leaf": false,"checked": false,"partial_selected": false,"children": [{"title": "资产","leaf": false,"checked": false,"partial_selected": false,"children": [{"title": "设备","leaf": true,"checked": false,"partial_selected": false,"children": null}, {"title": "机柜","leaf": true,"checked": false,"partial_selected": false,"children": null}]}, {"title": "动环","leaf": true,"checked": false,"partial_selected": false,"children": null}]}, {"title": "系统配置","leaf": false,"checked": false,"partial_selected": false,"children": [{"title": "菜单配置","leaf": true,"checked": false,"partial_selected": false,"children": null}]}
]
3.3 带选中状态和半选中状态的树
// 模拟选中 '资产' 菜单
selectedNode := []SystemMenu{allMenu[2]}
resp = GenerateTree(SystemMenus.ConvertToINodeArray(allMenu), SystemMenus.ConvertToINodeArray(selectedNode))
bytes, _ = json.Marshal(resp)
fmt.Println(string(pretty.Color(pretty.PrettyOptions(bytes, pretty.DefaultOptions), nil)))
[{"title": "系统总览","leaf": false,"checked": false,"partial_selected": true,"children": [{"title": "资产","leaf": false,"checked": true,"partial_selected": false,"children": [{"title": "设备","leaf": true,"checked": true,"partial_selected": false,"children": null}, {"title": "机柜","leaf": true,"checked": true,"partial_selected": false,"children": null}]}, {"title": "动环","leaf": true,"checked": false,"partial_selected": false,"children": null}]}, {"title": "系统配置","leaf": false,"checked": false,"partial_selected": false,"children": [{"title": "菜单配置","leaf": true,"checked": false,"partial_selected": false,"children": null}]}
]
3.4 模拟查询某个节点,然后生成树
// 模拟从数据库中查询出 '设备'
device := []SystemMenu{allMenu[5]}
// 查询 `设备` 的所有父节点
respNodes := FindRelationNode(SystemMenus.ConvertToINodeArray(device), SystemMenus.ConvertToINodeArray(allMenu))
resp = GenerateTree(respNodes, nil)
bytes, _ = json.Marshal(resp)
fmt.Println(string(pretty.Color(pretty.PrettyOptions(bytes, pretty.DefaultOptions), nil)))
[{"title": "系统总览","leaf": false,"checked": false,"partial_selected": false,"children": [{"title": "资产","leaf": false,"checked": false,"partial_selected": false,"children": [{"title": "设备","leaf": true,"checked": false,"partial_selected": false,"children": null}]}]}
]
源码地址:https://github.com/azhengyongqin/golang-tree-menu