feat(ideContainer): 预设侧边栏右键菜单功能,修改侧边栏复合组件的数据处理逻辑

master
钟良源 3 months ago
parent 7e6d2db561
commit 3cf8e605c5

@ -177,68 +177,80 @@ const SideBar: React.FC<SideBarProps> = ({
const [showModal, setShowModal] = useState(false);
const [modalType, setModalType] = useState<'ADD' | 'EDIT'>('ADD');
const [currentApp, setCurrentApp] = useState<any>(null);
const [contextMenu, setContextMenu] = useState<{
visible: boolean;
x: number;
y: number;
nodeData: any;
}>({
visible: false,
x: 0,
y: 0,
nodeData: null
}); // 添加右键菜单状态
const resizeBoxRef = useRef<HTMLDivElement>(null); // 引用第一个 ResizeBox 容器
const contextMenuRef = useRef<HTMLDivElement>(null); // 右键菜单引用
const { menuData } = useSelector(state => state.ideContainer);
const dispatch = useDispatch();
function getMenuData(): MenuItemType[] {
switch (identity) {
case 'scene':
switch (identity) {
case 'scene':
const menuData = _.cloneDeep(menuData1);
const newSubMenuData = _.cloneDeep(subMenuData);
// 遍历所有 subMenuKey 来构建子菜单数据结构
Object.keys(newSubMenuData).forEach(subMenuKey => {
const subMenuValue: any = _.cloneDeep(newSubMenuData[subMenuKey]);
const menuIndex = menuData.findIndex(v => v.key === subMenuKey);
if (menuIndex !== -1) {
// 构建数据结构,这是目录默认需要的数据结构
subMenuValue.forEach(v => {
v.title = v.name;
v.key = `compFlow-${v.id}`;
v.path = 'compFlow';
v.parentKey = subMenuKey;
v.icon = '/ideContainer/icon/app.png';
if (subMenuKey !== 'appFlow') {
v.children = [
{
title: '事件',
children: null,
icon: '/ideContainer/icon/list.png'
},
{
title: '组件列表',
children: null,
icon: '/ideContainer/icon/list.png'
}
];
}
});
menuData[menuIndex]['children'] = subMenuValue;
}
});
const newSubMenuData = _.cloneDeep(subMenuData);
// 遍历所有 subMenuKey 来构建子菜单数据结构
Object.keys(newSubMenuData).forEach(subMenuKey => {
const subMenuValue: any = _.cloneDeep(newSubMenuData[subMenuKey]);
const menuIndex = menuData.findIndex(v => v.key === subMenuKey);
if (menuIndex !== -1) {
// 构建数据结构,这是目录默认需要的数据结构
subMenuValue.forEach(v => {
v.title = v.name;
v.key = `compFlow-${v.id}`;
v.path = 'compFlow';
v.parentKey = subMenuKey;
v.icon = '/ideContainer/icon/app.png';
if (subMenuKey !== 'appFlow') {
v.children = [
{
title: '事件',
children: null,
icon: '/ideContainer/icon/list.png'
},
{
title: '组件列表',
children: null,
icon: '/ideContainer/icon/list.png'
}
];
}
});
menuData[menuIndex]['children'] = subMenuValue;
}
});
dispatch(updateMenuData({ 'scene': menuData }));
return menuData;
case 'componentDevelopment' :
dispatch(updateMenuData({ 'scene': menuData }));
return menuData;
case 'componentDevelopment' :
dispatch(updateMenuData({ 'componentDevelopment': menuData2 }));
return menuData2;
default:
default:
return menuData1;
}
}
}
// 处理子菜单区域的拖拽调整大小
const handleSubMenuResize = (e: MouseEvent, { width }: { width: number }) => {
resizeBoxRef.current.style.width = `${width}px`;
resizeBoxRef.current.style.width = `${width}px`;
};
// 切换子菜单区域的收起/展开状态
const toggleSubMenu = () => {
setIsSubMenuCollapsed(!isSubMenuCollapsed);
const width = isSubMenuCollapsed ? 300 : 0;
resizeBoxRef.current.style.width = `${width}px`;
resizeBoxRef.current.style.width = `${width}px`;
};
// 处理菜单项点击事件
@ -254,7 +266,7 @@ const SideBar: React.FC<SideBarProps> = ({
// 如果点击的是其他菜单项,则展开子菜单(如果已收起)
if (isSubMenuCollapsed) {
setIsSubMenuCollapsed(false);
resizeBoxRef.current.style.width = `300px`;
resizeBoxRef.current.style.width = `300px`;
}
}
}
@ -303,6 +315,7 @@ const SideBar: React.FC<SideBarProps> = ({
const currentMenu = _.cloneDeep(menuData[identity]);
const index = currentMenu.findIndex(v => v.key === parentKey);
const res: any = await getAppInfoNew(data.id);
console.log('res.data:', res.data.subs);
if (res.code === 200) {
const children = currentMenu[index].children.find(v => v.id === data.id);
children.children[0].children = res.data.events.map(item => {
@ -316,12 +329,19 @@ const SideBar: React.FC<SideBarProps> = ({
return {
title: compTypeMap[item],
icon: item === 'appComponent' ? '/ideContainer/icon/app1.png' : '/ideContainer/icon/complexApp.png',
children: res.data.compList[item].map(item => {
children: item === 'appComponent' ? res.data.compList[item].map(title => {
return {
title: item,
title: title,
children: null,
icon: '/ideContainer/icon/tool.png'
};
}) : res.data.subs.map(info => {
return {
title: info.flowName,
children: null,
icon: '/ideContainer/icon/tool.png',
compData: info
};
})
};
});
@ -401,6 +421,59 @@ const SideBar: React.FC<SideBarProps> = ({
setSearchValue(value);
};
// 处理鼠标按下事件
const handleMouseDown = (e: React.MouseEvent) => {
// 明确检查右键点击
if (e.button === 2) {
e.stopPropagation();
e.preventDefault();
// 获取点击的目标元素及其数据
const target = e.target as HTMLElement;
const treeNode = target.closest('.arco-tree-node');
if (treeNode) {
// 在实际应用中,你可能需要通过 tree-node 获取对应的数据
// 这里我们简单地显示右键菜单
}
// 设置右键菜单的位置和显示
setContextMenu({
visible: true,
x: e.clientX,
y: e.clientY,
nodeData: null
});
}
};
// 劫持右键
const handleContextMenu = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
// 设置右键菜单的位置和显示
setContextMenu({
visible: true,
x: e.clientX,
y: e.clientY,
nodeData: null
});
};
// 点击其他地方隐藏右键菜单
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (contextMenuRef.current && !contextMenuRef.current.contains(e.target as Node)) {
setContextMenu(prev => ({ ...prev, visible: false }));
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
// 渲染节点的额外操作按钮
const renderNodeExtra = (node) => {
// 只有当 node.dataRef.id 存在时才渲染操作按钮
@ -416,6 +489,7 @@ const SideBar: React.FC<SideBarProps> = ({
setCurrentApp(node.dataRef);
setModalType('EDIT');
setShowModal(true);
setContextMenu(prev => ({ ...prev, visible: false })); // 隐藏右键菜单
}}
>
<span style={{ color: 'rgba(161, 165, 194, 1)' }}>
@ -439,6 +513,7 @@ const SideBar: React.FC<SideBarProps> = ({
// 通知父组件应用已被删除
onDeleteApp?.(node.dataRef.id);
onRefresh();
setContextMenu(prev => ({ ...prev, visible: false })); // 隐藏右键菜单
}
});
}}
@ -462,6 +537,9 @@ const SideBar: React.FC<SideBarProps> = ({
top: 10,
color: '#000000'
}}
onClick={(e) => {
e.stopPropagation();
}}
/>
</Dropdown>
);
@ -528,27 +606,64 @@ const SideBar: React.FC<SideBarProps> = ({
</div>}
{/* 子菜单 */}
<Tree
defaultExpandedKeys={['0-0']}
selectedKeys={[]} // 移除选中样式
onSelect={async (_selectedKeys, info) => {
const selectedNode = info.node;
const originalData = selectedNode.props.dataRef;
if (selected?.parentKey === 'appList') {
await getProjectEnvData(originalData);
// 调用外部传入的菜单选择处理函数
originalData.key && onMenuSelect?.({ ...originalData } as Selected);
}
}}
style={{ background: 'transparent' }} // 移除背景色
renderExtra={selected?.parentKey === 'appList' ? renderNodeExtra : null}
>
{renderMenuItems(filteredMenu[activeKey]?.children)}
</Tree>
<div onContextMenu={handleContextMenu}>
<Tree
defaultExpandedKeys={['0']} // 整个属性去掉就会展开全部
selectedKeys={[]} // 移除选中样式
onMouseDown={handleMouseDown}
onSelect={async (_selectedKeys, info) => {
const selectedNode = info.node;
const originalData = selectedNode.props.dataRef;
console.log(originalData);
if (selected?.parentKey === 'appList') {
await getProjectEnvData(originalData);
// 调用外部传入的菜单选择处理函数
originalData.key && onMenuSelect?.({ ...originalData } as Selected);
}
}}
style={{ background: 'transparent' }} // 移除背景色
renderExtra={selected?.parentKey === 'appList' ? renderNodeExtra : null}
>
{renderMenuItems(filteredMenu[activeKey]?.children)}
</Tree>
</div>
</div>
</ResizeBox>}
{/* 右键菜单 */}
{/*{contextMenu.visible && (*/}
{/* <div*/}
{/* ref={contextMenuRef}*/}
{/* className={styles['context-menu']}*/}
{/* style={{*/}
{/* position: 'fixed',*/}
{/* top: contextMenu.y,*/}
{/* left: contextMenu.x,*/}
{/* zIndex: 1000*/}
{/* }}*/}
{/* >*/}
{/* <Menu*/}
{/* className={styles['context-menu-dropdown']}*/}
{/* style={{*/}
{/* borderRadius: 4,*/}
{/* boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)'*/}
{/* }}*/}
{/* >*/}
{/* <MenuItem*/}
{/* key="refresh"*/}
{/* onClick={() => {*/}
{/* console.log('点击');*/}
{/* // onRefresh();*/}
{/* // setContextMenu(prev => ({ ...prev, visible: false }));*/}
{/* }}*/}
{/* >*/}
{/* <span>编辑复合组件</span>*/}
{/* </MenuItem>*/}
{/* </Menu>*/}
{/* </div>*/}
{/*)}*/}
{/* 新增/编辑应用 */}
{showModal && (
<AppHandleModal

@ -71,3 +71,33 @@
padding: 10px;
}
}
.context-menu {
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
padding: 4px 0;
.context-menu-dropdown {
border: none;
box-shadow: none;
padding: 0;
:global {
.arco-menu-inner {
padding: 4px 0;
}
.arco-menu-item {
padding: 5px 12px;
margin: 0;
height: 32px;
line-height: 22px;
&:hover {
background-color: #f5f5f5;
}
}
}
}
}
Loading…
Cancel
Save