2025-06-22 11:34:32 +08:00

252 lines
8.3 KiB
TypeScript

'use client'
import Link from 'next/link'
import { useState, useEffect } from 'react'
import { usePathname, useRouter } from 'next/navigation'
import { User, ShoppingCart, Menu, X } from 'lucide-react'
interface User {
id: string
email: string
username: string
name?: string
isAdmin: boolean
}
export function Navbar() {
const [user, setUser] = useState<User | null>(null)
const [isMenuOpen, setIsMenuOpen] = useState(false)
const pathname = usePathname()
const router = useRouter()
useEffect(() => {
// 检查用户登录状态
const checkUserStatus = () => {
const token = localStorage.getItem('token')
if (token) {
const userData = localStorage.getItem('user')
if (userData) {
setUser(JSON.parse(userData))
}
} else {
setUser(null)
}
}
checkUserStatus()
// 监听localStorage变化
const handleStorageChange = (e: StorageEvent) => {
if (e.key === 'user' || e.key === 'token') {
checkUserStatus()
}
}
// 监听自定义用户更新事件
const handleUserUpdate = () => {
checkUserStatus()
}
window.addEventListener('storage', handleStorageChange)
window.addEventListener('user-updated', handleUserUpdate)
return () => {
window.removeEventListener('storage', handleStorageChange)
window.removeEventListener('user-updated', handleUserUpdate)
}
}, [])
const handleLogout = () => {
localStorage.removeItem('token')
localStorage.removeItem('user')
setUser(null)
// 触发用户更新事件
window.dispatchEvent(new Event('user-updated'))
router.push('/')
}
// 检查当前路径是否匹配
const isActive = (path: string) => {
if (path === '/') {
return pathname === '/'
}
return pathname.startsWith(path)
}
// 导航链接样式
const getLinkStyle = (path: string) => {
return isActive(path)
? 'text-blue-600 font-medium'
: 'text-gray-700 hover:text-blue-600'
}
return (
<nav className="bg-white shadow-md sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo */}
<Link href="/" className="text-2xl font-bold text-blue-600">
PC DIY商城
</Link> {/* Desktop Navigation */}
<div className="hidden md:flex space-x-8">
<Link href="/" className={getLinkStyle('/')}>
</Link>
<Link href="/components" className={getLinkStyle('/components')}>
</Link>
<Link href="/build" className={getLinkStyle('/build')}>
</Link>
</div>
{/* User Actions */}
<div className="hidden md:flex items-center space-x-4">
{user ? (
<div className="flex items-center space-x-4">
<Link href="/cart" className="text-gray-700 hover:text-blue-600">
<ShoppingCart className="h-6 w-6" />
</Link>
<div className="relative group">
<button className="flex items-center space-x-2 text-gray-700 hover:text-blue-600">
<User className="h-6 w-6" />
<span>{user.name || user.username}</span>
</button>
<div className="absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
<Link href="/profile" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
</Link>
<Link href="/orders" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
</Link>
{user.isAdmin && (
<Link href="/admin" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">
</Link>
)}
<button
onClick={handleLogout}
className="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
>
退
</button>
</div>
</div>
</div>
) : (
<div className="flex items-center space-x-4">
<Link
href="/login"
className="text-gray-700 hover:text-blue-600"
>
</Link>
<Link
href="/register"
className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700"
>
</Link>
</div>
)}
</div>
{/* Mobile menu button */}
<div className="md:hidden">
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="text-gray-700 hover:text-blue-600"
>
{isMenuOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
</button>
</div>
</div> {/* Mobile Navigation */}
{isMenuOpen && (
<div className="md:hidden">
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3">
<Link
href="/"
className={`block px-3 py-2 ${getLinkStyle('/')}`}
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/components"
className={`block px-3 py-2 ${getLinkStyle('/components')}`}
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/build"
className={`block px-3 py-2 ${getLinkStyle('/build')}`}
onClick={() => setIsMenuOpen(false)}
>
</Link>
{user ? (
<>
<Link
href="/cart"
className="block px-3 py-2 text-gray-700 hover:text-blue-600"
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/profile"
className="block px-3 py-2 text-gray-700 hover:text-blue-600"
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/orders"
className="block px-3 py-2 text-gray-700 hover:text-blue-600"
onClick={() => setIsMenuOpen(false)}
>
</Link>
{user.isAdmin && (
<Link
href="/admin"
className="block px-3 py-2 text-gray-700 hover:text-blue-600"
onClick={() => setIsMenuOpen(false)}
>
</Link>
)}
<button
onClick={handleLogout}
className="block w-full text-left px-3 py-2 text-gray-700 hover:text-blue-600"
>
退
</button>
</>
) : (
<>
<Link
href="/login"
className="block px-3 py-2 text-gray-700 hover:text-blue-600"
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/register"
className="block px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
onClick={() => setIsMenuOpen(false)}
>
</Link>
</>
)}
</div>
</div>
)}
</div>
</nav>
)
}