tree.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /**
  2. 场景
  3. 树形数据过滤, 并保留原有树形结构不变, 即如果有子集被选中,父级同样保留。
  4. 思路
  5. 对数据进行处理,根据过滤标识对匹配的数据添加标识。如visible:true
  6. 对有标识的子集的父级添加标识visible:true
  7. 根据visible标识对数据进行递归过滤,得到最后的数据
  8. */
  9. import _ from 'lodash';
  10. export type TreeNode = {
  11. id: string;
  12. name: string;
  13. children: TreeNode[];
  14. visible?: boolean;
  15. } & Record<string, any>;
  16. /*
  17. * 对表格数据进行处理
  18. * data 树形数据数组
  19. * filter 过滤参数值
  20. * filterType 过滤参数名
  21. */
  22. export function treeFilter(data: TreeNode[], filter: string, filterType: string): TreeNode[] {
  23. const _data = _.cloneDeep(data);
  24. const traverse = (item: TreeNode[]) => {
  25. item.forEach((child) => {
  26. child.visible = filterMethod(filter, child, filterType);
  27. if (child.children) traverse(child.children);
  28. if (!child.visible && child.children?.length) {
  29. const visible = !child.children.some((c) => c.visible);
  30. child.visible = !visible;
  31. }
  32. });
  33. };
  34. traverse(_data);
  35. return filterDataByVisible(_data);
  36. }
  37. // 根据传入的值进行数据匹配, 并返回匹配结果
  38. function filterMethod(val: string, data: TreeNode, filterType: string | number) {
  39. return data[filterType].includes(val);
  40. }
  41. // 递归过滤符合条件的数据
  42. function filterDataByVisible(data: TreeNode[]) {
  43. return data.filter((item) => {
  44. if (item.children) {
  45. item.children = filterDataByVisible(item.children);
  46. }
  47. return item.visible;
  48. });
  49. }
  50. const mockData = [
  51. {
  52. children: [
  53. {
  54. children: [],
  55. name: '加',
  56. id: 'operator-1',
  57. },
  58. {
  59. children: [],
  60. name: '减',
  61. id: 'operator-2',
  62. },
  63. {
  64. children: [],
  65. name: '乘',
  66. id: 'operator-3',
  67. },
  68. {
  69. children: [],
  70. name: '除',
  71. id: 'operator-4',
  72. },
  73. {
  74. children: [],
  75. name: '括号',
  76. id: 'operator-5',
  77. },
  78. {
  79. children: [],
  80. name: '按位异或',
  81. id: 'operator-6',
  82. },
  83. ],
  84. name: '操作符',
  85. id: 'operator',
  86. },
  87. {
  88. children: [
  89. {
  90. children: [],
  91. name: 'if',
  92. id: 'if',
  93. },
  94. {
  95. children: [],
  96. name: 'for',
  97. id: 'for',
  98. },
  99. {
  100. children: [],
  101. name: 'while',
  102. id: 'while',
  103. },
  104. ],
  105. name: '控制语句',
  106. id: 'control',
  107. },
  108. ];
  109. const myTree = treeFilter(mockData, '操作', 'name');
  110. console.log(JSON.stringify(myTree), 'mytree');