代码拉取完成,页面将自动刷新
package treenode
import (
"bytes"
"encoding/json"
"github.com/gogf/gf/v2/util/gconv"
)
// BuildTree 生成树形结构数据-不用查找节点
// 参数解析
// data:构建树的原始二维数组数据
// nodeId:从指定节点构建树
// Example:
//
// data := []interface{
// {Id: 1, Pid: 0, Name: ``},
// {Id: 2, Pid: 0, Name: ``},
// {Id: 3, Pid: 0, Name: ``},
// {Id: 4, Pid: 1, Name: ``},
// {Id: 5, Pid: 1, Name: ``},
// {Id: 6, Pid: 1, Name: ``},
// {Id: 7, Pid: 2, Name: ``},
// {Id: 8, Pid: 3, Name: ``},
// {Id: 9, Pid: 4, Name: ``},
// {Id: 10, Pid: 0, Name: ``},
// {Id: 11, Pid: 9, Name: ``},
// {Id: 12, Pid: 9, Name: ``},
// }
//
// New().BuildTrr(data)
// Output:[{"children":[{"children":[{"children":[{"children":[],"id":11,"is_show":0,"menu_type":0,"name":"","path":"","pid":9},{"children":[],"id":12,"is_show":0,"menu_type":0,"name":"","path":"","pid":9}],"id":9,"is_show":0,"menu_type":0,"name":"","path":"","pid":4}],"id":4,"is_show":0,"menu_type":0,"name":"","path":"","pid":1},{"children":[],"id":5,"is_show":0,"menu_type":0,"name":"","path":"","pid":1},{"children":[],"id":6,"is_show":0,"menu_type":0,"name":"","path":"","pid":1}],"id":1,"is_show":0,"menu_type":0,"name":"","path":"","pid":0},{"children":[{"children":[],"id":7,"is_show":0,"menu_type":0,"name":"","path":"","pid":2}],"id":2,"is_show":0,"menu_type":0,"name":"","path":"","pid":0},{"children":[{"children":[],"id":8,"is_show":0,"menu_type":0,"name":"","path":"","pid":3}],"id":3,"is_show":0,"menu_type":0,"name":"","path":"","pid":0},{"children":[],"id":10,"is_show":0,"menu_type":0,"name":"","path":"","pid":0}] <nil>
func (n *sTreeNode) BuildTree(data interface{}, nodeId ...uint) ([]map[string]interface{}, error) {
return n.BuildFindTreeNode(data, nil, nodeId...)
}
// BuildFindTreeNode 生成树形结构数据并查找树的节点
// 参数解析
// data:构建树的原始二维数组数据
// findNode:查找节点ID
// nodeId:从指定节点构建树
// Example:
//
// data := []interface{
// {Id: 1, Pid: 0, Name: ``},
// {Id: 2, Pid: 0, Name: ``},
// {Id: 3, Pid: 0, Name: ``},
// {Id: 4, Pid: 1, Name: ``},
// {Id: 5, Pid: 1, Name: ``},
// {Id: 6, Pid: 1, Name: ``},
// {Id: 7, Pid: 2, Name: ``},
// {Id: 8, Pid: 3, Name: ``},
// {Id: 9, Pid: 4, Name: ``},
// {Id: 10, Pid: 0, Name: ``},
// {Id: 11, Pid: 9, Name: ``},
// {Id: 12, Pid: 9, Name: ``},
// }
//
// New().BuildFindTreeNode(data, []uint{1, 5, 7, 8, 10})
// Output:[{"children":[{"children":[{"children":[{"children":[],"id":11,"is_show":0,"menu_type":0,"name":"","path":"","pid":9,"selected":0},{"children":[],"id":12,"is_show":0,"menu_type":0,"name":"","path":"","pid":9,"selected":0}],"id":9,"is_show":0,"menu_type":0,"name":"","path":"","pid":4,"selected":2}],"id":4,"is_show":0,"menu_type":0,"name":"","path":"","pid":1,"selected":2},{"children":[],"id":5,"is_show":0,"menu_type":0,"name":"","path":"","pid":1,"selected":1},{"children":[],"id":6,"is_show":0,"menu_type":0,"name":"","path":"","pid":1,"selected":1}],"id":1,"is_show":0,"menu_type":0,"name":"","path":"","pid":0,"selected":2},{"children":[{"children":[],"id":7,"is_show":0,"menu_type":0,"name":"","path":"","pid":2,"selected":0}],"id":2,"is_show":0,"menu_type":0,"name":"","path":"","pid":0,"selected":0},{"children":[{"children":[],"id":8,"is_show":0,"menu_type":0,"name":"","path":"","pid":3,"selected":0}],"id":3,"is_show":0,"menu_type":0,"name":"","path":"","pid":0,"selected":0},{"children":[],"id":10,"is_show":0,"menu_type":0,"name":"","path":"","pid":0,"selected":1}] <nil>
func (n *sTreeNode) BuildFindTreeNode(data interface{}, findNode []uint, nodeId ...uint) ([]map[string]interface{}, error) {
// 初始化生成父级树
nodeMaps, err := n.toParentNode(n.Maps(data))
if err != nil {
return nil, err
}
// 默认从根节点构建树
pid := nodeRootPid
if len(nodeId) > 0 {
pid = nodeId[0] // 可自定义从指定节点构建树
}
// 迭代生成子级树
nodes, _ := n.buildTreeHandler(nodeMaps, pid, n.MapUintBool(findNode))
return nodes, nil
}
// Maps 数据类型转换为MAP列表
func (n *sTreeNode) Maps(node interface{}) []map[string]interface{} {
buff, err := json.Marshal(node)
if err != nil {
return nil
}
// 格式化MAP
var nodes []map[string]interface{}
if err = json.NewDecoder(bytes.NewBuffer(buff)).Decode(&nodes); err != nil {
return nil
}
return nodes
}
// MapUintBool 转换已经勾选中的ID为MAP
func (n *sTreeNode) MapUintBool(selectedId []uint) map[uint]bool {
// 为nil不进行查找节点
if selectedId == nil {
return nil
}
// 数据为空-也继续查找数据
selectMap := make(map[uint]bool, len(selectedId))
if len(selectedId) == 0 {
return selectMap
}
// 迭代为转换MAP
for _, id := range selectedId {
selectMap[id] = true
}
return selectMap
}
// buildTreeHandler 处理并生成树形结构数据
func (n *sTreeNode) buildTreeHandler(nodeMaps map[uint][]map[string]interface{}, pid uint, findNode map[uint]bool) ([]map[string]interface{}, int) {
// 勾选子层级数量,计算子层级是否完成了全部勾选
var count int
// 取出当前节点的树层
nodes, ok := nodeMaps[pid]
if !ok {
return []map[string]interface{}{}, count
}
// 迭代查找子级树
for _, node := range nodes {
id := gconv.Uint(node[n.idColumn])
// 迭代子级
children, countChildSelected := n.buildTreeHandler(nodeMaps, id, findNode)
// 设置子树层级和选中规则
node[n.childrenColumn] = children
// 处理是否勾选数据
count = n.nodeSelectedHandler(selectedNode{
count: countChildSelected,
findNode: findNode,
countChild: len(children),
id: id,
}, &node)
}
// 返回数据
return nodes, count
}
// nodeSelectedHandler 查找节点是否勾选处理
func (n *sTreeNode) nodeSelectedHandler(item selectedNode, node *map[string]interface{}) int {
if item.findNode == nil {
return 0
}
var (
selectedFlag bool
selected = selectedNot
)
// 当前层级(父级)是否已勾选中
_, selectedFlag = item.findNode[item.id]
if item.count == -1 || (item.countChild > 0 && item.countChild > item.count && selectedFlag) {
// 若是子级返回-1,则父级为部分勾选,向上传递
selected = selectedPartial
if item.count >= 0 {
item.count = -1 // 子级存在不完全勾选,则所有上级(父级、祖父级。。。)都设置未部分勾选,向上传递
}
} else if selectedFlag {
// 子级勾选
selected = selectedUp
item.count += 1 // 累计此层勾选中数量
}
// 设置是否选择
if node != nil {
// 解引用指针创建Map传递指针的副本复值选中字段
(*node)[n.selectedColumn] = selected
}
return item.count
}
// toParentNode 转换树形结构数据为父级ID集合二维数组
func (n *sTreeNode) toParentNode(nodes []map[string]interface{}) (map[uint][]map[string]interface{}, error) {
nodeMaps := make(map[uint][]map[string]interface{})
if len(nodes) == 0 {
return nodeMaps, nil
}
// 迭代把二维数组转换为父级ID集合的二维数组
for _, node := range nodes {
// 字段检测
if err := n.IsField(node); err != nil {
return nil, err
}
pid := gconv.Uint(node[n.pidColumn])
nodeMaps[pid] = append(nodeMaps[pid], node)
}
return nodeMaps, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。