From fc7ea534b7ee6bfba2ffd147c41f08bc793a566c Mon Sep 17 00:00:00 2001 From: Your Name <2499342078@qq.com> Date: Wed, 9 Jul 2025 11:02:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=B0=E5=A2=9E=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E5=86=92=E6=B3=A1=E5=8F=8A=E6=90=9C=E7=B4=A2=E5=B1=95?= =?UTF-8?q?=E5=BC=80=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/devicepage/select/Device-manager.tsx | 226 ++++++++++++++---- .../main/devicepage/select/Device-select.tsx | 21 +- config/nginx/conf.d/web.conf | 4 +- 3 files changed, 198 insertions(+), 53 deletions(-) diff --git a/apps/web/src/app/main/devicepage/select/Device-manager.tsx b/apps/web/src/app/main/devicepage/select/Device-manager.tsx index ae75543..21a499b 100755 --- a/apps/web/src/app/main/devicepage/select/Device-manager.tsx +++ b/apps/web/src/app/main/devicepage/select/Device-manager.tsx @@ -43,6 +43,7 @@ export default function DeviceManager({ title }: TermManagerProps) { const [pageSize, setPageSize] = useState(10); const [currentPage, setCurrentPage] = useState(1); const [expandedRowKeys, setExpandedRowKeys] = useState([]); + const [lastExpandedKeys, setLastExpandedKeys] = useState([]); // 新增:保存最后的展开状态 // ... 保持原有的 API 调用和逻辑 ... @@ -119,8 +120,8 @@ export default function DeviceManager({ title }: TermManagerProps) { useEffect(() => { if (networkTypeTerms && systemTypeTerms && deviceTypeTerms) { if (!searchValue) { - // 清空展开状态 - setExpandedRowKeys([]); + // 恢复到最后保存的展开状态 + setExpandedRowKeys(lastExpandedKeys); // 构建正常显示的完整树形结构 const buildNetworkTypeTree = (items: any[]): any[] => { @@ -207,7 +208,7 @@ export default function DeviceManager({ title }: TermManagerProps) { const finalTreeData = addSystemAndFaultTypes(networkTypeTree); setTreeData(finalTreeData); } else { - // 搜索逻辑 + // 搜索逻辑:构建完整树结构,但只显示匹配项及其路径 const searchTerm = searchValue.toLowerCase().trim(); const allTerms = [...networkTypeTerms, ...systemTypeTerms, ...deviceTypeTerms]; @@ -222,8 +223,8 @@ export default function DeviceManager({ title }: TermManagerProps) { return; } - // 找到需要展开的所有祖先节点 - const findAllAncestors = (termId: string): string[] => { + // 找到所有匹配项的祖先节点 + const findAncestors = (termId: string): string[] => { const ancestors: string[] = []; let currentTerm = allTerms.find(t => t.id === termId); @@ -235,58 +236,187 @@ export default function DeviceManager({ title }: TermManagerProps) { return ancestors; }; - // 收集所有需要展开的节点 - const expandKeys = new Set(); - const relevantTermIds = new Set(); - + // 收集需要显示的节点(匹配项 + 祖先节点) + const visibleNodes = new Set(); matchedTerms.forEach(matched => { - relevantTermIds.add(matched.id); - const ancestors = findAllAncestors(matched.id); - ancestors.forEach(ancestorId => { - expandKeys.add(ancestorId); - relevantTermIds.add(ancestorId); + visibleNodes.add(matched.id); + findAncestors(matched.id).forEach(ancestorId => { + visibleNodes.add(ancestorId); }); }); - // 只保留相关的项目来构建搜索结果树 - const relevantTerms = allTerms.filter(term => relevantTermIds.has(term.id)); + // 构建完整的树形结构,但添加可见性标记 + const buildCompleteTreeWithVisibility = (): any[] => { + // 先按照原有逻辑构建完整的树形结构 + const buildNetworkTypeTree = (items: any[]): any[] => { + const itemMap = new Map(items.map(item => [item.id, { ...item, children: [] }])); + const roots: any[] = []; - // 构建搜索结果的树形结构 - const buildSearchTree = (items: any[]): any[] => { - const itemMap = new Map(); - - // 初始化所有相关项 - items.forEach(item => { - itemMap.set(item.id, { - ...item, - key: item.id, - children: [], - isMatched: matchedTerms.some(m => m.id === item.id) + items.forEach(item => { + const treeItem = itemMap.get(item.id); + if (item.parentId && itemMap.has(item.parentId)) { + const parent = itemMap.get(item.parentId); + parent.children.push(treeItem); + } else { + roots.push(treeItem); + } }); - }); - const roots: any[] = []; + return roots; + }; - // 建立父子关系 - items.forEach(item => { - const treeItem = itemMap.get(item.id); - if (item.parentId && itemMap.has(item.parentId)) { - const parent = itemMap.get(item.parentId); - parent.children.push(treeItem); - } else { - roots.push(treeItem); - } - }); + const addSystemAndFaultTypes = (networkTypeTree: any[]): any[] => { + return networkTypeTree.map(networkType => { + const systemChildren = systemTypeTerms.filter( + (t) => t.parentId === networkType.id + ); - return roots; + const buildSystemTypeTree = (systemTypes: any[]): any[] => { + return systemTypes.map((systemType) => { + const childSystemTypes = systemTypeTerms.filter( + (t) => t.parentId === systemType.id && t.taxonomyId === systemTypeTaxonomy?.id + ); + + const faultTypes = deviceTypeTerms.filter( + (t) => t.parentId === systemType.id + ); + + const processedChildSystems = childSystemTypes.length > 0 + ? buildSystemTypeTree(childSystemTypes) + : []; + + const processedFaultTypes = faultTypes.map((fault) => ({ + ...fault, + key: fault.id, + isMatched: matchedTerms.some(m => m.id === fault.id), + isVisible: visibleNodes.has(fault.id), + })); + + return { + ...systemType, + key: systemType.id, + isMatched: matchedTerms.some(m => m.id === systemType.id), + isVisible: visibleNodes.has(systemType.id), + children: [ + ...processedChildSystems, + ...processedFaultTypes + ], + }; + }); + }; + + const processedSystemChildren = buildSystemTypeTree(systemChildren); + + let processedChildNetworkTypes: any[] = []; + if (networkType.children && networkType.children.length > 0) { + processedChildNetworkTypes = addSystemAndFaultTypes(networkType.children); + } + + const allChildren = [ + ...processedChildNetworkTypes, + ...processedSystemChildren + ]; + + return { + ...networkType, + key: networkType.id, + isMatched: matchedTerms.some(m => m.id === networkType.id), + isVisible: visibleNodes.has(networkType.id), + children: allChildren, + }; + }); + }; + + const networkTypeTree = buildNetworkTypeTree(networkTypeTerms); + return addSystemAndFaultTypes(networkTypeTree); }; - const searchResultTree = buildSearchTree(relevantTerms); - setTreeData(searchResultTree); - setExpandedRowKeys(Array.from(expandKeys)); + // 过滤树结构,只保留可见的节点 + const filterVisibleNodes = (nodes: any[]): any[] => { + return nodes + .filter(node => node.isVisible) + .map(node => ({ + ...node, + children: node.children ? filterVisibleNodes(node.children) : [] + })); + }; + + // 构建完整树结构 + const completeTree = buildCompleteTreeWithVisibility(); + // 过滤只显示可见节点 + const filteredTree = filterVisibleNodes(completeTree); + + setTreeData(filteredTree); + + // 自动展开有匹配子项的节点 + const autoExpandKeys = new Set(); + matchedTerms.forEach(matched => { + const ancestors = findAncestors(matched.id); + ancestors.forEach(ancestorId => autoExpandKeys.add(ancestorId)); + }); + + setExpandedRowKeys(Array.from(autoExpandKeys)); } } - }, [networkTypeTerms, systemTypeTerms, deviceTypeTerms, searchValue, networkTypeTaxonomy, systemTypeTaxonomy, deviceTypeTaxonomy]); + }, [networkTypeTerms, systemTypeTerms, deviceTypeTerms, searchValue, networkTypeTaxonomy, systemTypeTaxonomy, deviceTypeTaxonomy, lastExpandedKeys]); + + // 添加一个自定义的展开处理函数 + const handleExpand = (expanded: boolean, record: any) => { + const key = record.key; + let newExpandedKeys = [...expandedRowKeys]; + + if (expanded) { + // 展开节点时,如果是搜索状态,需要动态加载完整的子节点 + if (searchValue) { + const allTerms = [...(networkTypeTerms || []), ...(systemTypeTerms || []), ...(deviceTypeTerms || [])]; + + // 更新treeData,为展开的节点添加所有子项 + const updateTreeDataWithAllChildren = (nodes: any[]): any[] => { + return nodes.map(node => { + if (node.key === key) { + // 找到当前节点的所有直接子项 + const allDirectChildren = allTerms.filter(term => term.parentId === node.id); + + // 为每个子项添加标记 + const enrichedChildren = allDirectChildren.map(child => ({ + ...child, + key: child.id, + isMatched: child.name.toLowerCase().includes(searchValue.toLowerCase()), + isVisible: true, + children: [] // 子项的子项会在后续展开时动态加载 + })); + + return { + ...node, + children: enrichedChildren + }; + } else if (node.children && node.children.length > 0) { + return { + ...node, + children: updateTreeDataWithAllChildren(node.children) + }; + } + return node; + }); + }; + + setTreeData(prevData => updateTreeDataWithAllChildren(prevData)); + } + + if (!newExpandedKeys.includes(key)) { + newExpandedKeys.push(key); + } + } else { + newExpandedKeys = newExpandedKeys.filter(k => k !== key); + } + + setExpandedRowKeys(newExpandedKeys); + + // 在非搜索状态下,更新最后的展开状态 + if (!searchValue) { + setLastExpandedKeys(newExpandedKeys); + } + }; const handleSearch = (value: string) => { setSearchValue(value); @@ -602,7 +732,7 @@ export default function DeviceManager({ title }: TermManagerProps) { dataSource={treeData} expandable={{ expandedRowKeys: expandedRowKeys, - onExpandedRowsChange: (keys) => setExpandedRowKeys(keys.map(key => String(key))), + onExpand: handleExpand, expandRowByClick: true, indentSize: 20, }} @@ -677,7 +807,7 @@ export default function DeviceManager({ title }: TermManagerProps) {