20c6e0d7c2
- 从导航区移到底部按钮组,夹在主题切换与退出登录中间 - 仍为整页跳转回用户端官网首页 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
import { Link, NavLink, useNavigate } from 'react-router-dom'
|
|
import {
|
|
BarChart3,
|
|
FileText,
|
|
Home,
|
|
LayoutDashboard,
|
|
LogOut,
|
|
Moon,
|
|
Sun,
|
|
X,
|
|
} from 'lucide-react'
|
|
import { logout } from '@/api/auth'
|
|
import { useTheme } from '@/components/theme-provider'
|
|
import { LogoMark } from '@/components/logo'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
const NAV = [
|
|
{ to: '/', label: '仪表盘', icon: LayoutDashboard, end: true },
|
|
{ to: '/posts', label: '文章', icon: FileText, end: false },
|
|
{ to: '/visits', label: '访问统计', icon: BarChart3, end: false },
|
|
]
|
|
|
|
interface Props {
|
|
open: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
export function AdminSidebar({ open, onClose }: Props) {
|
|
const navigate = useNavigate()
|
|
const { resolved, setTheme } = useTheme()
|
|
|
|
const itemCls = ({ isActive }: { isActive: boolean }) =>
|
|
cn(
|
|
'flex items-center gap-3 rounded-lg px-3 py-2.5 text-[14px] transition-colors',
|
|
isActive
|
|
? 'bg-accent-soft font-medium text-accent-ink'
|
|
: 'text-ink-2 hover:bg-ground hover:text-ink',
|
|
)
|
|
|
|
const bottomBtnCls =
|
|
'flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-[14px] text-ink-2 transition-colors hover:bg-ground hover:text-ink'
|
|
|
|
return (
|
|
<>
|
|
{open && (
|
|
<div
|
|
className="fixed inset-0 z-40 bg-black/40 md:hidden"
|
|
onClick={onClose}
|
|
aria-hidden="true"
|
|
/>
|
|
)}
|
|
<aside
|
|
className={cn(
|
|
'fixed inset-y-0 left-0 z-50 flex w-[220px] flex-col border-r border-hairline bg-surface transition-transform md:translate-x-0',
|
|
open ? 'translate-x-0' : '-translate-x-full',
|
|
)}
|
|
>
|
|
<div className="flex h-16 items-center justify-between border-b border-hairline px-5">
|
|
<Link
|
|
to="/"
|
|
onClick={onClose}
|
|
className="flex items-center gap-2.5 font-mono text-[14px] font-semibold"
|
|
>
|
|
<LogoMark size={24} />
|
|
sundynix <em className="not-italic text-accent">admin</em>
|
|
</Link>
|
|
<button
|
|
type="button"
|
|
onClick={onClose}
|
|
aria-label="关闭菜单"
|
|
className="text-ink-2 md:hidden"
|
|
>
|
|
<X className="size-5" />
|
|
</button>
|
|
</div>
|
|
|
|
<nav className="flex-1 space-y-1 px-3 py-4">
|
|
{NAV.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
end={item.end}
|
|
onClick={onClose}
|
|
className={itemCls}
|
|
>
|
|
<item.icon className="size-[18px]" />
|
|
{item.label}
|
|
</NavLink>
|
|
))}
|
|
</nav>
|
|
|
|
<div className="space-y-1 border-t border-hairline p-3">
|
|
<button
|
|
type="button"
|
|
onClick={() => setTheme(resolved === 'dark' ? 'light' : 'dark')}
|
|
className={bottomBtnCls}
|
|
>
|
|
{resolved === 'dark' ? (
|
|
<Sun className="size-[18px]" />
|
|
) : (
|
|
<Moon className="size-[18px]" />
|
|
)}
|
|
{resolved === 'dark' ? '浅色模式' : '深色模式'}
|
|
</button>
|
|
{/* 整页跳转回用户端官网首页(生产同源) */}
|
|
<a href="/" onClick={onClose} className={bottomBtnCls}>
|
|
<Home className="size-[18px]" /> 返回主页
|
|
</a>
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
logout()
|
|
navigate('/login')
|
|
}}
|
|
className={bottomBtnCls}
|
|
>
|
|
<LogOut className="size-[18px]" /> 退出登录
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
</>
|
|
)
|
|
}
|