refactor(ideContainer): 侧边栏样式和结构重构

- 重新设计了侧边栏的样式,增加了滚动条和过渡效果
- 优化了菜单项的展示方式,支持图标和文本- 移除了折叠功能,简化了侧边栏的结构
- 使用自定义样式替代了 arco-design 的 Sider 组件
master
钟良源 5 months ago
parent afa5de1030
commit 8061bd169a

@ -1,21 +1,16 @@
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 { Layout, Menu } from '@arco-design/web-react'; import { IconApps } from '@arco-design/web-react/icon';
import { IconApps, IconMenuFold, IconMenuUnfold } from '@arco-design/web-react/icon';
import { GlobalState } from '@/store'; import { GlobalState } from '@/store';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import getUrlParams from '@/utils/getUrlParams'; import getUrlParams from '@/utils/getUrlParams';
import { menuData, menuData2 } from './config/menuData'; import { menuData, menuData2 } from './config/menuData';
const Sider = Layout.Sider;
const MenuItem = Menu.Item;
const SubMenu = Menu.SubMenu;
interface MenuItemType { interface MenuItemType {
title: string; title: string;
children?: MenuItemType[]; children?: MenuItemType[];
path?: string; path?: string;
icon?: React.ReactNode;
} }
interface SideBarProps { interface SideBarProps {
@ -26,21 +21,15 @@ interface SideBarProps {
const SideBar: React.FC<SideBarProps> = ({ onMenuSelect, selectedKey, identity }) => { const SideBar: React.FC<SideBarProps> = ({ onMenuSelect, selectedKey, identity }) => {
const urlParams = getUrlParams(); const urlParams = getUrlParams();
const [collapsed, setCollapsed] = useState<boolean>(false); const [menu, setMenu] = useState<MenuItemType[]>([]);
const [menu, setMenu] = useState([]); const { settings } = useSelector(
const { userInfo, settings, userLoading } = useSelector(
(state: GlobalState) => state (state: GlobalState) => state
); );
const navbarHeight = 60; const navbarHeight = 60;
const menuWidth = collapsed ? 48 : settings?.menuWidth;
const showNavbar = settings?.navbar && urlParams.navbar !== false; const showNavbar = settings?.navbar && urlParams.navbar !== false;
const paddingTop = showNavbar ? { paddingTop: navbarHeight } : {}; const paddingTop = showNavbar ? { paddingTop: navbarHeight } : {};
const sideBarStyle = { ...paddingTop, height: '100%' };
function toggleCollapse() {
setCollapsed((collapsed) => !collapsed);
}
function getMenuData(): MenuItemType[] { function getMenuData(): MenuItemType[] {
switch (identity) { switch (identity) {
@ -57,56 +46,33 @@ const SideBar: React.FC<SideBarProps> = ({ onMenuSelect, selectedKey, identity }
setMenu(getMenuData()); setMenu(getMenuData());
}, [identity]); }, [identity]);
// 递归渲染菜单项 return (
const renderMenuItems = (items: MenuItemType[], parentKey = '') => { <div
return items.map((item, index) => { className={styles.sider}
const currentKey = (parentKey ? `${parentKey}_${index}` : `${index}`); style={sideBarStyle}
>
if (!item.children) { <div className={styles['menu-container']}>
return ( {menu.map((item, index) => (
<MenuItem <div
key={currentKey} key={index}
className={`${styles['menu-item']} ${selectedKey === `${index}` ? styles['menu-item-active'] : ''}`}
onClick={() => { onClick={() => {
onMenuSelect?.({ currentPath: item.path, currentKey }); onMenuSelect?.({ currentPath: item.path, currentKey: `${index}` });
}} }}
> >
{item.title} <div className={styles['menu-item-content']}>
</MenuItem> <span className={styles['menu-item-icon']}>
); {item.icon || <IconApps />}
} </span>
<span className={styles['menu-item-text']}>
return ( {item.title}
<SubMenu key={currentKey} title={item.title}> </span>
{renderMenuItems(item.children, currentKey)} </div>
</SubMenu> </div>
); ))}
}); </div>
}; </div>
return (
<>
<Layout>
<Sider
className={styles.sider}
width={menuWidth}
collapsed={collapsed}
onCollapse={setCollapsed}
trigger={null}
collapsible
breakpoint="xl"
style={paddingTop}>
<Menu
selectedKeys={selectedKey ? [selectedKey] : ['0']}
>
{renderMenuItems(menu)}
</Menu>
{/*<div className={styles['collapse-btn']} onClick={toggleCollapse}>*/}
{/* {collapsed ? <IconMenuUnfold /> : <IconMenuFold />}*/}
{/*</div>*/}
</Sider>
</Layout>
</>
); );
}; };
export default SideBar; export default SideBar;

@ -1,28 +1,65 @@
.sider { .sider {
position: fixed; width: 60px;
height: 100%; height: 100%;
overflow-y: auto;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.08);
z-index: 99;
transition: all 0.3s ease-in-out;
position: fixed;
top: 0; top: 0;
left: 0; left: 0;
z-index: 99; background-color: var(--color-bg-2);
box-sizing: border-box; }
.menu-container {
height: calc(100% - 40px); // 为底部留出空间
overflow-y: auto;
}
.collapse-btn { .menu-item {
height: 24px; padding: 12px 4px;
width: 24px; text-align: center;
background-color: var(--color-fill-1); cursor: pointer;
color: var(--color-text-3); transition: all 0.3s ease-in-out;
border-radius: 2px; position: relative;
cursor: pointer; display: flex;
display: flex; flex-direction: column;
justify-content: center; align-items: center;
align-items: center;
// 位置
position: absolute;
bottom: 12px;
right: 12px;
&:hover { &:hover {
background-color: var(--color-fill-3); background-color: var(--color-fill-2);
}
} }
&-active {
background-color: var(--color-fill-2);
color: rgb(var(--primary-6));
}
}
.menu-item-content {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.menu-item-icon {
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
min-width: 16px;
margin-bottom: 10px;
}
.menu-item-text {
font-size: 14px;
text-align: center;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 4;
-webkit-box-orient: vertical;
line-height: 1.2;
width: 100%;
padding: 0 5px;
} }
Loading…
Cancel
Save