import { useEffect, useState, useCallback } from 'react' import { createPortal } from 'react-dom' import { X } from 'lucide-react' interface ConfettiPiece { id: number x: number color: string delay: number duration: number size: number rotation: number } interface CelebrationProps { isOpen: boolean onClose: () => void onReset?: () => void } // 生成随机纸屑 function generateConfetti(count: number): ConfettiPiece[] { const colors = [ 'var(--color-primary)', // 青色 'var(--color-success)', // 绿色 'var(--color-amber)', // 琥珀色 '#FF6B6B', // 珊瑚红 '#A78BFA', // 紫罗兰 '#FBBF24', // 金色 ] return Array.from({ length: count }, (_, i) => ({ id: i, x: Math.random() * 100, color: colors[Math.floor(Math.random() * colors.length)], delay: Math.random() * 0.5, duration: 2 + Math.random() * 2, size: 8 + Math.random() * 8, rotation: Math.random() * 360, })) } function Confetti({ pieces }: { pieces: ConfettiPiece[] }) { return (
{pieces.map((piece) => (
))}
) } function CelebrationModal({ isOpen, onClose, onReset }: CelebrationProps) { const [confetti, setConfetti] = useState([]) useEffect(() => { if (isOpen) { // 生成纸屑 setConfetti(generateConfetti(60)) // 3秒后清除纸屑 const timer = setTimeout(() => setConfetti([]), 5000) return () => clearTimeout(timer) } }, [isOpen]) if (!isOpen) return null return createPortal( <>
{/* 背景遮罩 */}
{/* 弹窗内容 */}
{/* 关闭按钮 */} {/* 庆祝图标 */}
🎉

恭喜完成全部教程!

你已经掌握了所有知识点,太棒了!

{/* 统计信息 */}
100%
完成进度
全部完成
{/* 操作按钮 */}
, document.body ) } export function Celebration() { const [isOpen, setIsOpen] = useState(false) const [hasShown, setHasShown] = useState(false) // 监听完成事件 useEffect(() => { const handleComplete = () => { if (!hasShown) { setIsOpen(true) setHasShown(true) } } window.addEventListener('tutorial-complete', handleComplete) return () => window.removeEventListener('tutorial-complete', handleComplete) }, [hasShown]) const handleClose = useCallback(() => { setIsOpen(false) }, []) const handleReset = useCallback(() => { setIsOpen(false) // 触发重置事件 window.dispatchEvent(new CustomEvent('tutorial-reset')) setHasShown(false) }, []) return ( ) } // 触发庆祝的 hook export function useCelebration() { const triggerCelebration = useCallback(() => { window.dispatchEvent(new CustomEvent('tutorial-complete')) }, []) return { triggerCelebration } }