useTree.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from '../types/tree';
  2. import type { Ref, ComputedRef } from 'vue';
  3. import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
  4. import { cloneDeep } from 'lodash-es';
  5. import { unref } from 'vue';
  6. import { forEach } from '/@/utils/helper/treeHelper';
  7. export function useTree(treeDataRef: Ref<TreeDataItem[]>, getFieldNames: ComputedRef<FieldNames>) {
  8. function getAllKeys(list?: TreeDataItem[]) {
  9. const keys: string[] = [];
  10. const treeData = list || unref(treeDataRef);
  11. const { key: keyField, children: childrenField } = unref(getFieldNames);
  12. if (!childrenField || !keyField) return keys;
  13. for (let index = 0; index < treeData.length; index++) {
  14. const node = treeData[index];
  15. keys.push(node[keyField]!);
  16. const children = node[childrenField];
  17. if (children && children.length) {
  18. keys.push(...(getAllKeys(children) as string[]));
  19. }
  20. }
  21. return keys as KeyType[];
  22. }
  23. // get keys that can be checked and selected
  24. function getEnabledKeys(list?: TreeDataItem[]) {
  25. const keys: string[] = [];
  26. const treeData = list || unref(treeDataRef);
  27. const { key: keyField, children: childrenField } = unref(getFieldNames);
  28. if (!childrenField || !keyField) return keys;
  29. for (let index = 0; index < treeData.length; index++) {
  30. const node = treeData[index];
  31. node.disabled !== true && node.selectable !== false && keys.push(node[keyField]!);
  32. const children = node[childrenField];
  33. if (children && children.length) {
  34. keys.push(...(getEnabledKeys(children) as string[]));
  35. }
  36. }
  37. return keys as KeyType[];
  38. }
  39. function getChildrenKeys(nodeKey: string | number, list?: TreeDataItem[]) {
  40. const keys: KeyType[] = [];
  41. const treeData = list || unref(treeDataRef);
  42. const { key: keyField, children: childrenField } = unref(getFieldNames);
  43. if (!childrenField || !keyField) return keys;
  44. for (let index = 0; index < treeData.length; index++) {
  45. const node = treeData[index];
  46. const children = node[childrenField];
  47. if (nodeKey === node[keyField]) {
  48. keys.push(node[keyField]!);
  49. if (children && children.length) {
  50. keys.push(...(getAllKeys(children) as string[]));
  51. }
  52. } else {
  53. if (children && children.length) {
  54. keys.push(...getChildrenKeys(nodeKey, children));
  55. }
  56. }
  57. }
  58. return keys as KeyType[];
  59. }
  60. // Update node
  61. function updateNodeByKey(key: string, node: TreeDataItem, list?: TreeDataItem[]) {
  62. if (!key) return;
  63. const treeData = list || unref(treeDataRef);
  64. const { key: keyField, children: childrenField } = unref(getFieldNames);
  65. if (!childrenField || !keyField) return;
  66. for (let index = 0; index < treeData.length; index++) {
  67. const element: any = treeData[index];
  68. const children = element[childrenField];
  69. if (element[keyField] === key) {
  70. treeData[index] = { ...treeData[index], ...node };
  71. break;
  72. } else if (children && children.length) {
  73. updateNodeByKey(key, node, element[childrenField]);
  74. }
  75. }
  76. }
  77. // Expand the specified level
  78. function filterByLevel(level = 1, list?: TreeDataItem[], currentLevel = 1) {
  79. if (!level) {
  80. return [];
  81. }
  82. const res: (string | number)[] = [];
  83. const data = list || unref(treeDataRef) || [];
  84. for (let index = 0; index < data.length; index++) {
  85. const item = data[index];
  86. const { key: keyField, children: childrenField } = unref(getFieldNames);
  87. const key = keyField ? item[keyField] : '';
  88. const children = childrenField ? item[childrenField] : [];
  89. res.push(key);
  90. if (children && children.length && currentLevel < level) {
  91. currentLevel += 1;
  92. res.push(...filterByLevel(level, children, currentLevel));
  93. }
  94. }
  95. return res as string[] | number[];
  96. }
  97. /**
  98. * 添加节点
  99. */
  100. function insertNodeByKey({ parentKey = null, node, push = 'push' }: InsertNodeParams) {
  101. const treeData: any = cloneDeep(unref(treeDataRef));
  102. if (!parentKey) {
  103. treeData[push](node);
  104. treeDataRef.value = treeData;
  105. return;
  106. }
  107. const { key: keyField, children: childrenField } = unref(getFieldNames);
  108. if (!childrenField || !keyField) return;
  109. forEach(treeData, (treeItem) => {
  110. if (treeItem[keyField] === parentKey) {
  111. treeItem[childrenField] = treeItem[childrenField] || [];
  112. treeItem[childrenField][push](node);
  113. return true;
  114. }
  115. });
  116. treeDataRef.value = treeData;
  117. }
  118. /**
  119. * 批量添加节点
  120. */
  121. function insertNodesByKey({ parentKey = null, list, push = 'push' }: InsertNodeParams) {
  122. const treeData: any = cloneDeep(unref(treeDataRef));
  123. if (!list || list.length < 1) {
  124. return;
  125. }
  126. if (!parentKey) {
  127. for (let i = 0; i < list.length; i++) {
  128. treeData[push](list[i]);
  129. }
  130. treeDataRef.value = treeData;
  131. return;
  132. } else {
  133. const { key: keyField, children: childrenField } = unref(getFieldNames);
  134. if (!childrenField || !keyField) return;
  135. forEach(treeData, (treeItem) => {
  136. if (treeItem[keyField] === parentKey) {
  137. treeItem[childrenField] = treeItem[childrenField] || [];
  138. for (let i = 0; i < list.length; i++) {
  139. treeItem[childrenField][push](list[i]);
  140. }
  141. treeDataRef.value = treeData;
  142. return true;
  143. }
  144. });
  145. }
  146. }
  147. // Delete node
  148. function deleteNodeByKey(key: string, list?: TreeDataItem[]) {
  149. if (!key) return;
  150. const treeData = list || unref(treeDataRef);
  151. const { key: keyField, children: childrenField } = unref(getFieldNames);
  152. if (!childrenField || !keyField) return;
  153. for (let index = 0; index < treeData.length; index++) {
  154. const element: any = treeData[index];
  155. const children = element[childrenField];
  156. if (element[keyField] === key) {
  157. treeData.splice(index, 1);
  158. break;
  159. } else if (children && children.length) {
  160. deleteNodeByKey(key, element[childrenField]);
  161. }
  162. }
  163. }
  164. // Get selected node
  165. function getSelectedNode(key: KeyType, list?: TreeItem[], selectedNode?: TreeItem | null) {
  166. if (!key && key !== 0) return null;
  167. const treeData = list || unref(treeDataRef);
  168. const { key: keyField, children: childrenField } = unref(getFieldNames);
  169. if (!keyField) return;
  170. treeData.forEach((item) => {
  171. if (selectedNode?.key || selectedNode?.key === 0) return selectedNode;
  172. if (item[keyField] === key) {
  173. selectedNode = item;
  174. return;
  175. }
  176. if (item[childrenField!] && item[childrenField!].length) {
  177. selectedNode = getSelectedNode(key, item[childrenField!], selectedNode);
  178. }
  179. });
  180. return selectedNode || null;
  181. }
  182. return {
  183. deleteNodeByKey,
  184. insertNodeByKey,
  185. insertNodesByKey,
  186. filterByLevel,
  187. updateNodeByKey,
  188. getAllKeys,
  189. getChildrenKeys,
  190. getEnabledKeys,
  191. getSelectedNode,
  192. };
  193. }