'use client'; import { useState, useEffect, useRef } from 'react'; import Link from 'next/link'; import { useRouter, usePathname } from 'next/navigation'; import { Bars3Icon, XMarkIcon, UserCircleIcon } from '@heroicons/react/24/outline'; import { motion, AnimatePresence, useScroll, useTransform, useSpring } from 'framer-motion'; import { Carrot } from 'lucide-react'; import { useAuth } from '@/contexts/AuthContext'; export default function Navbar() { const [isOpen, setIsOpen] = useState(false); const [isHidden, setIsHidden] = useState(false); const [isScrolled, setIsScrolled] = useState(false); const [scrollProgress, setScrollProgress] = useState(0); const navbarRef = useRef(null); const { user, isAuthenticated, isLoading: isAuthLoading, logout } = useAuth(); const router = useRouter(); const pathname = usePathname(); const { scrollY } = useScroll(); // 弹簧动画效果 const springConfig = { stiffness: 300, damping: 30 }; const navbarY = useSpring(useTransform(scrollY, [0, 100], [0, -100]), springConfig); const navbarOpacity = useSpring(useTransform(scrollY, [0, 50], [1, 0.95]), springConfig); // 在auth页面隐藏navbar const isAuthPage = pathname === '/auth'; // 检测navbar高度并设置CSS自定义属性 useEffect(() => { const updateHeight = () => { if (navbarRef.current) { const height = navbarRef.current.offsetHeight; document.documentElement.style.setProperty('--navbar-height', `${height}px`); } }; updateHeight(); window.addEventListener('resize', updateHeight); return () => window.removeEventListener('resize', updateHeight); }, []); // 滚动进度计算 useEffect(() => { const handleScroll = () => { const scrollTop = window.scrollY; const docHeight = document.documentElement.scrollHeight - window.innerHeight; const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0; setScrollProgress(progress); }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, []); useEffect(() => { let lastScrollY = 0; let ticking = false; const handleScroll = () => { if (!ticking) { window.requestAnimationFrame(() => { const currentScrollY = window.scrollY; // 检测是否滚动到顶部 setIsScrolled(currentScrollY > 20); // 更敏感的隐藏逻辑:只要往下滚动就隐藏,不管滚动多少 if (!isAuthPage && currentScrollY > lastScrollY && currentScrollY > 10) { setIsHidden(true); } else if (currentScrollY < lastScrollY) { // 往上滚动就显示 setIsHidden(false); } lastScrollY = currentScrollY; ticking = false; }); ticking = true; } }; if (!isAuthPage) { window.addEventListener('scroll', handleScroll, { passive: true }); } return () => window.removeEventListener('scroll', handleScroll); }, [isAuthPage]); const handleLogout = () => { logout(); router.push('/'); setIsOpen(false); }; const handleLinkClick = () => { setIsOpen(false); }; // 在auth页面不渲染navbar if (isAuthPage) { return null; } const navItems = [ { href: '/', label: '首页', icon: null }, { href: '/skins', label: '皮肤库', icon: null }, ]; return ( <> {/* 滚动进度条 */}
{/* Logo */} CarrotSkin {/* Desktop Navigation */}
{navItems.map((item, index) => ( {item.label} {pathname === item.href && ( )} ))} {/* 用户头像框 - 增强的微交互 */} {isAuthLoading ? (
) : isAuthenticated ? (
{user?.avatar ? ( {/* eslint-disable-next-line @next/next/no-img-element */} {user.username} ) : ( )} {user?.username} 退出登录
) : ( 登录 )}
{/* Mobile menu button */}
setIsOpen(!isOpen)} className="text-gray-700 dark:text-gray-300 hover:text-orange-500 dark:hover:text-orange-400 transition-colors duration-200 p-2" whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} animate={{ rotate: isOpen ? 180 : 0 }} transition={{ duration: 0.3 }} > {isOpen ? ( ) : ( )}
{/* Mobile Navigation */} {isOpen && (
{navItems.map((item, index) => ( {item.label} ))} {isAuthenticated ? ( <>
{user?.avatar ? ( /* eslint-disable-next-line @next/next/no-img-element */ {user.username} ) : ( )} {user?.username}
) : ( <> 登录 注册 )}
)}
{/* 返回顶部按钮 - 已注释掉,如需使用请恢复 showScrollTop 状态 */} {/* {showScrollTop && ( window.scrollTo({ top: 0, behavior: 'smooth' })} className="fixed bottom-8 right-8 z-40 bg-gradient-to-r from-orange-500 to-amber-500 text-white p-3 rounded-full shadow-lg hover:shadow-xl transition-all duration-200" > )} */} ); }