treeUtils.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // import type { AppRouteRecordRaw } from '/@/router/types';
  2. export interface TreeNode {
  3. id: number;
  4. parentId: number;
  5. name: string;
  6. key?: string;
  7. level?: string;
  8. children?: TreeNode[];
  9. }
  10. export interface TreeMenuNode {
  11. menuId: number;
  12. parentId: number;
  13. name: string;
  14. type?: number;
  15. id: number;
  16. children?: TreeMenuNode[];
  17. }
  18. // function traverse(tree: TreeMenuNode[], rootId: number) {
  19. // tree.forEach((item) => {
  20. // if (item.parentId == rootId) {
  21. // console.log('name', item.name);
  22. // console.log('menuId', item.menuId);
  23. // console.log('rootId', rootId);
  24. // // temp.push(item.parentId);
  25. // // item.key = temp;
  26. // }
  27. // if (item.children?.length) {
  28. // traverse(item.children, item.menuId);
  29. // }
  30. // });
  31. // }
  32. export function makeTree(treeNodes: TreeNode[]): TreeNode[] {
  33. // 提前生成节点查找表。
  34. // 如果明确节点是顺序可以保证先父后子,可以省去这次遍历,在后面边遍历过程中填充查找表
  35. const nodesMap = new Map<number, TreeNode>(treeNodes.map((node) => [node.id, node]));
  36. // 引入虚拟根节点来统一实现 parent 始终有效,避免空判断
  37. const virtualRoot = {} as Partial<TreeNode>;
  38. treeNodes.forEach((node) => {
  39. const parent = nodesMap.get(node.parentId) ?? virtualRoot;
  40. (parent.children ??= []).push(node);
  41. });
  42. // if (virtualRoot.children?.length) {
  43. // traverse(virtualRoot.children, virtualRoot.children[0].id);
  44. // }
  45. return virtualRoot.children ?? [];
  46. }
  47. export function getTreeId(treeNodes: TreeMenuNode[]): number[] {
  48. // 提前生成节点查找表。
  49. // 如果明确节点是顺序可以保证先父后子,可以省去这次遍历,在后面边遍历过程中填充查找表
  50. // const nodesMap = new Map<number, TreeNode>(treeNodes.map((node) => [node.id, node]));
  51. // 引入虚拟根节点来统一实现 parent 始终有效,避免空判断
  52. const TreeIdList: number[] = [];
  53. function getTreeIdList(list: TreeMenuNode[]) {
  54. return list.map((ele) => {
  55. if (ele.children && ele.children.length) {
  56. getTreeIdList(ele.children);
  57. } else {
  58. TreeIdList.push(ele.id);
  59. }
  60. });
  61. }
  62. getTreeIdList(treeNodes);
  63. console.log('TreeIdList', TreeIdList, treeNodes);
  64. return TreeIdList ?? [];
  65. }
  66. export function makeMenuTree(treeNodes: TreeMenuNode[]): TreeMenuNode[] {
  67. const nodesMap = new Map<number, TreeMenuNode>(treeNodes.map((node) => [node.menuId, node]));
  68. // 引入虚拟根节点来统一实现 parent 始终有效,避免空判断
  69. const virtualRoot = {} as Partial<TreeMenuNode>;
  70. treeNodes.forEach((node) => {
  71. const parent = nodesMap.get(node.parentId) ?? virtualRoot;
  72. (parent.children ??= []).push(node);
  73. });
  74. return virtualRoot.children ?? [];
  75. }
  76. /**
  77. * 递归修改文件树的字段名称
  78. * @param {Array|Object} tree - 文件树数据(数组/单个节点对象)
  79. * @param {Object} fieldMap - 字段名映射表 { 原字段名: 目标字段名 }
  80. * @returns {Array|Object} 修改后的文件树
  81. */
  82. export function renameTreeFields(tree, fieldMap) {
  83. // 边界条件:空值直接返回
  84. if (tree === null || typeof tree !== 'object') {
  85. return tree;
  86. }
  87. // 如果是数组,递归处理每个元素
  88. if (Array.isArray(tree)) {
  89. return tree.map((item) => renameTreeFields(item, fieldMap));
  90. }
  91. // 如果是对象,遍历所有键并替换
  92. const newNode = {
  93. ...tree,
  94. label: tree.nameSn,
  95. value: tree.code,
  96. // 替换字段名(如果在映射表中)
  97. [fieldMap['childrenList']]: renameTreeFields(tree.childrenList, fieldMap),
  98. // [fieldMap['children']]: renameTreeFields(tree.children, fieldMap),
  99. };
  100. return newNode;
  101. }