mh-lcmk-sms-web/src/layout/SiderOld.js
2024-05-27 09:25:22 +08:00

295 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 (
<div
onMouseEnter={() => setShortMenuShow(true)}
onMouseLeave={() => setShortMenuShow(false)}
className={`sider ${shortMenuShow ? 'shortMenuShow' : ''}`}
>
{/** 所有菜单 */}
<div
onMouseEnter={handleExpandMenuShow}
onMouseLeave={handleExpandMenuHide}
onClick={navToHome}
className='sider__menuAll'
>
<img src={require('../assets/layout/menu-all.png')} alt='' className='sider__menuAll-icon' />
<div className='sider__menu-font'>
<span className='sider__menu-font--text'>首页</span>
<Icon type='right' className='sider__menu-font--icon' />
</div>
</div>
{/** 常用菜单 */}
<Scrollbars
autoHide
autoHideTimeout={1000}
autoHideDuration={200}
className='sider__scrollbars'
>
{
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 (
<div key={`${menu.ID}_${index}`} onClick={() => handleActiveMenu(menu)} className={wrapClass}>
<Icon type={menu.ICON ? menu.ICON : "file-text"} className={iconClass} />
<div className='sider__menu-font'><span className={fontClass}>{menu.NAME}</span></div>
</div>
)
})
}
</Scrollbars>
{/** 展开菜单 */}
<div
onMouseEnter={expandMenuShow ? handleExpandMenuShow : handleExpandMenuHide}
onMouseLeave={handleExpandMenuHide}
className={`sider__menuExpand ${expandMenuShow ? 'expandMenuShow' : ''}`}
style={{ width: expandMenuShow ? ((topMenus.width + 48) < 300 ? 300 : topMenus.width + 48) : 0, overflow: expandMenuShow ? 'visible' : 'hidden' }} // 加 padding: 24
>
{/* 留白, 扩大上方onMouseEnter的范围 */}
<div className={`${expandMenuShow ? 'sider__menuExpand-divempty' : 'sider__menuExpand-divempty-hide'}`}></div>
{/** inner 加 padding否则加在 sider__menuExpand 上的话width 为 0也会有 padding 的宽度 */}
<div className='sider__menuExpand-inner' style={{ width: ((topMenus.width + 48) < 300 ? 300 : topMenus.width + 48) }}>
{/** 一级菜单 */}
<div className='sider__menuExpand-header'>
{
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 (
<div
key={`${menu.Node.ID}_${index}`}
onMouseEnter={() => { setCurrMenu(menu.Node); setActiveKeepMenu(menu.Node) }}
onClick={() => handleActiveMenu(menu.Node)}
className={wrapClass}
>
<div
className='sider__menuExpand-menu--item'
>
<Icon type={menu.Node.ICON ? menu.ICON : "file-text"} className={iconClass} />
<div className={fontClass}>{menu.Node.NAME}</div>
</div>
<div className={indicatorClass} />
</div>
)
})
}
</div>
{/** 二三级菜单 */}
<div className='sider__menuExpand-body'>
<Scrollbars
autoHide
autoHideTimeout={1000}
autoHideDuration={200}
>
<div className='sider__menuExpand-body--scroll'>
{
subMenus.map((menu, index) => {
const isLevel4Menu = menu.Children?.find(mc => mc.Children?.length)
const childMenus = isLevel4Menu ? [menu] : (menu.Children || [])
return (
<div
key={`${menu.Node.ID}_${index}`}
className='sider__menuExpand-subMenu'
style={{ flex: `0 0 ${1 / topMenus.leafMenuSections * 100}%` }}
>
{/** 二级菜单 */}
<div
onClick={() => handleMenuShrink(menu.Node.ID)}
className='sider__menuExpand-subMenu--title'
>
{menu.Node.NAME}
<Icon type={!menuShrink[menu.Node.ID] ? 'down' : 'up'} className='sider__menuExpand-subMenu--title--icon' />
</div>
{/** 三级菜单 */}
{
!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 (
<div
key={`${child.Node.ID}_${index}_${childIndex}`}
onClick={() => isLevel4Menu ? navToBackend(child.Node) : handleActiveMenu(child.Node)}
className='sider__menuExpand-subMenu--menu'
>
<Icon type={child.Node.ICON ? child.Node.ICON : "file-text"} className={iconClass} />
<div className={fontClass}>{child.Node.NAME}</div>
</div>
)
})
: null
}
</div>
)
})
}
</div>
</Scrollbars>
</div>
{/* <div className='sider__menuExpand-footer'>
<Scrollbars
autoHide
autoHideTimeout={1000}
autoHideDuration={200}
>
<div className='sider__menuExpand-footer--scroll'>{currMenu?.REMARK}</div>
</Scrollbars>
<span className='sider__menuExpand-footer--title'>脚注</span>
</div> */}
</div>
{/** 左边的 border */}
<div className='sider__menuExpand-divider' />
{/* 留白, 扩大右侧onMouseEnter的范围 */}
<div className={`${expandMenuShow ? 'sider__menuExpand-divempty-right' : 'sider__menuExpand-divempty-hide'}`}></div>
</div>
</div>
)
}
export default withRouter(connect(({ login }) => ({ login }))(Sider))