refactor: 重构页面布局,样式
This commit is contained in:
+61
-42
@@ -2,7 +2,6 @@ import { Outlet, Navigate, useNavigate, Link, useLocation } from 'react-router-d
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { logoutApi } from '../api/auth';
|
||||
import {
|
||||
Radio,
|
||||
LayoutDashboard,
|
||||
ListMusic,
|
||||
Mic2,
|
||||
@@ -53,47 +52,56 @@ export default function AdminLayout() {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-slate-50 dark:bg-slate-950 overflow-hidden">
|
||||
<div className="flex h-screen bg-[#FAF5E6] dark:bg-[#1A1A1A] overflow-hidden font-sans warm-noise">
|
||||
{/* Sidebar */}
|
||||
<aside className="fixed inset-y-0 left-0 z-50 w-64 bg-slate-900 text-slate-100 hidden md:flex flex-col shadow-xl">
|
||||
<div className="flex items-center h-16 px-6 border-b border-slate-800 shrink-0">
|
||||
<div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center mr-3 shadow-lg shadow-primary/20">
|
||||
<Radio className="w-5 h-5 text-white" />
|
||||
<aside className="fixed inset-y-0 left-0 z-50 w-64 sidebar-noise text-slate-100 hidden md:flex flex-col shadow-2xl border-r border-white/5">
|
||||
<div className="flex items-center h-20 px-6 border-b border-white/5 shrink-0">
|
||||
<div className="w-12 h-12 rounded-2xl overflow-hidden mr-3 shadow-lg shadow-orange-500/20 ring-1 ring-white/20 flex items-center justify-center bg-white">
|
||||
<img src="/favicon.jpg" alt="logo" className="w-full h-full object-cover p-1 bg-white" />
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-black text-lg tracking-tight leading-none text-white">早安和傍晚</span>
|
||||
<span className="text-[10px] uppercase tracking-[0.2em] text-white/40 mt-1">广播控制台</span>
|
||||
</div>
|
||||
<span className="font-bold text-lg tracking-wide uppercase">早安电台</span>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 px-4 py-6 space-y-2 overflow-y-auto custom-scrollbar">
|
||||
<div className="flex-1 px-4 py-8 space-y-4 overflow-y-auto custom-scrollbar">
|
||||
{navItems.map((item) => {
|
||||
const isActive = location.pathname === item.path || (item.path !== '/' && location.pathname.startsWith(item.path));
|
||||
return (
|
||||
<Link key={item.path} to={item.path}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className={`w-full justify-start h-11 px-4 rounded-xl transition-all duration-200 group ${isActive
|
||||
? 'bg-primary text-primary-foreground shadow-lg shadow-primary/10'
|
||||
: 'text-slate-400 hover:text-slate-100 hover:bg-slate-800'
|
||||
className={`w-full justify-start h-12 px-4 rounded-2xl transition-all duration-300 group relative overflow-hidden ${isActive
|
||||
? 'text-white bg-white/10 sidebar-halo'
|
||||
: 'text-white/50 hover:text-white hover:bg-white/5'
|
||||
}`}
|
||||
>
|
||||
<item.icon className={`w-5 h-5 mr-3 shrink-0 ${isActive ? 'text-white' : 'group-hover:text-primary'}`} />
|
||||
<span className="font-medium">{item.name}</span>
|
||||
<item.icon className={`w-5 h-5 mr-3 shrink-0 transition-transform duration-300 ${isActive ? 'text-[#D28F4F]' : 'group-hover:text-[#D28F4F] group-hover:scale-110'}`} />
|
||||
<span className="font-bold tracking-wide">{item.name}</span>
|
||||
{isActive && (
|
||||
<div className="ml-auto w-1.5 h-1.5 rounded-full bg-[#D28F4F] shadow-[0_0_12px_#D28F4F]" />
|
||||
)}
|
||||
</Button>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="p-4 border-t border-slate-800 shrink-0">
|
||||
<div className="bg-slate-800/50 rounded-2xl p-3 flex items-center space-x-3">
|
||||
<Avatar className="h-10 w-10 ring-2 ring-slate-700">
|
||||
<AvatarImage src={userInfo?.avatar || ''} />
|
||||
<AvatarFallback className="bg-slate-700 text-slate-100">
|
||||
<UserIcon className="w-5 h-5" />
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="p-4 border-t border-white/5 shrink-0">
|
||||
<div className="bg-white/5 backdrop-blur-md rounded-[2rem] p-4 flex items-center space-x-3 border border-white/10">
|
||||
<div className="relative">
|
||||
<Avatar className="h-10 w-10 ring-2 ring-white/10">
|
||||
<AvatarImage src={userInfo?.avatar || ''} />
|
||||
<AvatarFallback className="bg-white/10 text-white/80">
|
||||
<UserIcon className="w-5 h-5" />
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="absolute -bottom-0.5 -right-0.5 w-3 h-3 bg-emerald-500 rounded-full border-2 border-[#263238] animate-pulse" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-semibold truncate">{userInfo?.nickName || '管理员'}</p>
|
||||
<p className="text-xs text-slate-500 truncate">{userInfo?.account || 'admin'}</p>
|
||||
<p className="text-sm font-black truncate text-white">{userInfo?.nickName || '管理员'}</p>
|
||||
<p className="text-[10px] text-white/30 uppercase tracking-tighter truncate font-bold">{userInfo?.account || 'admin'}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,37 +110,47 @@ export default function AdminLayout() {
|
||||
{/* Main Area */}
|
||||
<div className="flex-1 md:ml-64 flex flex-col h-full overflow-hidden relative">
|
||||
{/* Navbar */}
|
||||
<header className="h-16 flex items-center justify-between px-8 bg-white dark:bg-slate-900 border-b shrink-0 z-40">
|
||||
<header className="h-20 flex items-center justify-between px-8 bg-[#FAF5E6]/60 dark:bg-black/40 backdrop-blur-xl border-b border-[#4A3A2C]/10 shrink-0 z-40 sticky top-0 warm-noise">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="md:hidden">
|
||||
<Radio className="w-6 h-6 text-primary" />
|
||||
<img src="/favicon.jpg" alt="logo" className="w-8 h-8 rounded-lg object-cover" />
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<h2 className="text-[10px] font-black text-[#D28F4F]/60 uppercase tracking-[0.3em] leading-none mb-1">电台工作台</h2>
|
||||
<p className="text-xl font-black tracking-tight text-[#4A3A2C]">
|
||||
{navItems.find(i => i.path === location.pathname)?.name || '控制台'}
|
||||
</p>
|
||||
</div>
|
||||
<h2 className="text-sm font-medium text-slate-500 uppercase tracking-widest hidden sm:block">早安电台后台系统</h2>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center space-x-6">
|
||||
<div className="flex items-center space-x-2 bg-[#D28F4F]/5 border border-[#D28F4F]/10 px-4 py-2 rounded-2xl">
|
||||
<div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse shadow-[0_0_8px_#10b981]" />
|
||||
<span className="text-[10px] font-black text-[#8C7E6C] uppercase tracking-widest">系统在线</span>
|
||||
</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-10 px-3 rounded-xl hover:bg-slate-100 dark:hover:bg-slate-800 flex items-center space-x-2">
|
||||
<div className="text-right hidden sm:block">
|
||||
<p className="text-sm font-medium leading-none">{userInfo?.nickName || '管理员'}</p>
|
||||
</div>
|
||||
<ChevronDown className="w-4 h-4 text-slate-400" />
|
||||
<Button variant="ghost" className="h-12 px-2 rounded-2xl hover:bg-white/40 flex items-center space-x-3 transition-all">
|
||||
<Avatar className="h-10 w-10 ring-2 ring-[#D28F4F]/20 shadow-lg">
|
||||
<AvatarImage src={userInfo?.avatar || ''} />
|
||||
<AvatarFallback className="bg-[#FAF5E6]"><UserIcon className="text-[#D28F4F]" /></AvatarFallback>
|
||||
</Avatar>
|
||||
<ChevronDown className="w-4 h-4 text-[#8C7E6C]" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56 mt-2 rounded-xl p-1" align="end" forceMount>
|
||||
<DropdownMenuLabel className="font-normal px-2 py-3">
|
||||
<DropdownMenuContent className="w-64 mt-2 rounded-[2.5rem] p-2 glass-card warm-noise border-[#D28F4F]/10" align="end">
|
||||
<DropdownMenuLabel className="font-normal px-4 py-6">
|
||||
<div className="flex flex-col space-y-1">
|
||||
<p className="text-sm font-bold text-slate-900 dark:text-slate-100">{userInfo?.nickName || '管理员'}</p>
|
||||
<p className="text-xs text-slate-500">{userInfo?.account || 'admin'}</p>
|
||||
<p className="text-lg font-black text-[#4A3A2C]">{userInfo?.nickName || '管理员'}</p>
|
||||
<p className="text-xs text-[#8C7E6C] font-bold tracking-wide">{userInfo?.account || 'admin'}</p>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuSeparator className="bg-[#4A3A2C]/5" />
|
||||
<DropdownMenuItem
|
||||
onClick={handleLogout}
|
||||
className="cursor-pointer text-rose-500 focus:bg-rose-50 focus:text-rose-600 rounded-lg p-2 font-medium"
|
||||
className="cursor-pointer text-rose-600 focus:bg-rose-50 focus:text-rose-700 rounded-2xl p-4 font-black transition-all"
|
||||
>
|
||||
<LogOut className="mr-3 h-4 w-4" />
|
||||
<span>安全退出</span>
|
||||
<LogOut className="mr-3 h-5 w-5" />
|
||||
<span>安全退出系统</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
@@ -140,8 +158,9 @@ export default function AdminLayout() {
|
||||
</header>
|
||||
|
||||
{/* Page Content */}
|
||||
<main className="flex-1 overflow-y-auto p-4 md:p-10 bg-slate-50/50 dark:bg-slate-950/50 scroll-smooth">
|
||||
<div className="max-w-7xl mx-auto h-full">
|
||||
<main className="flex-1 overflow-y-auto p-6 md:p-8 scroll-smooth relative">
|
||||
<div className="absolute top-0 left-0 w-full h-[500px] bg-gradient-to-b from-[#D28F4F]/5 to-transparent pointer-events-none" />
|
||||
<div className="max-w-7xl mx-auto h-full relative">
|
||||
<Outlet />
|
||||
</div>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user