import React, { useMemo } from 'react' import { Layout, Menu } from 'antd' import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons' import { RouteItem } from '@/config/routes' import { useHistory, useLocation } from 'react-router-dom' const { Sider } = Layout const { SubMenu } = Menu export const defaultRenderLogo = (logo: React.ReactNode): React.ReactNode => { if (typeof logo === 'string') { return logo } if (typeof logo === 'function') { return logo() } return logo } const defaultRenderCollapsedButton = (collapsed?: boolean) => collapsed ? : const defaultRenderLogoAndTitle = ( props: SiderMenuProps, collapsed: boolean ): React.ReactNode => { const { logo, title } = props const logoDom = defaultRenderLogo(logo) const titleDom =

{title}

return ( {logoDom} {collapsed ? null : titleDom} ) } function clearMenuItem(menusData: RouteItem[]): RouteItem[] { return menusData .map((item) => { const finalItem = { ...item } if (finalItem.hideInMenu) { return null } if (finalItem && finalItem?.children) { if (finalItem.children.some((child) => child && !child.hideInMenu)) { return { ...item, children: clearMenuItem(finalItem.children), } } delete finalItem.children } return finalItem }) .filter(Boolean) as RouteItem[] } function renderMenu(menuData: RouteItem[]) { return menuData.map((menu, index) => { return ( {menu.children ? ( {renderMenu(menu.children)} ) : !menu.hideInMenu ? ( {menu.name || menu.path} ) : null} ) }) } export interface SiderMenuProps { title?: string logo?: string | React.ReactNode routes: RouteItem[] onCollapse?: Function collapsed: boolean theme?: 'light' | 'dark' siderWidth?: string style?: Record links?: string[] } const SideBar: React.FC = (props) => { const { routes, onCollapse, theme = 'light', siderWidth = 208, style, collapsed, links, } = props const location = useLocation() const selectedKey = location.pathname === '/' ? '/home' : location.pathname const collapsedButtonRender = defaultRenderCollapsedButton const menuData = clearMenuItem(routes) const headerDom = defaultRenderLogoAndTitle(props, collapsed) const renderMenuDom = useMemo(() => { return renderMenu(menuData) }, [menuData]) const history = useHistory() return (
{ onCollapse?.(collapse) }} collapsedWidth={48} style={{ overflow: 'hidden', ...style, minHeight: '100%', height: '100%', }} width={siderWidth} className="menu-sider" > {headerDom}
{ history.push(key) }} style={{ flex: '1 1 0', }} > {renderMenuDom}
{(links || []).map((node, index) => ( {node} ))} { onCollapse?.(!collapsed) }} > {collapsedButtonRender(collapsed)}
) } export default SideBar