mh_jy_safe_web/src/layout/SiderOldTwo.js
2025-08-25 10:08:30 +08:00

474 lines
17 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(true);
const [expandMenuShow, setExpandMenuShow] = useState(true);
/** 菜单页展开与收起 */
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"
>
<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);setCurrMenu(menu.Node);
setActiveKeepMenu(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>
{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>
{/** 左边的 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));