import { Input, Tree } from "antd"; import { useEffect, useState } from "react"; const { Search } = Input; /** * 基础左侧树组件(不建议直接使用此组件,二次继承使用) */ const BasicLeftTree = (props) => { const { onSelect, onGetNodePaths, onGetNodePathsIsIncludeOneself = true, expandedKeys: externalExpandedKeys, treeData = [], nameKey = "name", idKey = "id", childrenKey = "childrenList", ...restProps } = props; const [expandedKeys, setExpandedKeys] = useState([]); const [searchValue, setSearchValue] = useState(""); const [autoExpandParent, setAutoExpandParent] = useState(true); useEffect(() => { setExpandedKeys(externalExpandedKeys); }, [externalExpandedKeys]); // 展开所有包含匹配项的父节点 const getAllExpandedKeys = (data, searchValue, keys = []) => { data.forEach((node) => { if (node[childrenKey]) { if (node[nameKey].includes(searchValue) || node[childrenKey].some(child => child[nameKey].includes(searchValue))) { keys.push(node[idKey]); } getAllExpandedKeys(node[childrenKey], searchValue, keys); } }); return keys; }; // 过滤树数据,只保留匹配的节点 const filterTreeData = (data, searchValue) => { if (!searchValue) { return data; } return data.reduce((acc, node) => { // 检查当前节点是否匹配 const isMatch = node[nameKey].includes(searchValue); // 递归处理子节点 const filteredChildren = node[childrenKey] ? filterTreeData(node[childrenKey], searchValue) : []; // 如果当前节点匹配或者有匹配的子节点,则保留该节点 if (isMatch || filteredChildren.length > 0) { acc.push({ ...node, [childrenKey]: filteredChildren.length > 0 ? filteredChildren : undefined, }); } return acc; }, []); }; const handleExpand = (newExpandedKeys) => { setExpandedKeys(newExpandedKeys); setAutoExpandParent(false); }; const getNodePaths = (data, targetId, idKey, childrenKey, path = [], isIncludeOneself) => { for (let i = 0; i < data.length; i++) { const node = data[i]; const newPath = [...path, node]; // 找到目标节点,根据isIncludeOneself决定是否包含自身 if (node[idKey] === targetId) { if (isIncludeOneself) return newPath; // 包含自身 else return path; // 不包含自身,只返回父节点路径 } // 递归查找子节点 if (node[childrenKey] && node[childrenKey].length > 0) { const result = getNodePaths(node[childrenKey], targetId, idKey, childrenKey, newPath, isIncludeOneself); if (result) { return result; } } } return null; }; const handleSelect = (selectedKeys, event) => { if (selectedKeys.length > 0) { const selectedNodeId = selectedKeys[0]; const parentNodes = getNodePaths(treeData, selectedNodeId, idKey, childrenKey, onGetNodePathsIsIncludeOneself); onGetNodePaths?.(parentNodes); } onSelect?.(selectedKeys, event); }; const onFilterTreeData = (value) => { setSearchValue(value); setAutoExpandParent(true); if (!value) { setExpandedKeys([]); return; } const expandedKeys = getAllExpandedKeys(treeData, value); setExpandedKeys(expandedKeys); }; const onSearch = async (value) => { if (value === searchValue) return; onFilterTreeData(value); }; // 渲染带高亮的标题 const renderTitle = (name) => { if (!searchValue) return name; const index = name.indexOf(searchValue); if (index === -1) return name; const beforeStr = name.substring(0, index); const afterStr = name.substring(index + searchValue.length); return ( {beforeStr} {searchValue} {afterStr} ); }; // 递归处理树节点标题显示 const processTreeData = (data) => { return data.map(node => ({ ...node, [nameKey]: renderTitle(node[nameKey]), [childrenKey]: node[childrenKey] ? processTreeData(node[childrenKey]) : undefined, })); }; // 过滤并处理树数据 const filteredTreeData = filterTreeData(treeData, searchValue); const processedTreeData = processTreeData(filteredTreeData); return (