diff --git a/src/catalogue/demos/async.tsx b/src/catalogue/demos/async.tsx index 2c1e5de37..e87e9c101 100644 --- a/src/catalogue/demos/async.tsx +++ b/src/catalogue/demos/async.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; import { Catalogue } from 'dt-react-component'; import { useTreeData } from 'dt-react-component/catalogue/useTreeData'; -import { insertChildIntoNode } from 'dt-react-component/catalogue/utils'; +import { insertChildrenToNode } from 'dt-react-component/catalogue/utils'; interface DataNode { title: string; @@ -30,7 +30,7 @@ const App: React.FC = () => { return; } setTimeout(() => { - const newData = insertChildIntoNode(treeData.data, key, [ + const newData = insertChildrenToNode(treeData.data, key, [ { title: 'Child Node', key: `${key}-0` }, { title: 'Child Node', key: `${key}-1` }, ]); diff --git a/src/catalogue/demos/config.tsx b/src/catalogue/demos/config.tsx index 5947e9180..38047945d 100644 --- a/src/catalogue/demos/config.tsx +++ b/src/catalogue/demos/config.tsx @@ -8,9 +8,9 @@ import { cloneDeep } from 'lodash-es'; import shortid from 'shortid'; import { - appendNodeByKey, findNodeByKey, findParentNodeByKey, + insertChildrenToNode, removeEditNode, removeNodeByKey, updateTreeNodeEdit, @@ -83,7 +83,13 @@ export default () => { const handleAdd = (key: ITreeNode['key']) => { const newExpandedKeys = treeData.expandedKeys ? [...treeData.expandedKeys] : []; - const data = appendNodeByKey(treeData.data, key); + const data = insertChildrenToNode(treeData.data, key, [ + { + key: 'new_', + title: '', + edit: true, + }, + ]); if (!newExpandedKeys?.includes(key)) { newExpandedKeys.push(key); } diff --git a/src/catalogue/demos/drag.tsx b/src/catalogue/demos/drag.tsx index 9d3c1e7d8..7a561b888 100644 --- a/src/catalogue/demos/drag.tsx +++ b/src/catalogue/demos/drag.tsx @@ -8,9 +8,9 @@ import { cloneDeep } from 'lodash-es'; import shortid from 'shortid'; import { - appendNodeByKey, findNodeByKey, findParentNodeByKey, + insertChildrenToNode, removeEditNode, removeNodeByKey, updateTreeNodeEdit, @@ -77,7 +77,9 @@ export default () => { const handleAdd = (key: ITreeNode['key']) => { const newExpandedKeys = treeData.expandedKeys ? [...treeData.expandedKeys] : []; - const data = appendNodeByKey(treeData.data, key); + const data = insertChildrenToNode(treeData.data, key, [ + { key: 'new_', title: '', edit: true }, + ]); if (!newExpandedKeys?.includes(key)) { newExpandedKeys.push(key); } diff --git a/src/catalogue/demos/operator.tsx b/src/catalogue/demos/operator.tsx index 8106f4778..de692182a 100644 --- a/src/catalogue/demos/operator.tsx +++ b/src/catalogue/demos/operator.tsx @@ -7,9 +7,9 @@ import { cloneDeep } from 'lodash-es'; import shortid from 'shortid'; import { - appendNodeByKey, findNodeByKey, findParentNodeByKey, + insertChildrenToNode, removeEditNode, removeNodeByKey, updateTreeNodeEdit, @@ -130,7 +130,9 @@ export default () => { const handleAdd = (key: ITreeNode['key']) => { const newExpandedKeys = treeData.expandedKeys ? [...treeData.expandedKeys] : []; - const data = appendNodeByKey(treeData.data, key); + const data = insertChildrenToNode(treeData.data, key, [ + { key: 'new_', title: '', edit: true }, + ]); if (!newExpandedKeys?.includes(key)) { newExpandedKeys.push(key); } diff --git a/src/catalogue/utils.tsx b/src/catalogue/utils.tsx index 42827a416..4588b8fa9 100644 --- a/src/catalogue/utils.tsx +++ b/src/catalogue/utils.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { FolderFilled, FolderOpenedFilled } from '@dtinsight/react-icons'; -import { CatalogueProps } from './components/catalogue'; import { ITreeNode } from './useTreeData'; export const getIcon: ITreeNode['icon'] = ({ selected, expanded }) => { @@ -15,12 +14,10 @@ export const getIcon: ITreeNode['icon'] = ({ selected, expanded }) => { }; /** - * @description 轮询 Tree 数据,赋值搜索标识和leafIcon + * @description 轮询 data 数据,赋值搜索标识和leafIcon */ -export const loopTree = >( - data: CatalogueProps['treeData'] -): CatalogueProps['treeData'] => { - return data?.map((item) => { +export const loopTree = >(data: ITreeNode[]): ITreeNode[] => + data?.map((item) => { if (item.children) { return { icon: getIcon, @@ -34,13 +31,12 @@ export const loopTree = >( children: undefined, }; }); -}; /** - * 查找 key 对应的节点 - * @param data 遍历的数组 - * @param key 当前 key 值 - * @returns 找到的对应节点 + * @description 查找 key 对应的节点 + * @param {ITreeNode[]} data - 遍历的数组 + * @param {ITreeNode['key']} key - 当前 key 值 + * @returns {ITreeNode | null}找到的对应节点 */ export const findNodeByKey = ( data: ITreeNode[], @@ -59,16 +55,16 @@ export const findNodeByKey = ( }; /** - * 更新 key 对应节点为编辑状态 - * @param data 遍历的数组 - * @param key 当前 key 值 - * @returns 更新之后 data + * @description 更新 key 对应节点为编辑状态 + * @param {ITreeNode[]} data - 遍历的数组 + * @param {ITreeNode['key']} key - 当前 key 值 + * @returns {ITreeNode[]} 更新之后 data */ export const updateTreeNodeEdit = ( data: ITreeNode[], key: ITreeNode['key'] -): ITreeNode[] => { - return data.map((node) => { +): ITreeNode[] => + data.map((node) => { if (node.key === key) { return { ...node, edit: true }; } @@ -77,13 +73,12 @@ export const updateTreeNodeEdit = ( } return node; }); -}; /** - * 查找 key 对应的父级节点 - * @param data 遍历的数组 - * @param key 当前 key 值 - * @returns 当前找到父级节点 + * @description 查找 key 对应的父级节点 + * @param {ITreeNode[]} data - 遍历的数组 + * @param {ITreeNode['key']} key - 当前 key 值 + * @returns {ITreeNode | null}当前找到父级节点 */ export const findParentNodeByKey = ( data: ITreeNode[], @@ -103,39 +98,16 @@ export const findParentNodeByKey = ( }; /** - * 在 key 节点中添加子节点 - * @param data 遍历的数组 - * @param key 当前 key 值 - * @returns 插入新数据之后的 data - */ -export const appendNodeByKey = ( - data: ITreeNode[], - key: ITreeNode['key'] -): ITreeNode[] => { - const newNode = { key: 'new_', title: '', edit: true }; - return data.map((node) => { - if (node.key === key) { - const updatedChildren = node.children ? [...node.children, newNode] : [newNode]; - return { ...node, children: updatedChildren }; - } - if (node.children) { - return { ...node, children: appendNodeByKey(node.children, key) }; - } - return node; - }); -}; - -/** - * 移除 key 节点 - * @param data 遍历的数组 - * @param key 当前 key 值 - * @returns 删除数据之后的 data + * @description 移除 key 节点 + * @param {ITreeNode[]} data - 遍历的数组 + * @param {ITreeNode['key']} key - 当前 key 值 + * @returns {ITreeNode[]} 删除数据之后的 data */ export const removeNodeByKey = ( data: ITreeNode[], key: ITreeNode['key'] -): ITreeNode[] => { - return data +): ITreeNode[] => + data .filter((node) => node.key !== key) .map((node) => { if (node.children) { @@ -146,46 +118,98 @@ export const removeNodeByKey = ( } return node; }); -}; /** - * 移除 edit 为 true 的节点 - * @param treeData - * @returns 移除之后的数据 + * @description 移除 edit 为 true 的节点 + * @param {ITreeNode[]} treeData - 遍历的数组 + * @returns {ITreeNode[]} 移除之后的数据 */ export const removeEditNode = ( treeData: ITreeNode[] -): ITreeNode[] => { - return treeData +): ITreeNode[] => + treeData .filter((node) => !node.edit) .map((node) => ({ ...node, children: node.children ? removeEditNode(node.children) : undefined, })); -}; /** - * + * @description 在指定节点的子节点列表中添加一组子节点,可以选择添加在开头或结尾 + * @param {ITreeNode[]} treeData - 要操作的树节点数组 + * @param {ITreeNode['key']} key - 要添加子节点的目标节点 key + * @param {ITreeNode[]} children - 要添加的子节点数组 + * @param {boolean} [insertBefore=true] - 是否将子节点添加到现有子节点之前,true 表示添加到开头,false 表示添加到结尾 + * @returns {ITreeNode[]} 更新后的树节点数组 */ - -export const insertChildIntoNode = ( +export const insertChildrenToNode = ( treeData: ITreeNode[], key: ITreeNode['key'], - children: ITreeNode[] -): ITreeNode[] => { - return treeData.map((node) => { + children: ITreeNode[], + insertBefore = true +): ITreeNode[] => + treeData.map((node) => { if (node.key === key) { + const updatedChildren = insertBefore + ? [...children, ...(node.children || [])] + : [...(node.children || []), ...children]; return { ...node, - children, + children: node.children ? updatedChildren : children, }; } if (node.children) { return { ...node, - children: insertChildIntoNode(node.children, key, children), + children: insertChildrenToNode(node.children, key, children, insertBefore), }; } return node; }); + +/** + * @description 在树节点数组中查找指定 key 的节点索引 + * @param {ITreeNode[]} treeData - 要搜索的树节点数组 + * @param {ITreeNode['key']} key - 要查找的节点 key + * @returns {number} 找到的节点索引,如果未找到则返回 -1 + */ +export const findChildIndex = ( + data: ITreeNode[], + key: ITreeNode['key'] +): number => data.findIndex((item) => item.key === key); + +/** + * @description 在树节点数组中,根据指定的 key 找到目标节点,并将新节点插入到目标节点之前或之后。 + * @param {ITreeNode[]} treeData - 要操作的树节点数组。 + * @param {ITreeNode['key']} currentKey - 目标节点的 key。 + * @param {ITreeNode} node - 要插入的新节点。 + * @param {boolean} [insertBefore=true] - 是否将新节点插入到目标节点之前。true 表示之前,false 表示之后。 + * @returns {ITreeNode[]} 更新后的树节点数组。 + */ +export const insertNodeAtKey = ( + treeData: ITreeNode[], + currentKey: ITreeNode['key'], + node: ITreeNode, + insertBefore = true +): ITreeNode[] => { + const newTreeData: ITreeNode[] = []; + for (const item of treeData) { + if (item.key === currentKey) { + if (insertBefore) { + newTreeData.push(node); + newTreeData.push(item); + } else { + newTreeData.push(item); + newTreeData.push(node); + } + } else { + newTreeData.push({ + ...item, + children: item.children + ? insertNodeAtKey(item.children, currentKey, node, insertBefore) + : item.children, + }); + } + } + return newTreeData; };