feat(ideContainer): 添加菜单树展开/折叠全部功能

master
钟良源 2 months ago
parent dde9083fd5
commit 72b8a0f671

@ -20,7 +20,9 @@ import {
IconEye, IconEye,
IconSearch, IconSearch,
IconPlus, IconPlus,
IconEyeInvisible IconEyeInvisible,
IconExpand,
IconShrink
} from '@arco-design/web-react/icon'; } from '@arco-design/web-react/icon';
import { menuData1, menuData2 } from './config/menuData'; import { menuData1, menuData2 } from './config/menuData';
import { Selected } from '@/pages/ideContainer/types'; import { Selected } from '@/pages/ideContainer/types';
@ -210,6 +212,8 @@ const SideBar: React.FC<SideBarProps> = ({
const [hiddenNodes, setHiddenNodes] = useState<Set<string>>(new Set()); const [hiddenNodes, setHiddenNodes] = useState<Set<string>>(new Set());
// 用于控制展开的节点 // 用于控制展开的节点
const [expandedKeys, setExpandedKeys] = useState<string[]>(['0']); const [expandedKeys, setExpandedKeys] = useState<string[]>(['0']);
// 用于标记是否全部展开
const [isAllExpanded, setIsAllExpanded] = useState(false);
const resizeBoxRef = useRef<HTMLDivElement>(null); // 引用第一个 ResizeBox 容器 const resizeBoxRef = useRef<HTMLDivElement>(null); // 引用第一个 ResizeBox 容器
const contextMenuRef = useRef<HTMLDivElement>(null); // 右键菜单引用 const contextMenuRef = useRef<HTMLDivElement>(null); // 右键菜单引用
const { menuData, info, canvasDataMap } = useSelector(state => state.ideContainer); const { menuData, info, canvasDataMap } = useSelector(state => state.ideContainer);
@ -284,31 +288,70 @@ const SideBar: React.FC<SideBarProps> = ({
// 切换子菜单区域的收起/展开状态 // 切换子菜单区域的收起/展开状态
const toggleSubMenu = () => { const toggleSubMenu = () => {
setIsSubMenuCollapsed(!isSubMenuCollapsed); setIsSubMenuCollapsed(prev => !prev);
const width = isSubMenuCollapsed ? 300 : 0;
resizeBoxRef.current.style.width = `${width}px`;
}; };
// 监听子菜单收起/展开状态变化,更新宽度
useEffect(() => {
if (resizeBoxRef.current) {
const width = isSubMenuCollapsed ? 0 : 300;
resizeBoxRef.current.style.width = `${width}px`;
}
}, [isSubMenuCollapsed]);
// 获取所有可展开节点的 keys
const getAllExpandableKeys = useCallback((menuItems?: MenuItemType[], parentKey = '0'): string[] => {
const keys: string[] = [];
if (!menuItems || menuItems.length === 0) return keys;
menuItems.forEach((item, index) => {
const key = `${parentKey}-${index}`;
// 只有有子节点的才需要添加到展开列表
if (item.children && item.children.length > 0) {
keys.push(key);
// 递归获取子节点的 keys
keys.push(...getAllExpandableKeys(item.children, key));
}
});
return keys;
}, []);
// 切换展开/折叠全部
const toggleExpandAll = useCallback(() => {
if (isAllExpanded) {
// 折叠全部
setExpandedKeys([]);
setIsAllExpanded(false);
}
else {
// 展开全部
const allKeys = getAllExpandableKeys(filteredMenu[activeKey]?.children);
setExpandedKeys(allKeys);
setIsAllExpanded(true);
}
}, [isAllExpanded, activeKey, getAllExpandableKeys]);
// 处理菜单项点击事件 // 处理菜单项点击事件
const handleMenuItemClick = (item: MenuItemType, index: number) => { const handleMenuItemClick = (item: MenuItemType, index: number) => {
setActiveKey(index); setActiveKey(index);
if (showSubMenu) { if (showSubMenu) {
// 如果点击的是当前已激活的菜单项,则切换子菜单的展开/收起状态 // 如果点击的是当前已激活的菜单项,则切换子菜单的展开/收起状态
if (selected.key === `${item.key}`) { if ((selected?.parentKey || selected.key) === `${item.key}`) {
toggleSubMenu(); toggleSubMenu();
} }
else { else {
// 如果点击的是其他菜单项,则展开子菜单(如果已收起) // 如果点击的是其他菜单项,则展开子菜单(如果已收起)
if (isSubMenuCollapsed) { if (isSubMenuCollapsed) {
setIsSubMenuCollapsed(false); setIsSubMenuCollapsed(false);
resizeBoxRef.current.style.width = `300px`;
} }
} }
} }
// 调用外部传入的菜单选择处理函数 // 调用外部传入的菜单选择处理函数
onMenuSelect?.({ ...item }); // 单独针对这个title过滤
if (item.title !== '应用列表') onMenuSelect?.({ ...item });
}; };
// 监听 selected 状态变化,更新 activeKey // 监听 selected 状态变化,更新 activeKey
@ -327,11 +370,10 @@ const SideBar: React.FC<SideBarProps> = ({
if (selected?.key && menuData[identity]) { if (selected?.key && menuData[identity]) {
// 确保子菜单区域根据selected状态正确展开或收起 // 确保子菜单区域根据selected状态正确展开或收起
if (['appList', 'appFlow'].includes(selected.parentKey)) { if (['appList', 'appFlow'].includes(selected.parentKey)) {
// 如果应该显示子菜单但当前是收起状态,则展开 // // 如果应该显示子菜单但当前是收起状态,则展开
if (isSubMenuCollapsed) { // if (isSubMenuCollapsed) {
setIsSubMenuCollapsed(false); // setIsSubMenuCollapsed(false);
resizeBoxRef.current.style.width = `300px`; // }
}
} }
// 强制更新filteredMenu以确保显示正确的子菜单 // 强制更新filteredMenu以确保显示正确的子菜单
@ -787,10 +829,17 @@ const SideBar: React.FC<SideBarProps> = ({
<Input <Input
prefix={<IconSearch />} prefix={<IconSearch />}
placeholder={'搜索'} placeholder={'搜索'}
style={{ width: '90%' }} style={{ flex: 1 }}
value={searchValue} value={searchValue}
onChange={handleSearchChange} onChange={handleSearchChange}
/> />
<Button
type="secondary"
icon={isAllExpanded ? <IconShrink /> : <IconExpand />}
style={{ marginLeft: 5 }}
onClick={toggleExpandAll}
title={isAllExpanded ? '折叠全部' : '展开全部'}
/>
<Button <Button
type="primary" type="primary"
icon={<IconPlus />} icon={<IconPlus />}
@ -806,7 +855,12 @@ const SideBar: React.FC<SideBarProps> = ({
<div onContextMenu={handleContextMenu}> <div onContextMenu={handleContextMenu}>
<Tree <Tree
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
onExpand={(keys) => setExpandedKeys(keys as string[])} onExpand={(keys) => {
setExpandedKeys(keys as string[]);
// 检查是否全部展开,更新 isAllExpanded 状态
const allKeys = getAllExpandableKeys(filteredMenu[activeKey]?.children);
setIsAllExpanded(keys.length >= allKeys.length && allKeys.length > 0);
}}
selectedKeys={[]} // 移除选中样式 selectedKeys={[]} // 移除选中样式
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
onSelect={async (_selectedKeys, info) => { onSelect={async (_selectedKeys, info) => {

Loading…
Cancel
Save