import React, { useState, useEffect, useMemo, useRef } from 'react' import { connect } from 'dva' import { withRouter, matchPath } from 'dva/router' import { Scrollbars } from 'react-custom-scrollbars' import { Icon } from 'antd' import EnergyIcon from '../utils/energyIcon' import { $consts } from '../plugins' import './sider1.less' const Sider = (props) => { const [activeKeepMenu, setActiveKeepMenu] = useState(null) const [shortMenuShow, setShortMenuShow] = useState(false) const [expandMenuShow, setExpandMenuShow] = useState(false) /** 菜单页展开与收起 */ const timer = useRef(-1) const handleExpandMenuShow = () => { clearTimeout(timer.current) setExpandMenuShow(true) } const handleExpandMenuHide = () => { clearTimeout(timer.current) timer.current = setTimeout(() => { setExpandMenuShow(false) }, 200) } /** 控制三级菜单收缩和展开 */ const [menuShrink, setMenuShrink] = useState({}) const handleMenuShrink = (menuId) => { const data = Object.assign({}, menuShrink) data[menuId] ? data[menuId] = '' : data[menuId] = menuId setMenuShrink(data) } /** 回到首页 */ const navToHome = () => { setActiveMenu(null) props.history.push({ pathname: '/home' }) } /** 子菜单路由 */ const navToMenu = (menu) => { props.history.push({ pathname: `/main/${menu.ID}` }) } /** 后台设置:四级菜单 */ const navToBackend = (menu) => { props.history.push({ pathname: `/backend/${menu.ID}` }) } /** 一级菜单显示菜单 */ const [currMenu, setCurrMenu] = useState(null) useEffect(() => { const menus = props.login.loginInfo?.Menus || [] menus.length && !currMenu && setCurrMenu(menus[0].Node) }, [props.login.loginInfo?.Menus]) /** 已激活菜单 */ const [activeMenu, setActiveMenu] = useState(null) const handleActiveMenu = (menu) => { setActiveMenu(menu) navToMenu(menu) } /** 页面刷新时候,更新菜单的选中状态 */ useEffect(() => { const { pathname } = props.location const mathHome = matchPath(pathname, { path: $consts['ROUTE/HOME'], exact: true, strict: true }) if (mathHome) { activeMenu && setActiveMenu(null) } const mathMain = matchPath(pathname, { path: $consts['ROUTE/MAIN'], exact: true, strict: true }) if (mathMain) { const { flatMenus } = props.login const { menuId } = mathMain.params const find = flatMenus.find(item => item.ID === menuId) if (find) { props.dispatch({ type: 'app/updateActivatedMenu', payload: { currActivatedTab: find.ID, currActivatedMenu: find } }) !activeMenu && setActiveMenu(find) } } }, [props.location.pathname, props.login.flatMenus, activeMenu]) /** 常用菜单 */ const favorMenus = useMemo(() => { const { flatMenus } = props.login return flatMenus.filter(menu => menu.IS_RESIDENT) }, [props.login.flatMenus]) /** 一级菜单 */ const topMenus = useMemo(() => { const menus = props.login.loginInfo?.Menus || [] // 菜单宽度 82 + margin 40 const menuWidth = menus.length ? menus.length * 82 + (menus.length - 1) * 40 : 0 // 叶子菜单需要换行展示个数 const leafMenuSections = menus.length < 3 ? 1 : menus.length === 3 ? 2 : menus.length - 2 return { menus, width: menuWidth < 120 ? 120 : menuWidth, leafMenuSections } }, [props.login.loginInfo?.Menus]) /** 二三级子菜单 */ const subMenus = useMemo(() => { const { menus } = topMenus const find = menus.find(menu => menu.Node.ID === currMenu?.ID) return find?.Children || [] }, [currMenu, topMenus]) /** 三级子菜单默认收缩与展开 */ const { IS_MENU_SHRINK = false } = props.login.baseConfig useEffect(() => { // IS_MENU_SHRINK为true时, 收缩所有三级菜单 if (IS_MENU_SHRINK) { const { menus } = topMenus const data = {} menus.forEach(menu => menu.Children && menu.Children.forEach(child => data[child.Node.ID] = child.Node.ID)) setMenuShrink(data) } }, [IS_MENU_SHRINK]) /** 登录页隐藏 */ if (props.matchLogin) return null return (
setShortMenuShow(true)} onMouseLeave={() => setShortMenuShow(false)} className={`sider ${shortMenuShow ? 'shortMenuShow' : ''}`} > {/** 所有菜单 */}
首页
{/** 常用菜单 */} { favorMenus.map((menu, index) => { const active = menu.ID === activeMenu?.ID const wrapClass = `sider__menu ${index === favorMenus.length - 1 ? 'lastChild' : ''}` const iconClass = `sider__menu-icon ${active ? 'active' : ''}` const fontClass = `sider__menu-font--text ${active ? 'active' : ''}` return (
handleActiveMenu(menu)} className={wrapClass}>
{menu.NAME}
) }) }
{/** 展开菜单 */}
{/* 留白, 扩大上方onMouseEnter的范围 */}
{/** inner 加 padding,否则加在 sider__menuExpand 上的话,width 为 0,也会有 padding 的宽度 */}
{/** 一级菜单 */}
{ topMenus.menus.map((menu, index) => { const active = menu.Node.ID === activeMenu?.ID const activeKeep = menu.Node.ID === activeKeepMenu?.ID const wrapClass = `sider__menuExpand-menu ${index === topMenus.menus.length - 1 ? 'lastChild' : ''}` const iconClass = `sider__menuExpand-menu--itemIcon ${active ? 'active' : ''} ${activeKeep ? 'active' : ''}` const fontClass = `sider__menuExpand-menu--itemText text-ellipsis ${active ? 'active' : ''} ${activeKeep ? 'active' : ''}` const indicatorClass = `sider__menuExpand-menu--indicator ${active ? 'active' : ''} ${activeKeep ? 'active' : ''}` return (
{ setCurrMenu(menu.Node); setActiveKeepMenu(menu.Node) }} onClick={() => handleActiveMenu(menu.Node)} className={wrapClass} >
{menu.Node.NAME}
) }) }
{/** 二三级菜单 */}
{ subMenus.map((menu, index) => { const isLevel4Menu = menu.Children?.find(mc => mc.Children?.length) const childMenus = isLevel4Menu ? [menu] : (menu.Children || []) return (
{/** 二级菜单 */}
handleMenuShrink(menu.Node.ID)} className='sider__menuExpand-subMenu--title' > {menu.Node.NAME}
{/** 三级菜单 */} { !menuShrink[menu.Node.ID] ? childMenus.map((child, childIndex) => { const active = child.Node.ID === activeMenu?.ID const iconClass = `sider__menuExpand-menu--itemIcon ${active ? 'active' : ''}` const fontClass = `sider__menuExpand-menu--itemText text-ellipsis ${active ? 'active' : ''}` return (
isLevel4Menu ? navToBackend(child.Node) : handleActiveMenu(child.Node)} className='sider__menuExpand-subMenu--menu' >
{child.Node.NAME}
) }) : null }
) }) }
{/*
{currMenu?.REMARK}
脚注
*/}
{/** 左边的 border */}
{/* 留白, 扩大右侧onMouseEnter的范围 */}
) } export default withRouter(connect(({ login }) => ({ login }))(Sider))