import { ProLayout } from "@ant-design/pro-components";
import { Layout } from "antd";
import React, { FC, useEffect, useState, useRef } from "react";
import useUserStore from "/@/store/userStore";
import { shallow } from "zustand/shallow";
import { Outlet } from "react-router-dom";
import Breadcrumb from "/@/components/Breadcrumb";
import HeaderComponent from "/@/components/Header";
import CustomBoundary from "/@/components/Error";
import Menu from "/@/components/Menu";
import { Collapse, logo } from "/@/utils/png";
import styles from "./index.module.less";
const { Header, Sider } = Layout;
const headerStyle: React.CSSProperties = {
position: "fixed",
top: 0,
right: 0,
textAlign: "center",
height: 48,
zIndex: 10,
background: "var(--m-primary-linear-gradient-color)",
boxShadow: "0px 2px 8px 0px rgba(0,0,0,0.15)",
};
const siderStyle: React.CSSProperties = {
position: "fixed",
top: 0,
left: 0,
zIndex: 11,
height: "100%",
borderRight: "1px solid #E5E5E5",
cursor: "col-resize",
};
const siderBlockStyle: React.CSSProperties = {
overflow: "hidden",
transition: "all 0.18s,background 0s",
};
const collapsedTrue = {
width: "80px",
flex: "0 0 80px",
maxWidth: "80px",
minWidth: "80px",
};
const Index: FC = () => {
const { selectMenuKey } = useUserStore(
(state) => ({
selectMenuKey: state.selectMenuKey,
}),
shallow
);
const siderRef = useRef(null);
const [collapsed, setCollapsed] = useState(false);
const [siderBlockTrends, setSiderBlockTrends] = useState({
width: "290px",
flex: "0 0 290px",
maxWidth: "290px",
minWidth: "290px",
});
const [siderWidth, setSiderWidth] = useState(290);
const [isDragging, setIsDragging] = useState(false);
const [collapsedFalse, setCollapsedFalse] = useState({
width: "290px",
flex: "0 0 290px",
maxWidth: "290px",
minWidth: "290px",
});
const onToggleCollapsed = (): void => {
setCollapsed(!collapsed);
};
useEffect(() => {
console.log("collapsed", collapsed);
setSiderBlockTrends(!collapsed ? collapsedFalse : collapsedTrue);
setSiderWidth(collapsed ? 80 : 290);
setCollapsedFalse(
collapsed
? {
width: `80px`,
flex: `0 0 80px`,
maxWidth: `80px`,
minWidth: `80px`,
}
: {
width: `290px`,
flex: `0 0 290px`,
maxWidth: `290px`,
minWidth: `290px`,
}
);
}, [collapsed]);
useEffect(() => {
setCollapsed(siderWidth <= 80 ? true : false);
}, [siderWidth]);
useEffect(() => {
setSiderBlockTrends(collapsedFalse);
}, [collapsedFalse]);
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
const { clientX } = e;
if (isDragging) {
const maxClientX = window.innerWidth / 3;
const newWidth =
Math.min(clientX, maxClientX) >= 80
? Math.min(clientX, maxClientX)
: 80;
setSiderWidth(newWidth);
setCollapsedFalse({
width: `${newWidth}px`,
flex: `0 0 ${newWidth}px`,
maxWidth: `${newWidth}px`,
minWidth: `${newWidth}px`,
});
}
};
const handleMouseDown = (e: MouseEvent) => {
if (
siderRef.current &&
(siderRef.current as any).contains(e.target) &&
e.clientX > (siderRef.current as any).getBoundingClientRect().right - 10
) {
document.body.style.userSelect = "none";
setIsDragging(true);
}
};
const handleMouseUp = () => {
document.body.style.userSelect = "auto";
setIsDragging(false);
};
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mousedown", handleMouseDown);
document.addEventListener("mouseup", handleMouseUp);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mousedown", handleMouseDown);
document.removeEventListener("mouseup", handleMouseUp);
};
}, [isDragging]);
return (
<Layout hasSider>
<div style={{ ...siderBlockStyle, ...siderBlockTrends }}></div>
<Sider
ref={siderRef}
width={siderWidth}
style={siderStyle}
collapsed={collapsed}
theme="light"
breakpoint="lg"
onBreakpoint={(broken) => {
setSiderBlockTrends(broken ? collapsedTrue : collapsedFalse);
setCollapsed(broken);
}}
trigger={null}
>
<div className={styles.siderInner}>
<>
<div className={styles.logoContainer}>
<div
style={{
width: `${collapsed ? "27px" : "100%"}`,
overflow: "hidden",
transition: "width 0.3s linear 0.2s",
}}
>
<img src={logo} />
</div>
</div>
<Menu collapsed={collapsed} />
</>
{
<div
className={styles.diyCollapsed}
style={{
backgroundImage: `url(${Collapse})`,
transform: `translateX(50%) rotateY(${collapsed ? 180 : 0}deg)`,
transition: "transform 0.3s linear 0.2s",
}}
onClick={onToggleCollapsed}
></div>
}
</div>
</Sider>
<Layout>
<Header style={headerStyle}>
<HeaderComponent />
</Header>
<ProLayout
menuRender={false}
style={{ paddingTop: 48 }}
ErrorBoundary={CustomBoundary}
headerRender={false}
>
{!selectMenuKey.some((item) => item?.includes("dashboard")) && (
<Breadcrumb />
)}
<Outlet />
</ProLayout>
</Layout>
</Layout>
);
};
export default Index;