2024-07-25 18:49:59 +08:00
|
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
|
|
|
import { NavLink, useLocation } from 'react-router-dom';
|
|
|
|
|
import SidebarLinkGroup from './SidebarLinkGroup';
|
|
|
|
|
import Logo from '../../images/logo/logo.svg';
|
2024-08-08 15:27:57 +08:00
|
|
|
import { BiEditAlt, BiFolderOpen, BiHomeSmile, BiSliderAlt } from "react-icons/bi";
|
2024-08-05 02:42:35 +08:00
|
|
|
import { BiCategoryAlt } from "react-icons/bi";
|
2024-08-14 19:17:32 +08:00
|
|
|
import { LiaRssSolid } from "react-icons/lia";
|
2024-08-15 16:57:03 +08:00
|
|
|
import { IoIosStats } from "react-icons/io";
|
2024-07-25 18:49:59 +08:00
|
|
|
|
|
|
|
|
interface SidebarProps {
|
|
|
|
|
sidebarOpen: boolean;
|
|
|
|
|
setSidebarOpen: (arg: boolean) => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
|
|
|
|
|
const location = useLocation();
|
|
|
|
|
const { pathname } = location;
|
|
|
|
|
|
|
|
|
|
const trigger = useRef<any>(null);
|
|
|
|
|
const sidebar = useRef<any>(null);
|
|
|
|
|
|
|
|
|
|
const storedSidebarExpanded = localStorage.getItem('sidebar-expanded');
|
|
|
|
|
const [sidebarExpanded, setSidebarExpanded] = useState(
|
|
|
|
|
storedSidebarExpanded === null ? false : storedSidebarExpanded === 'true'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// close on click outside
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const clickHandler = ({ target }: MouseEvent) => {
|
|
|
|
|
if (!sidebar.current || !trigger.current) return;
|
|
|
|
|
if (
|
|
|
|
|
!sidebarOpen ||
|
|
|
|
|
sidebar.current.contains(target) ||
|
|
|
|
|
trigger.current.contains(target)
|
|
|
|
|
)
|
|
|
|
|
return;
|
|
|
|
|
setSidebarOpen(false);
|
|
|
|
|
};
|
|
|
|
|
document.addEventListener('click', clickHandler);
|
|
|
|
|
return () => document.removeEventListener('click', clickHandler);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// close if the esc key is pressed
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const keyHandler = ({ keyCode }: KeyboardEvent) => {
|
|
|
|
|
if (!sidebarOpen || keyCode !== 27) return;
|
|
|
|
|
setSidebarOpen(false);
|
|
|
|
|
};
|
|
|
|
|
document.addEventListener('keydown', keyHandler);
|
|
|
|
|
return () => document.removeEventListener('keydown', keyHandler);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
localStorage.setItem('sidebar-expanded', sidebarExpanded.toString());
|
|
|
|
|
if (sidebarExpanded) {
|
|
|
|
|
document.querySelector('body')?.classList.add('sidebar-expanded');
|
|
|
|
|
} else {
|
|
|
|
|
document.querySelector('body')?.classList.remove('sidebar-expanded');
|
|
|
|
|
}
|
|
|
|
|
}, [sidebarExpanded]);
|
|
|
|
|
|
2024-08-05 02:42:35 +08:00
|
|
|
// 导航项样式
|
|
|
|
|
const sidebarItemSty = "group relative flex items-center gap-2.5 rounded-sm py-2 px-4 font-medium text-bodydark1 duration-300 ease-in-out hover:bg-graydark dark:hover:bg-meta-4"
|
|
|
|
|
// 导航选中样式
|
|
|
|
|
const sidebarItemActiveSty = "bg-graydark dark:bg-meta-4"
|
|
|
|
|
|
2024-08-08 15:27:57 +08:00
|
|
|
const Arrow = ({ open }: { open: boolean }) => {
|
|
|
|
|
return <svg
|
|
|
|
|
className={`absolute right-4 top-1/2 -translate-y-1/2 fill-current ${open && 'rotate-180'
|
|
|
|
|
}`}
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 20 20"
|
|
|
|
|
fill="none"
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
>
|
|
|
|
|
<path
|
|
|
|
|
fillRule="evenodd"
|
|
|
|
|
clipRule="evenodd"
|
|
|
|
|
d="M4.41107 6.9107C4.73651 6.58527 5.26414 6.58527 5.58958 6.9107L10.0003 11.3214L14.4111 6.91071C14.7365 6.58527 15.2641 6.58527 15.5896 6.91071C15.915 7.23614 15.915 7.76378 15.5896 8.08922L10.5896 13.0892C10.2641 13.4147 9.73651 13.4147 9.41107 13.0892L4.41107 8.08922C4.08563 7.76378 4.08563 7.23614 4.41107 6.9107Z"
|
|
|
|
|
fill=""
|
|
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 18:49:59 +08:00
|
|
|
return (
|
|
|
|
|
<aside
|
|
|
|
|
ref={sidebar}
|
2024-07-25 20:22:04 +08:00
|
|
|
className={`absolute left-0 top-0 z-9999 flex h-screen w-64 flex-col overflow-y-hidden bg-black duration-300 ease-linear dark:bg-boxdark lg:static lg:translate-x-0 ${sidebarOpen ? 'translate-x-0' : '-translate-x-full'
|
2024-07-25 18:49:59 +08:00
|
|
|
}`}
|
|
|
|
|
>
|
2024-07-25 20:22:04 +08:00
|
|
|
<div className="flex justify-center items-center justify-between gap-2 px-6 py-5.5 lg:py-6.5">
|
2024-07-25 18:49:59 +08:00
|
|
|
<NavLink to="/">
|
|
|
|
|
<img src={Logo} alt="Logo" />
|
|
|
|
|
</NavLink>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
ref={trigger}
|
|
|
|
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
|
|
|
aria-controls="sidebar"
|
|
|
|
|
aria-expanded={sidebarOpen}
|
|
|
|
|
className="block lg:hidden"
|
|
|
|
|
>
|
|
|
|
|
<svg
|
|
|
|
|
className="fill-current"
|
|
|
|
|
width="20"
|
|
|
|
|
height="18"
|
|
|
|
|
viewBox="0 0 20 18"
|
|
|
|
|
fill="none"
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
>
|
|
|
|
|
<path
|
|
|
|
|
d="M19 8.175H2.98748L9.36248 1.6875C9.69998 1.35 9.69998 0.825 9.36248 0.4875C9.02498 0.15 8.49998 0.15 8.16248 0.4875L0.399976 8.3625C0.0624756 8.7 0.0624756 9.225 0.399976 9.5625L8.16248 17.4375C8.31248 17.5875 8.53748 17.7 8.76248 17.7C8.98748 17.7 9.17498 17.625 9.36248 17.475C9.69998 17.1375 9.69998 16.6125 9.36248 16.275L3.02498 9.8625H19C19.45 9.8625 19.825 9.4875 19.825 9.0375C19.825 8.55 19.45 8.175 19 8.175Z"
|
|
|
|
|
fill=""
|
|
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="no-scrollbar flex flex-col overflow-y-auto duration-300 ease-linear">
|
2024-07-25 20:22:04 +08:00
|
|
|
<nav className="py-4 px-4 lg:px-6">
|
2024-07-25 18:49:59 +08:00
|
|
|
<div>
|
|
|
|
|
<h3 className="mb-4 ml-4 text-sm font-semibold text-bodydark2">
|
2024-08-05 02:42:35 +08:00
|
|
|
Menu
|
2024-07-25 18:49:59 +08:00
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<ul className="mb-6 flex flex-col gap-1.5">
|
|
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/"
|
2024-08-05 02:42:35 +08:00
|
|
|
className={`${sidebarItemSty} ${pathname.includes('dashboard') && sidebarItemActiveSty}`}
|
2024-07-25 18:49:59 +08:00
|
|
|
>
|
2024-07-25 23:03:12 +08:00
|
|
|
<BiHomeSmile className='text-[22px]' />
|
2024-07-25 18:49:59 +08:00
|
|
|
仪表盘
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/create"
|
2024-08-05 02:42:35 +08:00
|
|
|
className={`${sidebarItemSty} ${pathname.includes('create') && sidebarItemActiveSty}`}
|
2024-07-25 18:49:59 +08:00
|
|
|
>
|
2024-08-05 02:42:35 +08:00
|
|
|
<BiEditAlt className='text-[22px]' />
|
2024-07-25 18:49:59 +08:00
|
|
|
创作
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<SidebarLinkGroup
|
2024-08-08 12:47:44 +08:00
|
|
|
activeCondition={false}
|
2024-07-25 18:49:59 +08:00
|
|
|
>
|
|
|
|
|
{(handleClick, open) => {
|
|
|
|
|
return (
|
|
|
|
|
<React.Fragment>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="#"
|
2024-08-08 15:27:57 +08:00
|
|
|
className={`${sidebarItemSty}`}
|
2024-07-25 18:49:59 +08:00
|
|
|
onClick={(e) => {
|
|
|
|
|
e.preventDefault();
|
2024-08-08 15:27:57 +08:00
|
|
|
|
2024-07-25 18:49:59 +08:00
|
|
|
sidebarExpanded
|
|
|
|
|
? handleClick()
|
|
|
|
|
: setSidebarExpanded(true);
|
|
|
|
|
}}
|
|
|
|
|
>
|
2024-08-08 12:47:44 +08:00
|
|
|
<BiCategoryAlt className='text-[22px]' />
|
2024-08-05 02:42:35 +08:00
|
|
|
管理
|
2024-08-08 15:27:57 +08:00
|
|
|
<Arrow open={open} />
|
2024-07-25 18:49:59 +08:00
|
|
|
</NavLink>
|
2024-08-08 15:27:57 +08:00
|
|
|
|
2024-07-25 18:49:59 +08:00
|
|
|
<div
|
|
|
|
|
className={`translate transform overflow-hidden ${!open && 'hidden'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<ul className="mt-4 mb-5.5 flex flex-col gap-2.5 pl-6">
|
|
|
|
|
<li>
|
|
|
|
|
<NavLink
|
2024-08-06 21:02:06 +08:00
|
|
|
to="/article"
|
2024-07-25 18:49:59 +08:00
|
|
|
className={({ isActive }) =>
|
|
|
|
|
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
|
|
|
|
|
(isActive && '!text-white')
|
|
|
|
|
}
|
|
|
|
|
>
|
2024-08-06 21:02:06 +08:00
|
|
|
文章管理
|
2024-07-25 18:49:59 +08:00
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-08-08 12:47:44 +08:00
|
|
|
|
2024-08-08 23:24:20 +08:00
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/tag"
|
|
|
|
|
className={({ isActive }) =>
|
|
|
|
|
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
|
|
|
|
|
(isActive && '!text-white')
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
标签管理
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
|
|
|
|
|
2024-07-25 18:49:59 +08:00
|
|
|
<li>
|
|
|
|
|
<NavLink
|
2024-08-06 23:21:42 +08:00
|
|
|
to="/comment"
|
2024-07-25 18:49:59 +08:00
|
|
|
className={({ isActive }) =>
|
|
|
|
|
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
|
|
|
|
|
(isActive && '!text-white')
|
|
|
|
|
}
|
|
|
|
|
>
|
2024-08-06 23:21:42 +08:00
|
|
|
评论管理
|
2024-07-25 18:49:59 +08:00
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-08-07 19:35:28 +08:00
|
|
|
|
2024-08-08 12:47:44 +08:00
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/cate"
|
|
|
|
|
className={({ isActive }) =>
|
|
|
|
|
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
|
|
|
|
|
(isActive && '!text-white')
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
分类管理
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
|
|
|
|
|
2024-08-07 19:35:28 +08:00
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/web"
|
|
|
|
|
className={({ isActive }) =>
|
|
|
|
|
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
|
|
|
|
|
(isActive && '!text-white')
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
网站管理
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-08-08 13:46:28 +08:00
|
|
|
|
|
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/swiper"
|
|
|
|
|
className={({ isActive }) =>
|
|
|
|
|
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
|
|
|
|
|
(isActive && '!text-white')
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
轮播图管理
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-07-25 18:49:59 +08:00
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
{/* <!-- Dropdown Menu End --> */}
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
</SidebarLinkGroup>
|
2024-08-08 15:27:57 +08:00
|
|
|
|
|
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/setup"
|
|
|
|
|
className={`${sidebarItemSty} ${pathname.includes('setup') && sidebarItemActiveSty}`}
|
|
|
|
|
>
|
|
|
|
|
<BiSliderAlt className='text-[22px]' />
|
|
|
|
|
系统
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-07-25 18:49:59 +08:00
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="mb-4 ml-4 text-sm font-semibold text-bodydark2">
|
2024-08-05 02:42:35 +08:00
|
|
|
New
|
2024-07-25 18:49:59 +08:00
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<ul className="mb-6 flex flex-col gap-1.5">
|
2024-08-14 14:46:08 +08:00
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/rss"
|
2024-08-15 15:39:37 +08:00
|
|
|
className={`${sidebarItemSty} ${pathname.includes('rss') && 'bg-graydark dark:bg-meta-4'
|
2024-08-14 14:46:08 +08:00
|
|
|
}`}
|
|
|
|
|
>
|
2024-08-14 19:17:32 +08:00
|
|
|
<LiaRssSolid className='text-[22px]' />
|
2024-08-14 14:46:08 +08:00
|
|
|
订阅中心
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
|
|
|
|
|
2024-07-25 18:49:59 +08:00
|
|
|
<li>
|
|
|
|
|
<NavLink
|
|
|
|
|
to="/chart"
|
2024-08-05 02:42:35 +08:00
|
|
|
className={`${sidebarItemSty} ${pathname.includes('chart') && 'bg-graydark dark:bg-meta-4'
|
2024-07-25 18:49:59 +08:00
|
|
|
}`}
|
|
|
|
|
>
|
2024-08-05 02:42:35 +08:00
|
|
|
<BiFolderOpen className='text-[22px]' />
|
|
|
|
|
文件系统
|
2024-07-25 18:49:59 +08:00
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-08-15 15:39:37 +08:00
|
|
|
|
|
|
|
|
<li>
|
|
|
|
|
<NavLink
|
2024-08-15 16:57:03 +08:00
|
|
|
to="/stats"
|
|
|
|
|
className={`${sidebarItemSty} ${pathname.includes('stats') && 'bg-graydark dark:bg-meta-4'
|
2024-08-15 15:39:37 +08:00
|
|
|
}`}
|
|
|
|
|
>
|
2024-08-15 16:57:03 +08:00
|
|
|
<IoIosStats className='text-[22px]' />
|
2024-08-15 15:39:37 +08:00
|
|
|
数据可视化
|
|
|
|
|
</NavLink>
|
|
|
|
|
</li>
|
2024-07-25 18:49:59 +08:00
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</nav>
|
|
|
|
|
</div>
|
|
|
|
|
</aside>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Sidebar;
|