修改新增分类冒泡及搜索展开问题
This commit is contained in:
parent
395945271f
commit
fc7ea534b7
|
|
@ -43,6 +43,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
|||
const [pageSize, setPageSize] = useState(10);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]);
|
||||
const [lastExpandedKeys, setLastExpandedKeys] = useState<string[]>([]); // 新增:保存最后的展开状态
|
||||
|
||||
// ... 保持原有的 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,39 +236,22 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
|||
return ancestors;
|
||||
};
|
||||
|
||||
// 收集所有需要展开的节点
|
||||
const expandKeys = new Set<string>();
|
||||
const relevantTermIds = new Set<string>();
|
||||
|
||||
// 收集需要显示的节点(匹配项 + 祖先节点)
|
||||
const visibleNodes = new Set<string>();
|
||||
matchedTerms.forEach(matched => {
|
||||
relevantTermIds.add(matched.id);
|
||||
const ancestors = findAllAncestors(matched.id);
|
||||
ancestors.forEach(ancestorId => {
|
||||
expandKeys.add(ancestorId);
|
||||
relevantTermIds.add(ancestorId);
|
||||
});
|
||||
});
|
||||
|
||||
// 只保留相关的项目来构建搜索结果树
|
||||
const relevantTerms = allTerms.filter(term => relevantTermIds.has(term.id));
|
||||
|
||||
// 构建搜索结果的树形结构
|
||||
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)
|
||||
visibleNodes.add(matched.id);
|
||||
findAncestors(matched.id).forEach(ancestorId => {
|
||||
visibleNodes.add(ancestorId);
|
||||
});
|
||||
});
|
||||
|
||||
// 构建完整的树形结构,但添加可见性标记
|
||||
const buildCompleteTreeWithVisibility = (): any[] => {
|
||||
// 先按照原有逻辑构建完整的树形结构
|
||||
const buildNetworkTypeTree = (items: any[]): any[] => {
|
||||
const itemMap = new Map(items.map(item => [item.id, { ...item, children: [] }]));
|
||||
const roots: any[] = [];
|
||||
|
||||
// 建立父子关系
|
||||
items.forEach(item => {
|
||||
const treeItem = itemMap.get(item.id);
|
||||
if (item.parentId && itemMap.has(item.parentId)) {
|
||||
|
|
@ -281,12 +265,158 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
|||
return roots;
|
||||
};
|
||||
|
||||
const searchResultTree = buildSearchTree(relevantTerms);
|
||||
setTreeData(searchResultTree);
|
||||
setExpandedRowKeys(Array.from(expandKeys));
|
||||
const addSystemAndFaultTypes = (networkTypeTree: any[]): any[] => {
|
||||
return networkTypeTree.map(networkType => {
|
||||
const systemChildren = systemTypeTerms.filter(
|
||||
(t) => t.parentId === networkType.id
|
||||
);
|
||||
|
||||
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 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<string>();
|
||||
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) {
|
|||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => handleAdd(record)}
|
||||
onClick={(e) => {e.stopPropagation();handleAdd(record)}}
|
||||
className="text-green-600 hover:text-green-700 hover:bg-green-50"
|
||||
size="small"
|
||||
title="添加子项"
|
||||
|
|
@ -686,7 +816,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
|||
<Button
|
||||
type="text"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleEdit(record)}
|
||||
onClick={(e) => {e.stopPropagation();handleEdit(record)}}
|
||||
className="text-blue-600 hover:text-blue-700 hover:bg-blue-50"
|
||||
size="small"
|
||||
title="编辑"
|
||||
|
|
@ -695,7 +825,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
|||
type="text"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={() => handleDelete(record)}
|
||||
onClick={(e) => {e.stopPropagation();handleDelete(record)}}
|
||||
size="small"
|
||||
title="删除"
|
||||
className="hover:bg-red-50"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export default function DeviceTypeSelect({
|
|||
[]
|
||||
);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isInitialized, setIsInitialized] = useState(false); // 添加初始化标记
|
||||
|
||||
// 动态构建查询条件
|
||||
const whereCondition = {
|
||||
|
|
@ -43,15 +44,29 @@ export default function DeviceTypeSelect({
|
|||
// 使用 useRef 来跟踪之前的 systemTypeId
|
||||
const prevSystemTypeIdRef = useRef<string | undefined>(systemTypeId);
|
||||
|
||||
// 当系统类型改变时,清空当前选择
|
||||
// 当系统类型改变时,清空当前选择,只有在已初始化且用户主动更改时才清空
|
||||
useEffect(() => {
|
||||
if (prevSystemTypeIdRef.current !== systemTypeId) {
|
||||
prevSystemTypeIdRef.current = systemTypeId;
|
||||
if (onChange && value) {
|
||||
|
||||
// 只有在已初始化且有值的情况下才清空
|
||||
if (isInitialized && onChange && value) {
|
||||
onChange(undefined);
|
||||
}
|
||||
|
||||
// 标记为已初始化
|
||||
if (!isInitialized) {
|
||||
setIsInitialized(true);
|
||||
}
|
||||
}, [systemTypeId]);
|
||||
}
|
||||
}, [systemTypeId, isInitialized]);
|
||||
|
||||
// 当值变化时,重置初始化状态(用于新建场景)
|
||||
useEffect(() => {
|
||||
if (!value && !systemTypeId) {
|
||||
setIsInitialized(false);
|
||||
}
|
||||
}, [value, systemTypeId]);
|
||||
|
||||
// 处理选项数据
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ server {
|
|||
# 监听80端口
|
||||
listen 80;
|
||||
# 服务器域名/IP地址,使用环境变量
|
||||
server_name 192.168.77.194;
|
||||
server_name 192.168.142.194;
|
||||
|
||||
# 基础性能优化配置
|
||||
# 启用tcp_nopush以优化数据发送
|
||||
|
|
@ -100,7 +100,7 @@ server {
|
|||
# 仅供内部使用
|
||||
internal;
|
||||
# 代理到认证服务
|
||||
proxy_pass http://192.168.77.194:3000/auth/file;
|
||||
proxy_pass http://192.168.142.194:3000/auth/file;
|
||||
|
||||
# 请求优化:不传递请求体
|
||||
proxy_pass_request_body off;
|
||||
|
|
|
|||
Loading…
Reference in New Issue