import { useState, useRef } from 'react' import { ExhibitOverlay, Title, Image, Cursor, GuideSteps, GuideStepsItem, Video, type VideoRef, type DragFillResult, } from '@/components' import { useCursorController } from '@/hooks/useCursorController' import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils' import { useNavigate, useParams } from 'react-router-dom' import { SuccessAlert, DragQuizPanel } from '@/components/layout' import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext' import { useSunzhongshanStore, saveSunzhongshanStore } from '@/store/sunzhongshanStore' const starName = 'sunzhongshan' const exhibitSrcMap: Record<1 | 2 | 3 | 4, string> = { 1: 'sunzhongshan/place3/李大钊给胡适的信', 2: 'sunzhongshan/place3/中国国民党第一次全国代表大会宣言', 3: 'sunzhongshan/place3/星期评论', 4: 'sunzhongshan/place3/社会主义的精义', } const SunzhongshanPlace3 = () => { const navigate = useNavigate() const { moduleName } = useParams<{ moduleName: string }>() // 获取碎片动画触发方法 const { triggerPuzzleAnimation } = usePuzzleAnimation() const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | 3 | 4 | null>(null) // 使用持久化的访问状态 const place = 'place3' const { markExhibitVisited, getVisitedExhibits } = useSunzhongshanStore() // 从 store 获取已访问的展品,转换为 Set 用于兼容现有代码 const visitedExhibits = getVisitedExhibits(place) const visited = new Set(visitedExhibits) // Cursor 顺序控制:1 -> 2 -> 3 -> 4 const { isEnabled } = useCursorController({ initialEnabled: [4], dependencies: { 1: [3], 2: [1], 3: [4], }, visited: visited, }) // 光标1的对话状态 const [guide1Visible, setGuide1Visible] = useState(false) const [guide1Step, setGuide1Step] = useState(0) // 光标2的对话状态 const [guide2Visible, setGuide2Visible] = useState(false) const [guide2Step, setGuide2Step] = useState(0) // 光标2的视频状态 const [showVideo2, setShowVideo2] = useState(false) const video2Ref = useRef(null) // 光标2的拖拽题状态 const [dragQuiz2Visible, setDragQuiz2Visible] = useState(false) const [dragQuiz2Value, setDragQuiz2Value] = useState([]) const [dragQuiz2Error, setDragQuiz2Error] = useState('') const [successAlert2Visible, setSuccessAlert2Visible] = useState(false) // 光标3的对话状态 const [guide3Visible, setGuide3Visible] = useState(false) const [guide3Step, setGuide3Step] = useState(0) // 光标4的对话状态 const [guide4Visible, setGuide4Visible] = useState(false) const [guide4Step, setGuide4Step] = useState(0) const handleOpenExhibit = (index: 1 | 2 | 3 | 4) => { setActiveExhibitId(index) // 根据不同的展品显示对应的对话,并重置进度 if (index === 1) { setGuide1Step(0) setGuide1Visible(true) } else if (index === 2) { setGuide2Step(0) setGuide2Visible(true) } else if (index === 3) { setGuide3Step(0) setGuide3Visible(true) } else if (index === 4) { setGuide4Step(0) setGuide4Visible(true) } } const progressCount = visited.size const total = 4 const completed = progressCount >= total const subtitle = completed ? '已完成' : `${progressCount}/${total}` const subtitleClassName = completed ? 'text-[#fff998] [text-shadow:_0_8px_8px_rgba(0,0,0,0.35),_0_0_16px_rgba(0,0,0,0.25)]' : undefined return (
<Image className="absolute right-5 top-5" src={getStaticImage('components/离开')} button onClick={() => { if (moduleName && starName) { navigate(`/${moduleName}/${starName}/place2`) } }} /> <Cursor className="absolute left-198 top-118" onClick={() => handleOpenExhibit(1)} read={visited.has(1)} disabled={!isEnabled(1)} /> <Cursor className="absolute left-210 top-140" onClick={() => handleOpenExhibit(2)} read={visited.has(2)} disabled={!isEnabled(2)} /> <Cursor className="absolute right-182 bottom-95" onClick={() => handleOpenExhibit(3)} read={visited.has(3)} disabled={!isEnabled(3)} /> <Cursor className="absolute right-158 bottom-95" onClick={() => handleOpenExhibit(4)} read={visited.has(4)} disabled={!isEnabled(4)} /> {completed && ( <Image className="absolute bottom-0 right-110" src={getStaticImage('components/place/r-前进')} button onClick={() => { const { setLastVisitedPlace } = useSunzhongshanStore.getState() setLastVisitedPlace('place4') saveSunzhongshanStore() navigate(`/${moduleName}/${starName}/place4`) }} /> )} <ExhibitOverlay visible={activeExhibitId !== null} src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ''} onOpen={() => { if (activeExhibitId === 4) { triggerPuzzleAnimation(8) } if (activeExhibitId === 1) { triggerPuzzleAnimation(9) } if (activeExhibitId === 2) { triggerPuzzleAnimation(10) } }} onClose={() => { const currentId = activeExhibitId // 关闭展品框时,重置所有对话的进度并隐藏对话,确保遮罩层正确清理 setGuide1Step(0) setGuide1Visible(false) setGuide2Step(0) setGuide2Visible(false) setGuide3Step(0) setGuide3Visible(false) setGuide4Step(0) setGuide4Visible(false) if (currentId === 2) { // 光标2:关闭窗口后播放视频 setActiveExhibitId(null) setShowVideo2(true) return } if (currentId !== null) { markExhibitVisited(place, currentId) } setActiveExhibitId(null) }} /> {/* 光标1的对话 */} <GuideSteps visible={guide1Visible} currentStep={guide1Step} onStepChange={setGuide1Step} onVisibleChange={(nextVisible) => { setGuide1Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_36.mp3')} > 这张是李大钊先生的手迹啊,和孙中山先生有什么关系呢? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_37.mp3')} > 这封信的收件人是胡适。信里提到,孙中山先生经历了陈炯明叛变事件回到上海后,态度变得很冷静,不再坚持之前的护法主张,反而提出“收军权于中央”“结合民主的联合战线,与反动派决裂”等。 </GuideStepsItem> <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_38.mp3')} > 孙先生与李大钊先生进行了深入的交谈。他在寻找新的合作力量吗? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_39.mp3')} > 这个力量就是新生的中国共产党。孙中山先生向共产党人释放了巨大的诚意。除了与李大钊的频繁接触,他还在上海会见了共产国际代表马林,明确表示愿意和苏俄合作;邀请鲍罗庭来中国担任国民党组织教练员; </GuideStepsItem> <GuideStepsItem speaker="guide"> 与陈独秀多次沟通,在共产国际与中共的建议和帮助下改组国民党,为国民党一大的召开做准备。 </GuideStepsItem> </GuideSteps> {/* 光标2的对话 */} <GuideSteps visible={guide2Visible} currentStep={guide2Step} onStepChange={setGuide2Step} onVisibleChange={(nextVisible) => { setGuide2Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_40.mp3')} > 我记得在毛泽东旧居陈列馆中学到,国共第一次合作正式形成的标志就是国民党一大,这就是当时的大会宣言吗? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_41.mp3')} > 完全正确!1924年1月20日,中国国民党第一次全国代表大会在广东高师礼堂开幕,孙中山先生以国民党总理的身份担任大会主席,主持开幕式。此次大会共有165名代表出席,其中共产党员代表超过20人,包括李大钊、毛泽东等中共早期领导人。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 会议上,孙先生重新解释了三民主义,事实上确立了联俄、联共、扶助农工的三大政策。第一次国共合作正式形成后,轰轰烈烈的国民革命也就此展开。 </GuideStepsItem> </GuideSteps> {/* 光标2的视频 */} {showVideo2 && ( <Video ref={video2Ref} src={getPublicPath('video/sunzhongshan/sunzhongshan_08.mp4')} className="fixed inset-0 z-[20000]" autoPlay playsInline showSkipButton onEnded={() => { setShowVideo2(false) setDragQuiz2Visible(true) }} /> )} {/* 光标2的拖拽题 */} <DragQuizPanel visible={dragQuiz2Visible} zIndex={10000} title="" questionPrefix="【拖拽】中国国民党第一次全国代表大会事实上确立了:" questionSuffix="三大政策。" options={[ { value: '联俄', label: '联俄' }, { value: '联共', label: '联共' }, { value: '扶助农工', label: '扶助农工' }, { value: '反俄', label: '反俄' }, ]} blanks={[ { id: 'blank1', label: '____' }, { id: 'blank2', label: '____' }, { id: 'blank3', label: '____' }, ]} value={dragQuiz2Value} error={dragQuiz2Error} onChange={(value) => { setDragQuiz2Value(value) setDragQuiz2Error('') if (value.length < 3) return // 检查答案:需要三个空白都填满,且答案正确 const correctAnswers = ['联俄', '联共', '扶助农工'] const filledAnswers = value.map((v) => v.optionValue) const answerSet = new Set(correctAnswers) const filledSet = new Set(filledAnswers) const isCorrect = answerSet.size === filledSet.size && [...answerSet].every((answer) => filledSet.has(answer)) if (isCorrect) { setDragQuiz2Visible(false) setSuccessAlert2Visible(true) } else { setDragQuiz2Error( '中国国民党第一次全国代表大会上,孙中山重新解释了三民主义,事实上确立了联俄、联共、扶助农工的三大政策。三大政策是孙中山的重要政治主张,使他倡导的民族民主革命从屡受挫折转向成功进而走上了正确道路。' ) } }} /> {/* 光标2的成功提示 */} <SuccessAlert visible={successAlert2Visible} onContinue={() => { setSuccessAlert2Visible(false) // 修改cursor状态 markExhibitVisited(place, 2) }} onClose={() => { setSuccessAlert2Visible(false) // 修改cursor状态 markExhibitVisited(place, 2) }} /> {/* 光标3的对话 */} <GuideSteps visible={guide3Visible} currentStep={guide3Step} onStepChange={setGuide3Step} onVisibleChange={(nextVisible) => { setGuide3Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_34.mp3')} > 这时候,工农群众的力量还没有正式登上历史舞台呢。 </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_35.mp3')} > 旁边这本《星期评论》创刊于五四运动后。孙中山先生在五四运动中看到了群众的力量和工人、学生们的热情。更觉顺应时代潮流,传播新文化、介绍马克思主义、鼓励工人运动的重要性。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 这份进步刊物成为一扇窗,让国人,也让孙先生自己看到了民族、民主革命的新转机。 </GuideStepsItem> </GuideSteps> {/* 光标4的对话 */} <GuideSteps visible={guide4Visible} currentStep={guide4Step} onStepChange={setGuide4Step} onVisibleChange={(nextVisible) => { setGuide4Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_32.mp3')} > 这本书看起来很特别,《社会主义的精义》是孙中山先生写的吗?他也关注社会主义学说呀? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/sunzhongshan/mp3_sunzhongshan_33.mp3')} > 不仅关注,而且还很早。1912年10月14日-16日,孙中山先生连续三日在上海三马路(今汉口路)中华大戏院发表关于社会主义学说的演讲,吸引了众多听众。这就是演说后经由他本人修订出版的小册子。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 后来俄国十月革命胜利,上海《民国日报》最先在中国报道了这个消息。 </GuideStepsItem> </GuideSteps> </div> ) } export default SunzhongshanPlace3