slice_tree.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package utils
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/container/garray"
  5. "github.com/gogf/gf/frame/g"
  6. "github.com/gogf/gf/util/gconv"
  7. "reflect"
  8. )
  9. // 有层级关系的数组,父级-》子级 排序
  10. func ParentSonSort(list g.List, params ...interface{}) g.List {
  11. args := make([]interface{}, 8)
  12. for k, v := range params {
  13. if k == 8 {
  14. break
  15. }
  16. args[k] = v
  17. }
  18. var (
  19. pid int //父级id
  20. level int //层级数
  21. fieldName string //父级id键名
  22. id string //id键名
  23. levelName string //层级名称
  24. title string //标题名称
  25. breaks int //中断层级
  26. prefixStr string //字符串前缀
  27. )
  28. pid = gconv.Int(GetSliceByKey(args, 0, 0))
  29. level = gconv.Int(GetSliceByKey(args, 1, 0))
  30. fieldName = gconv.String(GetSliceByKey(args, 2, "pid"))
  31. id = gconv.String(GetSliceByKey(args, 3, "id"))
  32. levelName = gconv.String(GetSliceByKey(args, 4, "flg"))
  33. title = gconv.String(GetSliceByKey(args, 5, "title"))
  34. breaks = gconv.Int(GetSliceByKey(args, 6, -1))
  35. prefixStr = gconv.String(GetSliceByKey(args, 7, "─"))
  36. //定义一个新slice用于返回
  37. var returnSlice g.List
  38. for _, v := range list {
  39. if pid == gconv.Int(v[fieldName]) {
  40. v[levelName] = level
  41. levelClone := level
  42. titlePrefix := ""
  43. for {
  44. if levelClone < 0 {
  45. break
  46. }
  47. titlePrefix += prefixStr
  48. levelClone--
  49. }
  50. titlePrefix = "├" + titlePrefix
  51. if level == 0 {
  52. v["title_prefix"] = ""
  53. } else {
  54. v["title_prefix"] = titlePrefix
  55. }
  56. v["title_show"] = fmt.Sprintf("%s%s", v["title_prefix"], v[title])
  57. returnSlice = append(returnSlice, v)
  58. if breaks != -1 && breaks == level {
  59. continue
  60. }
  61. args[0] = v[id]
  62. args[1] = level + 1
  63. newSlice2 := ParentSonSort(list, args...)
  64. if len(newSlice2) > 0 {
  65. returnSlice = append(returnSlice, newSlice2...)
  66. }
  67. }
  68. }
  69. return returnSlice
  70. }
  71. // 有层级关系的数组 ,将子级压入到父级(树形结构)
  72. func PushSonToParent(list g.List, params ...interface{}) g.List {
  73. args := make([]interface{}, 7)
  74. for k, v := range params {
  75. if k == 7 {
  76. break
  77. }
  78. args[k] = v
  79. }
  80. var (
  81. pid string //父级id
  82. fieldName string //父级id键名
  83. id string //id键名
  84. key string //子级数组键名
  85. filter string //过滤键名
  86. filterVal interface{} //过滤的值
  87. showNoChild bool //是否显示不存在的子级健
  88. )
  89. pid = gconv.String(GetSliceByKey(args, 0, 0))
  90. fieldName = gconv.String(GetSliceByKey(args, 1, "pid"))
  91. id = gconv.String(GetSliceByKey(args, 2, "id"))
  92. key = gconv.String(GetSliceByKey(args, 3, "children"))
  93. filter = gconv.String(GetSliceByKey(args, 4, ""))
  94. filterVal = GetSliceByKey(args, 5, nil)
  95. showNoChild = gconv.Bool(GetSliceByKey(args, 6, true))
  96. var returnList g.List
  97. for _, v := range list {
  98. if gconv.String(v[fieldName]) == pid {
  99. if filter != "" {
  100. if reflect.DeepEqual(v[filter], filterVal) {
  101. args[0] = v[id]
  102. child := PushSonToParent(list, args...)
  103. if child != nil || showNoChild {
  104. v[key] = child
  105. }
  106. returnList = append(returnList, v)
  107. }
  108. } else {
  109. args[0] = v[id]
  110. child := PushSonToParent(list, args...)
  111. if child != nil || showNoChild {
  112. v[key] = child
  113. }
  114. returnList = append(returnList, v)
  115. }
  116. }
  117. }
  118. return returnList
  119. }
  120. // 获取切片里的值 若为nil 可设置默认值val
  121. func GetSliceByKey(args []interface{}, key int, val interface{}) interface{} {
  122. var value interface{}
  123. if args[key] != nil {
  124. value = args[key]
  125. } else {
  126. value = val
  127. }
  128. return value
  129. }
  130. // 有层级关系的切片,通过父级id查找所有子级id数组
  131. // parentId 父级id
  132. // parentIndex 父级索引名称
  133. // idIndex id索引名称
  134. func FindSonByParentId(list g.List, parentId int, parentIndex, idIndex string) g.List {
  135. newList := make(g.List, 0, len(list))
  136. for _, v := range list {
  137. if gconv.Int(v[parentIndex]) == parentId {
  138. newList = append(newList, v)
  139. fList := FindSonByParentId(list, gconv.Int(v[idIndex]), parentIndex, idIndex)
  140. newList = append(newList, fList...)
  141. }
  142. }
  143. return newList
  144. }
  145. // 获取最顶层 parent Id
  146. func GetTopPidList(list g.List, parentIndex, idIndex string) *garray.Array {
  147. arr := garray.NewArray()
  148. for _, v1 := range list {
  149. tag := true
  150. for _, v2 := range list {
  151. if v1[parentIndex] == v2[idIndex] {
  152. tag = false
  153. break
  154. }
  155. }
  156. if tag {
  157. arr.PushRight(v1[parentIndex])
  158. }
  159. }
  160. return arr.Unique()
  161. }
  162. // 有层级关系的数组,通过子级fid查找所有父级数组
  163. func FindParentBySonPid(list g.List, id int, params ...interface{}) g.List {
  164. args := make([]interface{}, 4)
  165. for k, v := range params {
  166. if k == 4 {
  167. break
  168. }
  169. args[k] = v
  170. }
  171. var (
  172. filter = gconv.String(GetSliceByKey(args, 0, "filter")) //过滤键名
  173. fPid = gconv.String(GetSliceByKey(args, 1, "pid")) //父级id字段键名
  174. filterValue = GetSliceByKey(args, 2, nil) //过滤键值
  175. fid = gconv.String(GetSliceByKey(args, 3, "id")) //id字段键名
  176. )
  177. rList := make(g.List, 0, len(list))
  178. for _, v := range list {
  179. if gconv.Int(v[fid]) == id {
  180. if fv, ok := v[filter]; ok {
  181. if reflect.DeepEqual(fv, filterValue) {
  182. rList = append(rList, v)
  183. }
  184. } else {
  185. rList = append(rList, v)
  186. }
  187. r := FindParentBySonPid(list, gconv.Int(v[fPid]), filter, fPid, filterValue, fid)
  188. rList = append(rList, r...)
  189. }
  190. }
  191. return rList
  192. }
  193. /**
  194. * 根据id查询最顶层父级信息
  195. * @param list 有层级关系的数组
  196. * @param id 查找的id
  197. * @param string fpid 父级id键名
  198. * @param string fid 当前id键名
  199. * @return g.Map
  200. */
  201. func FindTopParent(list g.List, id int64, params ...interface{}) g.Map {
  202. if len(list) == 0 {
  203. return g.Map{}
  204. }
  205. args := make([]interface{}, 2)
  206. for k, v := range params {
  207. if k == 2 {
  208. break
  209. }
  210. args[k] = v
  211. }
  212. var (
  213. fPid = gconv.String(GetSliceByKey(args, 0, "pid")) //父级id字段键名
  214. fid = gconv.String(GetSliceByKey(args, 1, "id")) //id字段键名
  215. )
  216. hasParent := true
  217. top := g.Map{}
  218. //找到要查找id值的数组
  219. for _, v := range list {
  220. if gconv.Int64(v[fid]) == gconv.Int64(id) {
  221. top = v
  222. break
  223. }
  224. }
  225. for {
  226. if !hasParent {
  227. break
  228. }
  229. //查询最顶层
  230. for _, v := range list {
  231. if gconv.Int64(top[fPid]) == gconv.Int64(v[fid]) {
  232. top = v
  233. hasParent = true
  234. break
  235. }
  236. hasParent = false
  237. }
  238. }
  239. return top
  240. }