index.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package tree
  2. import "sort"
  3. // Tree uniformly defines the data structure of the menu tree, you can also customize other fields to add
  4. type Tree struct {
  5. Title string `json:"title"`
  6. Data interface{} `json:"data"`
  7. Leaf bool `json:"leaf"`
  8. Selected bool `json:"checked"`
  9. PartialSelected bool `json:"partiallySelected"`
  10. Children []Tree `json:"children"`
  11. }
  12. // INode Other structures of want to generate a menu tree and directly implement this interface
  13. type INode interface {
  14. GetTitle() string
  15. GetId() int
  16. GetPid() int
  17. GetData() interface{}
  18. IsRoot() bool
  19. }
  20. type INodes []INode
  21. func (nodes INodes) Len() int {
  22. return len(nodes)
  23. }
  24. func (nodes INodes) Swap(i, j int) {
  25. nodes[i], nodes[j] = nodes[j], nodes[i]
  26. }
  27. func (nodes INodes) Less(i, j int) bool {
  28. return nodes[i].GetId() < nodes[j].GetId()
  29. }
  30. // GenerateTree After the custom structure implements the INode interface, call this method to generate the tree structure
  31. // nodes need to generate tree nodes
  32. // selectedNode selected node after spanning tree
  33. // The tree structure object after menuTrees is successfully generated
  34. func (Tree) GenerateTree(nodes, selectedNodes []INode) (trees []Tree) {
  35. trees = []Tree{}
  36. // Define the top-level root and child nodes
  37. var roots, childs []INode
  38. for _, v := range nodes {
  39. if v.IsRoot() {
  40. // Determine the top-level root node
  41. roots = append(roots, v)
  42. }
  43. childs = append(childs, v)
  44. }
  45. for _, v := range roots {
  46. childTree := &Tree{
  47. Title: v.GetTitle(),
  48. Data: v.GetData(),
  49. }
  50. // Before recursion, confirm the selected state of childTree according to the parent node
  51. childTree.Selected = nodeSelected(v, selectedNodes, childTree.Children)
  52. // recursive
  53. recursiveTree(childTree, childs, selectedNodes)
  54. // After recursion, confirm the selected state of childTree according to the child node
  55. if !childTree.Selected {
  56. childTree.Selected = nodeSelected(v, selectedNodes, childTree.Children)
  57. }
  58. // After recursion, confirm the half-selected state of childTree according to the child nodes
  59. childTree.PartialSelected = nodePartialSelected(childTree.Children)
  60. // After recursion, confirm whether it is a leaf node according to the subsection
  61. childTree.Leaf = len(childTree.Children) == 0
  62. trees = append(trees, *childTree)
  63. }
  64. return
  65. }
  66. // recursiveTree recursively spanning tree structure
  67. // tree recursive tree object
  68. // nodes recursive nodes
  69. // selectedNodes selected nodes
  70. func recursiveTree(tree *Tree, nodes, selectedNodes []INode) {
  71. data := tree.Data.(INode)
  72. for _, v := range nodes {
  73. if v.IsRoot() {
  74. // If the current node is the top-level root node, skip
  75. continue
  76. }
  77. if data.GetId() == v.GetPid() {
  78. childTree := &Tree{
  79. Title: v.GetTitle(),
  80. Data: v.GetData(),
  81. }
  82. childTree.Selected = nodeSelected(v, selectedNodes, childTree.Children) || tree.Selected
  83. recursiveTree(childTree, nodes, selectedNodes)
  84. if !childTree.Selected {
  85. childTree.Selected = nodeSelected(v, selectedNodes, childTree.Children)
  86. }
  87. childTree.PartialSelected = nodePartialSelected(childTree.Children)
  88. childTree.Leaf = len(childTree.Children) == 0
  89. tree.Children = append(tree.Children, *childTree)
  90. }
  91. }
  92. }
  93. // FindRelationNode queries all parent nodes of nodes in nodes in allTree
  94. // nodes to query the child node array of the parent node
  95. // allTree all nodes array
  96. func (Tree) FindRelationNode(nodes, allNodes []INode) (respNodes []INode) {
  97. nodeMap := make(map[int]INode)
  98. for _, v := range nodes {
  99. recursiveFindRelationNode(nodeMap, allNodes, v, 0)
  100. }
  101. for _, v := range nodeMap {
  102. respNodes = append(respNodes, v)
  103. }
  104. sort.Sort(INodes(respNodes))
  105. return
  106. }
  107. // recursiveFindRelationNode recursively query related parent and child nodes
  108. // nodeMap query results are collected in the map
  109. // allNodes all nodes
  110. // node recursive node
  111. // t Recursive search type: 0 finds parent and child nodes; 1 only finds parent nodes; 2 only finds child nodes
  112. func recursiveFindRelationNode(nodeMap map[int]INode, allNodes []INode, node INode, t int) {
  113. nodeMap[node.GetId()] = node
  114. for _, v := range allNodes {
  115. if _, ok := nodeMap[v.GetId()]; ok {
  116. continue
  117. }
  118. // Find the parent node
  119. if t == 0 || t == 1 {
  120. if node.GetPid() == v.GetId() {
  121. nodeMap[v.GetId()] = v
  122. if v.IsRoot() {
  123. // When it is the top-level root node, no recursion
  124. continue
  125. }
  126. recursiveFindRelationNode(nodeMap, allNodes, v, 1)
  127. }
  128. }
  129. // Find child nodes
  130. if t == 0 || t == 2 {
  131. if node.GetId() == v.GetId() {
  132. nodeMap[v.GetId()] = v
  133. recursiveFindRelationNode(nodeMap, allNodes, v, 2)
  134. }
  135. }
  136. }
  137. }
  138. // nodeSelected determines the selected state of the node
  139. // node judges the node
  140. func nodeSelected(node INode, selectedNodes []INode, children []Tree) bool {
  141. for _, v := range selectedNodes {
  142. if node.GetId() == v.GetId() {
  143. // 1. If the current node exists in the selected node array
  144. return true
  145. }
  146. }
  147. if len(children) == 0 {
  148. // 2. Precondition 1 is not met, and there are no child nodes
  149. return false
  150. }
  151. selectedNum := 0
  152. for _, v := range children {
  153. if v.Selected {
  154. selectedNum++
  155. }
  156. }
  157. if selectedNum == len(children) {
  158. // The preconditions 1, 2 are not met, and all the child nodes are selected
  159. return true
  160. }
  161. return false
  162. }
  163. // nodePartialSelected judges the half-selected state of the node
  164. func nodePartialSelected(trees []Tree) bool {
  165. selectedNum := 0
  166. for _, v := range trees {
  167. if v.Selected {
  168. selectedNum++
  169. }
  170. }
  171. if selectedNum == len(trees) || selectedNum == 0 {
  172. // All child nodes are selected, or none of them are selected
  173. return false
  174. }
  175. return true
  176. }