139 lines
5.3 KiB
TypeScript
139 lines
5.3 KiB
TypeScript
import {useEffect, useState} from 'react'
|
|
import {Link} from 'react-router-dom'
|
|
import {LogOut, Menu, Shield, Sparkles, User} from 'lucide-react'
|
|
import {authApi, type User as UserType} from '../api/auth'
|
|
|
|
export default function Navbar() {
|
|
const [user, setUser] = useState<UserType | null>(null)
|
|
const [showUserMenu, setShowUserMenu] = useState(false)
|
|
|
|
useEffect(() => {
|
|
loadUser()
|
|
}, [])
|
|
|
|
const loadUser = async () => {
|
|
const token = localStorage.getItem('token')
|
|
if (!token) return
|
|
|
|
try {
|
|
const response = await authApi.getUserInfo()
|
|
setUser(response.data)
|
|
} catch (err) {
|
|
console.error('获取用户信息失败:', err)
|
|
localStorage.removeItem('token')
|
|
localStorage.removeItem('refreshToken')
|
|
}
|
|
}
|
|
|
|
const handleLogout = () => {
|
|
localStorage.removeItem('token')
|
|
localStorage.removeItem('refreshToken')
|
|
setUser(null)
|
|
window.location.href = '/'
|
|
}
|
|
|
|
return (
|
|
<nav className="fixed top-4 left-4 right-4 z-50">
|
|
<div className="max-w-7xl mx-auto glass rounded-2xl px-6 py-4">
|
|
<div className="flex items-center justify-between">
|
|
<Link to="/" className="flex items-center gap-2">
|
|
<div className="w-8 h-8 bg-gradient-to-br from-primary to-secondary rounded-lg flex items-center justify-center">
|
|
<Sparkles className="w-5 h-5" />
|
|
</div>
|
|
<span className="text-xl font-semibold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
|
|
云酒馆
|
|
</span>
|
|
</Link>
|
|
|
|
<div className="hidden md:flex items-center gap-6">
|
|
<Link to="/" className="text-sm hover:text-primary transition-colors cursor-pointer">
|
|
首页
|
|
</Link>
|
|
<Link to="/market" className="text-sm hover:text-primary transition-colors cursor-pointer">
|
|
角色广场
|
|
</Link>
|
|
{user && (
|
|
<>
|
|
<Link to="/characters" className="text-sm hover:text-primary transition-colors cursor-pointer">
|
|
角色管理
|
|
</Link>
|
|
<Link to="/presets" className="text-sm hover:text-primary transition-colors cursor-pointer">
|
|
预设管理
|
|
</Link>
|
|
<Link to="/chat" className="text-sm hover:text-primary transition-colors cursor-pointer">
|
|
我的对话
|
|
</Link>
|
|
{user.isAdmin && (
|
|
<Link to="/admin" className="text-sm hover:text-primary transition-colors cursor-pointer flex items-center gap-1">
|
|
<Shield className="w-4 h-4" />
|
|
管理后台
|
|
</Link>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex items-center gap-3">
|
|
{user ? (
|
|
<div className="relative">
|
|
<button
|
|
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
className="flex items-center gap-2 px-4 py-2 glass-hover rounded-lg text-sm cursor-pointer"
|
|
>
|
|
{user.avatar ? (
|
|
<img src={user.avatar} alt={user.nickName} className="w-6 h-6 rounded-full" />
|
|
) : (
|
|
<User className="w-5 h-5" />
|
|
)}
|
|
<span>{user.nickName || user.username}</span>
|
|
</button>
|
|
|
|
{showUserMenu && (
|
|
<div className="absolute right-0 mt-2 w-48 glass rounded-xl overflow-hidden">
|
|
<Link
|
|
to="/profile"
|
|
className="block px-4 py-3 text-sm hover:bg-white/5 cursor-pointer"
|
|
onClick={() => setShowUserMenu(false)}
|
|
>
|
|
个人中心
|
|
</Link>
|
|
{user.isAdmin && (
|
|
<Link
|
|
to="/admin"
|
|
className="block px-4 py-3 text-sm hover:bg-white/5 cursor-pointer flex items-center gap-2"
|
|
onClick={() => setShowUserMenu(false)}
|
|
>
|
|
<Shield className="w-4 h-4" />
|
|
管理后台
|
|
</Link>
|
|
)}
|
|
<button
|
|
onClick={handleLogout}
|
|
className="w-full text-left px-4 py-3 text-sm hover:bg-white/5 cursor-pointer flex items-center gap-2 text-red-400"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
退出登录
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<>
|
|
<Link to="/login" className="hidden md:block px-4 py-2 glass-hover rounded-lg text-sm cursor-pointer">
|
|
登录
|
|
</Link>
|
|
<Link to="/register" className="px-4 py-2 bg-gradient-to-r from-primary to-secondary rounded-lg text-sm hover:opacity-90 transition-opacity cursor-pointer">
|
|
开始使用
|
|
</Link>
|
|
</>
|
|
)}
|
|
<button className="md:hidden p-2 glass-hover rounded-lg cursor-pointer">
|
|
<Menu className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
)
|
|
}
|