feat(ideContainer): 更新菜单数据结构并支持动态应用列表加载

- 将 store 中的 selected 字段替换为 info,用于存储完整的 URL 参数信息- 调整 menuData 的结构以支持 identity 区分不同菜单
- 引入 getAppListBySceneId 接口,根据场景 ID 动态获取应用列表
- 修改 SideBar 组件逻辑,支持构建带子菜单的树形结构
- 更新 tab 切换逻辑,使用 key 替代 path 作为唯一标识- 移除无用的 ResizeBox 导入,优化代码结构
master
钟良源 4 months ago
parent 69cee04dba
commit 74e09e170e

@ -1,4 +1,4 @@
export const menuData = [
export const menuData1 = [
{
title: '应用列表',
path: '',

@ -1,5 +1,4 @@
import React, { useEffect, useState } from 'react';
import { ResizeBox } from '@arco-design/web-react';
import { getUrlParams } from '@/utils/common';
import styles from './style/index.module.less';
import SideBar from './sideBar';
@ -8,8 +7,12 @@ import RightSideBar from './rightSideBar';
import NavBar from './navBar';
import ProjectContainer from '@/pages/orchestration/project';
import ApplicationContainer from '@/pages/orchestration/application';
import { menuData, menuData2 } from './config/menuData';
import { menuData1, menuData2 } from './config/menuData';
import { Selected } from '@/pages/ideContainer/types';
import { updateInfo } from '@/store/ideContainer';
import { useDispatch, useSelector } from 'react-redux';
import { getAppListBySceneId } from '@/api/apps';
import * as url from 'node:url';
type UrlParamsOptions = {
identity?: string;
@ -41,11 +44,29 @@ function IDEContainer() {
const [subMenuWidth, setSubMenuWidth] = useState(200); // 子菜单宽度状态
// 用于跟踪已打开的tab保持组件状态
const [openedTabs, setOpenedTabs] = useState<Set<string>>(new Set());
const [subMenuData, setSubMenuData] = useState<any>({});
const { menuData } = useSelector((state) => state.ideContainer);
const dispatch = useDispatch();
const getAppList = async () => {
const res: any = await getAppListBySceneId({
pageSize: 999,
currPage: 1,
sceneId: urlParams.id
});
if (res.code === 200) setSubMenuData({ 'appList': res.data.list });
};
useEffect(() => {
setUrlParams(getUrlParams(window.location.href) as UrlParamsOptions);
dispatch(updateInfo(getUrlParams(window.location.href) as UrlParamsOptions));
}, []);
useEffect(() => {
if (urlParams.id) getAppList();
}, [urlParams.id]);
// 当selected.path变化时添加到已打开的tab集合中
useEffect(() => {
if (selected.path) {
@ -122,37 +143,25 @@ function IDEContainer() {
setSubMenuWidth(width);
};
// 根据identity获取对应的菜单数据
const getCurrentMenuData = () => {
switch (urlParams.identity) {
case 'scene':
return menuData;
case 'componentDevelopment':
return menuData2;
default:
return menuData;
}
};
// 处理tab切换
const handleTabChange = (path: string) => {
if (path) {
const handleTabChange = (key: string) => {
if (key) {
// 根据path查找对应的菜单项
const findMenuItem = (menuItems: any[], path: string): any => {
const findMenuItem = (menuItems: any[], key: string): any => {
for (const item of menuItems) {
if (item.path === path) {
if (item.key === key) {
return item;
}
if (item.children) {
const found = findMenuItem(item.children, path);
const found = findMenuItem(item.children, key);
if (found) return found;
}
}
return null;
};
const menuItems = getCurrentMenuData();
const menuItem = findMenuItem(menuItems, path);
const menuItems = menuData[urlParams.identity];
const menuItem = findMenuItem(menuItems, key);
if (menuItem) {
setSelected({
@ -184,16 +193,17 @@ function IDEContainer() {
<>
<div className={styles.IDEContainer}>
<SideBar
onMenuSelect={(select) => setSelected(select)}
selectedKey={selected.key}
identity={urlParams.identity}
subMenuData={subMenuData}
onMenuSelect={(select) => setSelected(select)}
/>
<div className={styles.content}>
<div className={styles.mainContent}>
{/*顶部导航栏*/}
<NavBar
selected={selected}
menuData={getCurrentMenuData()}
menuData={menuData[urlParams.identity]}
onTabChange={handleTabChange}
onTabClose={handleTabClose}
></NavBar>

@ -40,25 +40,26 @@ const NavBar: React.FC<NavBarProps> = ({ selected, menuData, onTabChange, onTabC
useEffect(() => {
if (selected?.path) {
const path = selected.path;
const key = selected.key;
const title = selected.title;
// 检查tab是否已存在
const existingTab = tabs.find(tab => tab.path === path && tab.title === title);
const existingTab = tabs.find(tab => tab.key === key && tab.title === title);
if (!existingTab) {
// 创建新tab
const title = menuData ? findMenuTitle(selected, menuData, path) : path;
const newTab = {
key: path,
key: key,
title: title,
path: path
};
setTabs(prev => [...prev, newTab]);
setActiveTab(path);
setActiveTab(key);
}
else {
// 如果tab已存在激活它
setActiveTab(path);
setActiveTab(key);
}
}
}, [selected, menuData]);
@ -86,7 +87,7 @@ const NavBar: React.FC<NavBarProps> = ({ selected, menuData, onTabChange, onTabC
// 查找对应的tab并通知父组件
const tab = tabs.find(t => t.key === key);
if (tab) {
onTabChange?.(tab.path);
onTabChange?.(tab.key);
}
};

@ -1,9 +1,12 @@
import React, { useEffect, useState } from 'react';
import styles from './style/sideBar.module.less';
import { IconApps } from '@arco-design/web-react/icon';
import { menuData, menuData2 } from './config/menuData';
import { menuData1, menuData2 } from './config/menuData';
import { ResizeBox, Tree } from '@arco-design/web-react';
import { Selected } from '@/pages/ideContainer/types';
import { useDispatch } from 'react-redux';
import { updateMenuData } from '@/store/ideContainer';
import _ from 'lodash';
const TreeNode = Tree.Node;
@ -13,29 +16,49 @@ interface MenuItemType {
children?: MenuItemType[];
path?: string;
icon?: React.ReactNode;
[key: string]: string | MenuItemType[] | React.ReactNode;
}
interface SideBarProps {
onMenuSelect?: (selected: Selected) => void;
subMenuData: any;
selectedKey?: string;
identity?: string;
onMenuSelect?: (selected: Selected) => void;
}
const SideBar: React.FC<SideBarProps> = ({ onMenuSelect, selectedKey, identity }) => {
const SideBar: React.FC<SideBarProps> = ({ selectedKey, identity, subMenuData, onMenuSelect }) => {
const [menu, setMenu] = useState<MenuItemType[]>([]);
const [subMenuWidth, setSubMenuWidth] = useState(200); // 子菜单宽度状态
const [isSubMenuCollapsed, setIsSubMenuCollapsed] = useState(false); // 子菜单收起状态
const [activeKey, setActiveKey] = useState(0);
const [mainMenuSelectedKey, setMainMenuSelectedKey] = useState<string>('');
const dispatch = useDispatch();
function getMenuData(): MenuItemType[] {
switch (identity) {
case 'scene':
const menuData = _.cloneDeep(menuData1);
const newSubMenuData = _.cloneDeep(subMenuData);
const subMenuKey = Object.keys(newSubMenuData)[0];
const subMenuValue: any = Object.values(newSubMenuData)[0];
const menuIndex = menuData.findIndex(v => v.key === subMenuKey);
// 构建数据结构,这是目录默认需要的数据结构
subMenuValue.forEach(v => {
v.title = v.name;
v.key = `compFlow-${v.id}`;
v.path = 'compFlow';
v.parentKey = selectedKey;
v.children = null;
});
menuData[menuIndex]['children'] = subMenuValue;
dispatch(updateMenuData({ 'scene': menuData }));
return menuData;
case 'componentDevelopment' :
dispatch(updateMenuData({ 'componentDevelopment': menuData2 }));
return menuData2;
default:
return menuData;
return menuData1;
}
}
@ -102,7 +125,7 @@ const SideBar: React.FC<SideBarProps> = ({ onMenuSelect, selectedKey, identity }
useEffect(() => {
setMenu(getMenuData());
}, [identity]);
}, [subMenuData]);
return (
<div

@ -45,7 +45,9 @@ const Engineering: React.FC<EngineeringProps> = ({ dataType, showAdd = true }) =
const params: OpenWindowOptions = {
target: '_blank',
menu: false,
identity: 'scene'
identity: 'scene',
id: item.id,
dataType
};
openWindow(url, params);
};

@ -1,14 +1,14 @@
import { createSlice } from '@reduxjs/toolkit';
interface IDEContainerState {
selected?: string;
menuData?: any[];
info: any;
menuData: any;
logBarStatus?: boolean;
}
const initialState: IDEContainerState = {
selected: '',
menuData: [],
info: {},
menuData: {},
logBarStatus: false
};
@ -16,8 +16,8 @@ const ideContainerSlice = createSlice({
name: 'ideContainer',
initialState,
reducers: {
updateSelected(state, action) {
state.selected = action.payload;
updateInfo(state, action) {
state.info = action.payload;
},
updateMenuData(state, action) {
state.menuData = action.payload;
@ -28,6 +28,6 @@ const ideContainerSlice = createSlice({
}
});
export const { updateSelected, updateMenuData, updateLogBarStatus } = ideContainerSlice.actions;
export const { updateInfo, updateMenuData, updateLogBarStatus } = ideContainerSlice.actions;
export default ideContainerSlice.reducer;
Loading…
Cancel
Save