@@ -8,11 +8,13 @@ import SystemLogs from './pages/SystemLogs'
88import TokensPage from './pages/TokensPage'
99import LoginPage from './pages/LoginPage'
1010import { authApi , User } from './lib/api'
11- import { LogOut } from 'lucide-react'
11+ import { LogOut , Menu , X } from 'lucide-react'
1212import { Button } from './components/ui/button'
13+ import { Sheet , SheetContent , SheetTrigger } from './components/ui/sheet'
1314
1415function Navigation ( { user, onLogout, onRefreshUser } : { user : User | null ; onLogout : ( ) => void ; onRefreshUser : ( ) => void } ) {
1516 const location = useLocation ( )
17+ const [ open , setOpen ] = useState ( false )
1618
1719 // 当路由变化时,检查是否需要刷新用户信息
1820 useEffect ( ( ) => {
@@ -26,74 +28,98 @@ function Navigation({ user, onLogout, onRefreshUser }: { user: User | null; onLo
2628 return location . pathname === path
2729 }
2830
31+ const navLinks = [
32+ { path : '/' , label : '下载任务' } ,
33+ { path : '/plugins' , label : '插件管理' } ,
34+ { path : '/settings' , label : '系统配置' } ,
35+ { path : '/logs' , label : '系统日志' } ,
36+ { path : '/tokens' , label : 'API Token' } ,
37+ ]
38+
2939 return (
30- < nav className = "border-b bg-card" >
40+ < nav className = "border-b bg-card sticky top-0 z-50 " >
3141 < div className = "container mx-auto px-4" >
3242 < div className = "flex h-16 items-center justify-between" >
33- < div className = "flex items-center space-x-8" >
34- < div className = "flex items-center space-x-2" >
35- < h1 className = "text-xl font-bold" > 🪹 MyNest</ h1 >
36- < span className = "text-sm text-muted-foreground" > 链接的归巢</ span >
37- </ div >
38- < div className = "flex items-center space-x-6" >
39- < Link
40- to = "/"
41- className = { `text-sm font-medium transition-colors hover:text-primary ${
42- isActive ( '/' ) ? 'text-primary' : 'text-muted-foreground'
43- } `}
44- >
45- 下载任务
46- </ Link >
47- < Link
48- to = "/plugins"
49- className = { `text-sm font-medium transition-colors hover:text-primary ${
50- isActive ( '/plugins' ) ? 'text-primary' : 'text-muted-foreground'
51- } `}
52- >
53- 插件管理
54- </ Link >
55- < Link
56- to = "/settings"
57- className = { `text-sm font-medium transition-colors hover:text-primary ${
58- isActive ( '/settings' ) ? 'text-primary' : 'text-muted-foreground'
59- } `}
60- >
61- 系统配置
62- </ Link >
63- < Link
64- to = "/logs"
65- className = { `text-sm font-medium transition-colors hover:text-primary ${
66- isActive ( '/logs' ) ? 'text-primary' : 'text-muted-foreground'
67- } `}
68- >
69- 系统日志
70- </ Link >
43+ { /* Logo */ }
44+ < Link to = "/" className = "flex items-center space-x-2" >
45+ < h1 className = "text-xl font-bold" > 🪹 MyNest</ h1 >
46+ < span className = "hidden sm:inline text-sm text-muted-foreground" > 链接的归巢</ span >
47+ </ Link >
48+
49+ { /* 桌面端导航 */ }
50+ < div className = "hidden md:flex items-center space-x-6" >
51+ { navLinks . map ( ( link ) => (
7152 < Link
72- to = "/tokens"
53+ key = { link . path }
54+ to = { link . path }
7355 className = { `text-sm font-medium transition-colors hover:text-primary ${
74- isActive ( '/tokens' ) ? 'text-primary' : 'text-muted-foreground'
56+ isActive ( link . path ) ? 'text-primary' : 'text-muted-foreground'
7557 } `}
7658 >
77- API Token
59+ { link . label }
7860 </ Link >
79- </ div >
61+ ) ) }
8062 </ div >
81- < div className = "flex items-center space-x-4" >
63+
64+ { /* 用户信息和移动端菜单 */ }
65+ < div className = "flex items-center space-x-2" >
8266 { user && (
8367 < >
84- < span className = "text-sm text-muted-foreground" >
68+ < span className = "hidden sm:inline text-sm text-muted-foreground" >
8569 { user . username }
8670 </ span >
8771 < Button
8872 variant = "ghost"
8973 size = "sm"
9074 onClick = { onLogout }
75+ className = "hidden sm:flex"
9176 >
9277 < LogOut className = "w-4 h-4 mr-2" />
9378 退出
9479 </ Button >
9580 </ >
9681 ) }
82+
83+ { /* 移动端汉堡菜单 */ }
84+ < Sheet open = { open } onOpenChange = { setOpen } >
85+ < SheetTrigger asChild >
86+ < Button variant = "ghost" size = "sm" className = "md:hidden" >
87+ < Menu className = "h-5 w-5" />
88+ </ Button >
89+ </ SheetTrigger >
90+ < SheetContent side = "right" className = "w-64" >
91+ < div className = "flex flex-col space-y-4 mt-8" >
92+ { user && (
93+ < div className = "pb-4 border-b" >
94+ < p className = "text-sm font-medium" > { user . username } </ p >
95+ </ div >
96+ ) }
97+ { navLinks . map ( ( link ) => (
98+ < Link
99+ key = { link . path }
100+ to = { link . path }
101+ onClick = { ( ) => setOpen ( false ) }
102+ className = { `text-base font-medium transition-colors hover:text-primary py-2 ${
103+ isActive ( link . path ) ? 'text-primary' : 'text-muted-foreground'
104+ } `}
105+ >
106+ { link . label }
107+ </ Link >
108+ ) ) }
109+ < Button
110+ variant = "ghost"
111+ onClick = { ( ) => {
112+ setOpen ( false )
113+ onLogout ( )
114+ } }
115+ className = "justify-start px-0 text-base font-medium text-muted-foreground hover:text-primary"
116+ >
117+ < LogOut className = "w-4 h-4 mr-2" />
118+ 退出
119+ </ Button >
120+ </ div >
121+ </ SheetContent >
122+ </ Sheet >
97123 </ div >
98124 </ div >
99125 </ div >
@@ -159,9 +185,9 @@ function App() {
159185 path = "/*"
160186 element = {
161187 < ProtectedRoute >
162- < div className = "min-h-screen bg-background" >
188+ < div className = "min-h-screen bg-background overflow-x-hidden " >
163189 < Navigation user = { user } onLogout = { handleLogout } onRefreshUser = { checkAuth } />
164- < main className = "container mx-auto px-4 py-8 " >
190+ < main className = "container mx-auto px-4 sm:px-6 py-6 sm:py-8 max-w-full " >
165191 < Routes >
166192 < Route path = "/" element = { < TasksPage /> } />
167193 < Route path = "/plugins" element = { < PluginsPage /> } />
0 commit comments