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: '应用列表', title: '应用列表',
path: '', path: '',

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

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

@ -1,9 +1,12 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './style/sideBar.module.less'; import styles from './style/sideBar.module.less';
import { IconApps } from '@arco-design/web-react/icon'; 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 { ResizeBox, Tree } from '@arco-design/web-react';
import { Selected } from '@/pages/ideContainer/types'; import { Selected } from '@/pages/ideContainer/types';
import { useDispatch } from 'react-redux';
import { updateMenuData } from '@/store/ideContainer';
import _ from 'lodash';
const TreeNode = Tree.Node; const TreeNode = Tree.Node;
@ -13,29 +16,49 @@ interface MenuItemType {
children?: MenuItemType[]; children?: MenuItemType[];
path?: string; path?: string;
icon?: React.ReactNode; icon?: React.ReactNode;
[key: string]: string | MenuItemType[] | React.ReactNode;
} }
interface SideBarProps { interface SideBarProps {
onMenuSelect?: (selected: Selected) => void; subMenuData: any;
selectedKey?: string; selectedKey?: string;
identity?: 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 [menu, setMenu] = useState<MenuItemType[]>([]);
const [subMenuWidth, setSubMenuWidth] = useState(200); // 子菜单宽度状态 const [subMenuWidth, setSubMenuWidth] = useState(200); // 子菜单宽度状态
const [isSubMenuCollapsed, setIsSubMenuCollapsed] = useState(false); // 子菜单收起状态 const [isSubMenuCollapsed, setIsSubMenuCollapsed] = useState(false); // 子菜单收起状态
const [activeKey, setActiveKey] = useState(0); const [activeKey, setActiveKey] = useState(0);
const [mainMenuSelectedKey, setMainMenuSelectedKey] = useState<string>(''); const [mainMenuSelectedKey, setMainMenuSelectedKey] = useState<string>('');
const dispatch = useDispatch();
function getMenuData(): MenuItemType[] { function getMenuData(): MenuItemType[] {
switch (identity) { switch (identity) {
case 'scene': 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; return menuData;
case 'componentDevelopment' : case 'componentDevelopment' :
dispatch(updateMenuData({ 'componentDevelopment': menuData2 }));
return menuData2; return menuData2;
default: default:
return menuData; return menuData1;
} }
} }
@ -102,7 +125,7 @@ const SideBar: React.FC<SideBarProps> = ({ onMenuSelect, selectedKey, identity }
useEffect(() => { useEffect(() => {
setMenu(getMenuData()); setMenu(getMenuData());
}, [identity]); }, [subMenuData]);
return ( return (
<div <div

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

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