import React, { useState, useRef, useEffect } from 'react' import { useNavigate, useParams } from 'react-router-dom' import { Image, ClueHintModal, ClueBookModal, flyToAnimation, Video, StudyGuideModal, EndingOverlay, } from '@/components' import { SuccessAlert } from '@/components/layout' import { SingleChoiceQuizPanel } from '@/components/layout/quiz' import { getBackgroundImage, getStaticImage, getPublicPath } from '@/lib/utils' import type { ClueHint } from '@/components/clue' import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext' import { useSunzhongshanStore, saveSunzhongshanStore } from '@/store/sunzhongshanStore' const starName = 'sunzhongshan' const sceneId = `${starName}/reflection/scene1` const GUIDE_STORAGE_KEY = `${sceneId}-guide-shown` // 线索配置 - 根据实际图片调整位置 const clueConfigs: ClueHint[] = [ { id: `${sceneId}/clue1`, name: '线索1', position: { top: '75%', left: '95.5%', width: '0%', height: '0%', }, }, { id: `${sceneId}/clue2`, name: '线索2', position: { top: '2%', left: '34%', width: '56%', height: '50%', }, }, { id: `${sceneId}/clue3`, name: '线索3', position: { top: '54%', left: '20%', width: '7%', height: '34%', }, }, { id: `${sceneId}/clue4`, name: '线索4', position: { top: '53%', left: '48.5%', width: '7%', height: '34%', }, }, ] const SunzhongshanReflectionScene1 = () => { const navigate = useNavigate() const { moduleName } = useParams<{ moduleName: string }>() // 获取碎片动画触发方法 const { triggerPuzzleAnimation } = usePuzzleAnimation() const { getReflectionFlag, setReflectionFlag } = useSunzhongshanStore() const [showClueHint, setShowClueHint] = useState(false) const [showClueBook, setShowClueBook] = useState(false) const [showSuccessAlert, setShowSuccessAlert] = useState(false) const [successAlertContent, setSuccessAlertContent] = useState('') const [showVideo, setShowVideo] = useState(true) const [showGuide, setShowGuide] = useState(false) const [showQuiz1, setShowQuiz1] = useState(false) const [showQuiz2, setShowQuiz2] = useState(false) const [showQuiz3, setShowQuiz3] = useState(false) const [showCompleteGuide, setShowCompleteGuide] = useState(false) const [pendingQuiz, setPendingQuiz] = useState<'quiz2' | 'quiz3' | 'complete' | null>(null) const { collectClue, isClueCollected } = useSunzhongshanStore() const containerRef = useRef(null) const clueBookButtonRef = useRef(null) // 为每个线索创建 ref const clueRefs = useRef>>(new Map()) // 获取或创建线索的 ref const getClueRef = (clueId: string): React.RefObject => { if (!clueRefs.current.has(clueId)) { clueRefs.current.set(clueId, React.createRef()) } return clueRefs.current.get(clueId)! } // 处理线索点击 const handleClueClick = (clueId: string, clueName: string) => { // 如果已收集,不重复收集 if (isClueCollected(clueId)) { setSuccessAlertContent('该线索已收集!') setShowSuccessAlert(true) return } // 收集线索 collectClue(clueId, clueName) // 获取线索元素的 ref const clueRef = getClueRef(clueId) // 使用函数式 API 触发飞行动画 if (clueRef.current && clueBookButtonRef.current) { flyToAnimation({ fromRef: clueRef as React.RefObject, toRef: clueBookButtonRef as React.RefObject, targetPosition: 'center', duration: 1200, onComplete: () => { // 动画完成后的回调 setSuccessAlertContent('获得1条线索,已获得线索可在线索簿中查看!') setShowSuccessAlert(true) }, }) } } // 处理背包点击 - 只收集线索1,不打开线索提示框 const handleBackpackClick = () => { const clue1Id = `${sceneId}/clue1` const clue1Name = '线索1' // 如果线索1已收集,显示提示 if (isClueCollected(clue1Id)) { setSuccessAlertContent('该线索已收集!') setShowSuccessAlert(true) return } // 收集线索1 collectClue(clue1Id, clue1Name) // 获取线索1的 ref const clue1Ref = getClueRef(clue1Id) // 执行飞行动画 if (clue1Ref.current && clueBookButtonRef.current) { flyToAnimation({ fromRef: clue1Ref as React.RefObject, toRef: clueBookButtonRef as React.RefObject, targetPosition: 'center', duration: 1200, onComplete: () => { // 动画完成后显示成功提示 setSuccessAlertContent('获得该线索!快去线索簿查看详细信息吧!') setShowSuccessAlert(true) }, }) } } // 处理线索提示按钮点击 - 打开线索提示框 const handleClueHintClick = () => { setShowClueHint(true) } // 处理视频播放结束 const handleVideoEnd = () => { setShowVideo(false) // 检查是否需要显示学习引导 const hasShownGuide = getReflectionFlag(GUIDE_STORAGE_KEY) if (!hasShownGuide) { setShowGuide(true) } } // 处理学习引导关闭 const handleGuideClose = () => { setShowGuide(false) setReflectionFlag(GUIDE_STORAGE_KEY, true) } // 检查是否所有线索都已收集 const areAllCluesCollected = () => { return clueConfigs.every((clue) => isClueCollected(clue.id)) } // 处理线索簿关闭 const handleClueBookClose = () => { setShowClueBook(false) // 如果所有线索都已收集,显示题目1 if (areAllCluesCollected()) { setShowQuiz1(true) } } // 处理题目1提交 const handleQuiz1Submit = (_value: string, isCorrect: boolean) => { if (isCorrect) { setShowQuiz1(false) setSuccessAlertContent('回答正确!') setShowSuccessAlert(true) setPendingQuiz('quiz2') } } // 处理题目2提交 const handleQuiz2Submit = (_value: string, isCorrect: boolean) => { if (isCorrect) { setShowQuiz2(false) setSuccessAlertContent('回答正确!') setShowSuccessAlert(true) setPendingQuiz('quiz3') } } // 处理题目3提交 const handleQuiz3Submit = (_value: string, isCorrect: boolean) => { if (isCorrect) { setShowQuiz3(false) setSuccessAlertContent('回答正确!') setShowSuccessAlert(true) // 设置待显示的完成提示 setPendingQuiz('complete') } } // 处理完成提示关闭 const handleCompleteGuideClose = () => { setShowCompleteGuide(false) // 保存场景1完成状态 setReflectionFlag(`${starName}-reflection-scene1-completed`, true) if (moduleName && starName) { const { setReflectionRoute } = useSunzhongshanStore.getState() setReflectionRoute('reflection2') saveSunzhongshanStore() navigate(`/${moduleName}/${starName}/reflection2`) } } // 获取线索图片 const getClueImage = (clueId: string) => { const clueNumber = clueId.split('clue')[1] return getStaticImage(`${sceneId}/线索${clueNumber}`) } // 获取线索详情图片 const getClueDetailImage = (clueId: string) => { const clueNumber = clueId.split('clue')[1] return getStaticImage(`${sceneId}/线索${clueNumber}-详情`) } // 获取线索提示图片 const getClueHintImage = (clueId: string): string | null => { const clueNumber = clueId.split('clue')[1] // 场景1中线索1有提示 if (clueNumber && ['1'].includes(clueNumber)) { return getStaticImage(`${sceneId}/线索${clueNumber}-详情的详情`) } return null } // 初始化线索(如果还没有) useEffect(() => { clueConfigs.forEach((clue) => { if (!isClueCollected(clue.id)) { // 不自动收集,只是确保线索存在 } }) }, [isClueCollected]) return (
{/* 视频播放 - 覆盖在页面内容之上 */} {showVideo && (
)} {/* 关闭按钮 */} { if (moduleName && starName) { navigate(`/${moduleName}/${starName}/reflection`) } }} /> {/* 线索点击区域 */} {clueConfigs.map((clue) => { const isCollected = isClueCollected(clue.id) const clueRef = getClueRef(clue.id) return (
{/* 线索元素(用于克隆和飞行) */}
{clue.name}
{/* 点击区域 */}
handleClueClick(clue.id, clue.name)} title={isCollected ? `${clue.name}(已收集)` : `点击收集${clue.name}`} />
) })} {/* 右下角-功能处 */}
setShowClueBook(true)} />
{/* 线索提示窗 */} setShowClueHint(false)} sourceContainerRef={containerRef} /> {/* 线索簿窗口 */} ({ id: c.id, name: c.name, collected: isClueCollected(c.id), }))} onClose={handleClueBookClose} getClueImage={getClueImage} getClueDetailImage={getClueDetailImage} getClueHintImage={getClueHintImage} /> {/* 成功提示弹窗 */} { setShowSuccessAlert(false) setSuccessAlertContent('') // 检查是否有待显示的题目或完成提示 if (pendingQuiz === 'quiz2') { setShowQuiz2(true) setPendingQuiz(null) } else if (pendingQuiz === 'quiz3') { setShowQuiz3(true) setPendingQuiz(null) } else if (pendingQuiz === 'complete') { triggerPuzzleAnimation(12) setShowCompleteGuide(true) setPendingQuiz(null) } }} onClose={() => { setShowSuccessAlert(false) setSuccessAlertContent('') // 检查是否有待显示的题目或完成提示 if (pendingQuiz === 'quiz2') { setShowQuiz2(true) setPendingQuiz(null) } else if (pendingQuiz === 'quiz3') { setShowQuiz3(true) setPendingQuiz(null) } else if (pendingQuiz === 'complete') { setShowCompleteGuide(true) setPendingQuiz(null) } }} /> {/* 学习引导弹窗 */} 同学你好,欢迎来到二十世纪初的上海。{'\n'} 辛亥革命之后,民主共和的观念深入人心。面对中外反动势力,社会各界更广泛地行动起来,以各自的方式争取着民主自由和国家尊严。 {'\n'} 你需要在本场景中找出4条线索,并正确回答所有问题后,才能拨开时局迷雾,进入下一个场景。 {/* 题目1:今天的日期是? */} {/* 题目2:今天的日记写什么呢? */} {/* 题目3:作为五四运动的见证者、参与者,你觉得中国革命有望通过怎样的方式实现? */} {/* 完成提示弹窗 */}
) } export default SunzhongshanReflectionScene1