"use client" import { useEffect, useState, useCallback, useRef } from "react" import { usePathname, useSearchParams } from "next/navigation" import { cn } from "@/lib/utils" /** * 路由加载进度条组件 * * 监听 Next.js App Router 的路由变化,显示顶部进度条动画 */ export function RouteProgress() { const pathname = usePathname() const searchParams = useSearchParams() const [progress, setProgress] = useState(0) const [isVisible, setIsVisible] = useState(false) const isFirstRender = useRef(true) const intervalRef = useRef(null) const startProgress = useCallback(() => { setIsVisible(true) setProgress(0) // 使用 interval 平滑递增 let currentProgress = 0 intervalRef.current = setInterval(() => { currentProgress += Math.random() * 10 + 5 // 每次增加 5-15% if (currentProgress >= 90) { currentProgress = 90 // 最多到 90%,等待完成 if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } } setProgress(currentProgress) }, 100) }, []) const completeProgress = useCallback(() => { // 清除进行中的 interval if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } setProgress(100) // 完成后短暂显示 100%,然后隐藏 setTimeout(() => { setIsVisible(false) setProgress(0) }, 300) }, []) useEffect(() => { // 跳过首次渲染 if (isFirstRender.current) { isFirstRender.current = false return } // 路由变化时触发进度条 startProgress() // 页面加载完成后结束进度条 const timer = setTimeout(() => completeProgress(), 300) return () => { clearTimeout(timer) if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } } }, [pathname, searchParams, startProgress, completeProgress]) if (!isVisible) return null return (
{/* 进度条背景 */}
{/* 进度条 */}
{/* 发光效果 */}
) }