import { EndingOverlay, ExhibitOverlay, GuideSteps, GuideStepsItem, Image, Title, } from '@/components' import Cursor from '@/components/cursor' import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils' import { useRef, useState } from 'react' import { useNavigate, useParams } from 'react-router-dom' import { useNieerStore, saveNieerStore } from '@/store/nieerStore' import { useCursorController } from '@/hooks/useCursorController' import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext' import { setCourseTimeProgress } from '@/lib/utils/api-common' const NieerPlace6 = () => { const navigate = useNavigate() const { moduleName } = useParams<{ moduleName: string }>() const { triggerPuzzleAnimation } = usePuzzleAnimation() const starName = 'nieer' const place = 'place6' const { markExhibitVisited, getVisitedExhibits } = useNieerStore() const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | null>(null) const [guide1Visible, setGuide1Visible] = useState(false) const [guide1Step, setGuide1Step] = useState(0) const total = 2 const visitedExhibits = getVisitedExhibits(place) const visited = new Set(visitedExhibits) const progressCount = visited.size const completed = progressCount >= total const [endingVisible, setEndingVisible] = useState(false) // 是否已展示过结束语(用于控制“离开场景”按钮出现时机) // 若用户刷新页面且已完成,则默认视为结束语已展示,避免卡住无法离开 const [endingShown, setEndingShown] = useState(() => completed) const endingShownRef = useRef(false) const subtitle = completed ? '已完成' : `${progressCount}/${total}` const { isEnabled } = useCursorController({ initialEnabled: [2], dependencies: { 1: [2], }, visited: visitedExhibits, }) if (!moduleName) return null const exhibitSrcMap: Record<1 | 2, string> = { 1: 'nieer/place6/场景6展品1', 2: 'nieer/place6/场景6展品2', } const handleOpenExhibit = (id: 1 | 2) => { setActiveExhibitId(id) if (id === 1) { setGuide1Step(0) setGuide1Visible(true) } } return (
<Image className="absolute right-5 top-5" src={getStaticImage('components/离开')} button onClick={() => navigate(`/${moduleName}/${starName}/place5`)} /> <Cursor className="absolute left-90 bottom-130" onClick={() => handleOpenExhibit(1)} read={visited.has(1)} disabled={!isEnabled(1)} /> <Cursor className="absolute right-240 bottom-135" onClick={() => handleOpenExhibit(2)} read={visited.has(2)} disabled={!isEnabled(2)} /> {/* 最后一个场景:完成后不显示“前进”按钮 */} {completed && endingShown && !endingVisible && ( <Image className="absolute bottom-0 right-0" src={getStaticImage('components/place/离开场景')} button onClick={() => { saveNieerStore() setCourseTimeProgress(13) navigate(`/${moduleName}/${starName}/home`) }} /> )} <ExhibitOverlay visible={activeExhibitId !== null} src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ''} onOpen={() => { if (activeExhibitId === 1) { triggerPuzzleAnimation(13) } if (activeExhibitId === 2) { triggerPuzzleAnimation(12) } }} onClose={() => { const closingId = activeExhibitId setActiveExhibitId(null) setGuide1Visible(false) if (closingId !== null) { markExhibitVisited(place, closingId) saveNieerStore() // 仅在“关闭展品”这一刻触发结束语:当本次关闭导致完成时,弹出 EndingOverlay const nextVisitedSize = visited.has(closingId) ? visited.size : visited.size + 1 const willComplete = nextVisitedSize >= total if (willComplete && !endingShownRef.current) { endingShownRef.current = true setEndingShown(true) setEndingVisible(true) } } }} /> {/* 光标1对话(图1) */} <GuideSteps visible={guide1Visible} currentStep={guide1Step} onStepChange={setGuide1Step} onVisibleChange={setGuide1Visible} showMask={false} highlightSelectors={[]} zIndex={10001} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/nieer/mp3_nieer_25.mp3')}> 小沪,这些不同场景下奏响国歌的画面太让人感动了!在和平年代,这首歌还有什么特别的意义呢? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/nieer/mp3_nieer_26_1.mp3')}> 和平年代里,它的精神力量依然不减。你看这张中国女排奥运夺金的照片,国歌奏响时,是民族自豪的宣告;神舟飞船升空时的国歌,是航天人攻坚克难的礼赞。 </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/nieer/mp3_nieer_26_2.mp3')}> 它就像一根精神纽带,无论在高光时刻还是艰难关头,都能凝聚起全国人民的力量,提醒我们不忘历史、砥砺前行。 </GuideStepsItem> </GuideSteps> {/* completed 后的结束语:统一使用 EndingOverlay */} <EndingOverlay visible={endingVisible} audioSrc={getPublicPath('audio/nieer/mp3_nieer_27.mp3')} text={ '从民族危机中觉醒的热血青年,到《义勇军进行曲》的谱曲者,聂耳用音符奏响了“救亡图存”的时代强音。' + '而《义勇军进行曲》的影响远不止于此,接下来,请你化身国歌时空旅行者,踏入6个散落于岁月中的故事现场,' + '一路聆听、一路共鸣,亲身体验这首旋律如何跨越时空,成为永远激荡在国人心中的精神号角吧!' } animationSpeed={200} onContinue={() => setEndingVisible(false)} /> </div> ) } export default NieerPlace6