import { ExhibitOverlay, GuideSteps, GuideStepsItem, EndingOverlay, Image, Title, Video, type VideoRef, SingleChoiceQuizPanel, } from '@/components' import { useNavigate, useParams } from 'react-router-dom' import { getBackgroundImage, getStaticImage, getPublicPath } from '@/lib/utils' import { useMemo, useRef, useState } from 'react' import Cursor from '@/components/cursor' import { useCursorController } from '@/hooks/useCursorController' import SuccessAlert from '@/components/layout/alert/success-alert' import ScaledPortal from '@/components/layout/ScaledPortal' import { useMaozedongStore, saveMaozedongStore } from '@/store/maozedongStore' import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext' import { setCourseTimeProgress } from '@/lib/utils/api-common' // starName 固定为 maozedong const starName = 'maozedong' // 展品 ID 与资源路径映射,ID 用来做唯一标识 const exhibitSrcMap: Record<1 | 2 | 3 | 4 | 5, string> = { 1: 'maozedong/place4/场景4展品1', 2: 'maozedong/place4/场景4展品2_', 3: 'maozedong/place4/场景4展品4', 4: 'maozedong/place4/场景4展品5', 5: 'maozedong/place4/场景4展品6', } const MaozedongPlace4 = () => { const navigate = useNavigate() const { moduleName } = useParams<{ moduleName: string }>() // 获取碎片动画触发方法 const { triggerPuzzleAnimation } = usePuzzleAnimation() // 场景级引导对话显示状态(暂未使用,可根据需要开启) const [visible, setVisible] = useState(false) // 当前激活的展品 ID const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | 3 | 4 | 5 | null>(null) // 持久化接入 const markVisited = useMaozedongStore((s) => s.markExhibitVisited) const getVisited = useMaozedongStore((s) => s.getVisitedExhibits) const persistedVisited = useMemo( () => new Set(getVisited('place4') as (1 | 2 | 3 | 4 | 5)[]), [getVisited] ) const [visited, setVisited] = useState>(() => new Set(persistedVisited)) // 光标1的对话状态 const [guide1Visible, setGuide1Visible] = useState(false) const [guide1Step, setGuide1Step] = useState(0) // 光标3的对话状态 const [guide3Visible, setGuide3Visible] = useState(false) const [guide3Step, setGuide3Step] = useState(0) // 光标4(展品4)对话 // 光标4关闭后的过场视频与总结对话 const [showVideo4, setShowVideo4] = useState(false) const [guide4SummaryVisible, setGuide4SummaryVisible] = useState(false) const [guide4SummaryStep, setGuide4SummaryStep] = useState(0) const [endingVisible, setEndingVisible] = useState(false) // 光标2的对话状态 const [guide2Visible, setGuide2Visible] = useState(false) const [guide2Step, setGuide2Step] = useState(0) // 光标2的视频与题目状态 const [showVideo2, setShowVideo2] = useState(false) const video2Ref = useRef(null) const [quizStep, setQuizStep] = useState(0) // 0 表示未开始,1-4 为四道题 const [quizVisible, setQuizVisible] = useState(false) const [successAlertVisible, setSuccessAlertVisible] = useState(false) const [successAlertContent, setSuccessAlertContent] = useState('') // Cursor 顺序控制:1 -> 2 -> 3 -> 4 -> 5 -> 6 const { isEnabled } = useCursorController({ initialEnabled: [2], dependencies: { 1: [2], 3: [1], 4: [3, 5], 5: [1], }, visited, }) const handleOpenExhibit = (id: 1 | 2 | 3 | 4 | 5) => { setActiveExhibitId(id) if (id === 1) { setGuide1Step(0) setGuide1Visible(true) } if (id === 2) { setGuide2Step(0) setGuide2Visible(true) setQuizStep(0) } if (id === 3) { setGuide3Step(0) setGuide3Visible(true) } } if (!moduleName) return null const progressCount = visited.size const total = 5 const completed = progressCount >= total const subtitle = completed ? '已完成' : `${progressCount}/${total}` return (
{/* 标题 */} <Image className="absolute right-5 top-5" src={getStaticImage('components/离开')} button onClick={() => { if (moduleName && starName) { navigate(`/${moduleName}/${starName}/place3`) } }} /> {completed && ( <Image className="absolute right-0 bottom-0" src={getStaticImage('components/place/离开场景')} button onClick={() => { if (moduleName && starName) { saveMaozedongStore() setCourseTimeProgress(1) navigate(`/${moduleName}/${starName}/home`) } }} /> )} {/* 光标1 */} <Cursor className="absolute left-105 bottom-158" onClick={() => handleOpenExhibit(1)} read={visited.has(1)} disabled={!isEnabled(1)} /> {/* 光标2 */} <Cursor className="absolute left-199 bottom-162" onClick={() => handleOpenExhibit(2)} read={visited.has(2)} disabled={!isEnabled(2)} /> {/* 光标3 */} {/* <Cursor className="absolute left-215 bottom-163" onClick={() => handleOpenExhibit(3)} read={visited.has(3)} disabled={!isEnabled(3)} /> */} {/* 光标3 */} <Cursor className="absolute left-212 bottom-123" onClick={() => handleOpenExhibit(3)} read={visited.has(3)} disabled={!isEnabled(3)} /> {/* 光标4 */} <Cursor className="absolute right-186 bottom-162" onClick={() => handleOpenExhibit(4)} read={visited.has(4)} disabled={!isEnabled(4)} /> {/* 光标5 */} <Cursor className="absolute right-153 bottom-123" onClick={() => handleOpenExhibit(5)} read={visited.has(5)} disabled={!isEnabled(5)} /> {/* 场景对话 */} <GuideSteps visible={visible} onVisibleChange={(nextVisible) => { setVisible(nextVisible) }} showMask={false} > <GuideStepsItem speaker="student">小沪,毛泽东是如何组织和发动工农群众的?</GuideStepsItem> <GuideStepsItem speaker="guide"> 1925年,毛泽东回到湖南,深入农村调查研究,写出了《湖南农民运动考察报告》。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 他认识到农民是中国革命的主力军,只有发动农民,革命才能成功。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 毛泽东在各地建立农民协会,组织农民开展减租减息、反对封建压迫的斗争。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 同时,他也重视工人运动,在安源、长沙等地组织工人罢工,提高工人的政治觉悟。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 通过这些工作,毛泽东为后来的革命斗争奠定了坚实的群众基础。 </GuideStepsItem> </GuideSteps> {/* 光标1的对话:点击展品1时出现 */} <GuideSteps visible={guide1Visible} currentStep={guide1Step} onStepChange={setGuide1Step} onVisibleChange={(nextVisible) => { setGuide1Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10001} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_15.mp3')} > 看来中共四大明确提出了“无产阶级领导权”和“工农联盟”,这和毛主席的实践有关吗? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_16_1.mp3')} > 太有关系了!中共三大后毛主席到上海工作了一段时间,看到工人运动轰轰烈烈,但农民还是“沉默的大多数”。 </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_16_2.mp3')} > 后来毛主席回湖南,专门跑了湘潭、湘乡、衡山、醴陵、长沙五县,发现农民不仅能革命,而且革命性极强——他们被剥削得最狠, 反抗起来也最坚决! </GuideStepsItem> </GuideSteps> {/* 光标2的对话:点击展品2时出现 */} <GuideSteps visible={guide2Visible} currentStep={guide2Step} onStepChange={setGuide2Step} onVisibleChange={(nextVisible) => { setGuide2Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10001} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_13.mp3')} > 那中共四大为什么召开呢? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_14.mp3')}> 因为此前中共三大虽然确定了国共合作的方针,但未明确解决“谁领导革命”的问题。我们必须要明确“谁领导革命”“依靠谁革命”这两个基本问题。 </GuideStepsItem> </GuideSteps> {/* 光标3的对话:点击展品3时出现(图1) */} <GuideSteps visible={guide3Visible} currentStep={guide3Step} onStepChange={setGuide3Step} onVisibleChange={(nextVisible) => { setGuide3Visible(nextVisible) }} showMask={false} highlightSelectors={[]} zIndex={10001} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_17.mp3')} > 所以毛主席觉得,光靠工人不够,得把农民拉进革命队伍? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_18_01.mp3')} > 对!无产阶级要领导革命,必须联合农民——他们是工人阶级的“天然盟友”。中共四大虽然还没有明确提出“农村包围城市”,但已经意识到农民问题的重要性。 </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_18_02.mp3')} > 后来毛主席常说:“国民革命的中心问题,就是农民问题,一切都要靠农民问题的解决。”这句话的种子,就是在中共四大前后埋下的。 </GuideStepsItem> </GuideSteps> {/* 光标4视频结束后出现的总结对话(图1) */} <GuideSteps visible={guide4SummaryVisible} currentStep={guide4SummaryStep} onStepChange={setGuide4SummaryStep} onVisibleChange={(nextVisible) => { setGuide4SummaryVisible(nextVisible) if (!nextVisible) { setEndingVisible(true) } }} showMask={false} highlightSelectors={[]} zIndex={10001} > <GuideStepsItem speaker="student" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_19.mp3')} > 为有牺牲多壮志,敢教日月换新天。小沪,通过您的讲解,我明白了中共一大到四大是在艰难探索中不断前进的——从建党的理想,到制定民主革命纲领;从国共合作,到发现农民的力量。这些探索对我们今天有什么启示呢? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_20_1.mp3')} > 同学问到了根子上!革命就像爬山,一开始可能看不清山顶的样子,但只要沿着正确的方向,一步一步扎扎实实地走,总会离目标越来越近。 </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_20_2.mp3')} > 你们现在学历史,不能只记年代和事件,更要理解“为什么”——为什么马克思主义要和中国实际相结合?为什么农民是革命的重要力量?把这些道理想通了,将来不管做什么事,都能脚踏实地。 </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath('audio/maozedong/mp3_mzd_20_3.mp3')} > “实事求是”这四个字,是我们党一路走来的法宝,希望你也能记住。 </GuideStepsItem> </GuideSteps> {/* 展品遮罩层 */} <ExhibitOverlay visible={activeExhibitId !== null} src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ''} onOpen={() => { if (activeExhibitId === 2) { triggerPuzzleAnimation(8) } if (activeExhibitId === 1) { triggerPuzzleAnimation(9) } if (activeExhibitId === 3) { triggerPuzzleAnimation(10) } if (activeExhibitId === 4) { triggerPuzzleAnimation(12) } if (activeExhibitId === 5) { triggerPuzzleAnimation(11) } }} onClose={() => { const currentId = activeExhibitId // 展品2:关闭后播放视频和答题,全部正确后再标记已访问 if (currentId === 2) { setGuide2Step(0) setGuide2Visible(false) setActiveExhibitId(null) setShowVideo2(true) return } // 展品4:关闭后播放视频,视频结束后显示总结对话,并立即标记已访问 if (currentId === 4) { setActiveExhibitId(null) setVisited((prev) => { const next = new Set(prev) next.add(4) markVisited('place4', 4) saveMaozedongStore() return next }) setShowVideo4(true) return } if (currentId !== null) { setVisited((prev) => { const next = new Set(prev) next.add(currentId) markVisited('place4', currentId) saveMaozedongStore() return next }) } setActiveExhibitId(null) }} /> <EndingOverlay visible={endingVisible} audioSrc={getPublicPath('audio/maozedong/mp3_mzd_21.mp3')} text="我们已经了解了毛主席1924年前后居住在上海时所经历的重要事件。接下来,请你跨越时空,走进风云激荡的1924年,通过参与毛主席在筹备中共四大期间做出的几次关键选择,体悟早期共产党人探索革命道路的初心与智慧,体悟理论与实践结合的深刻意义。" onContinue={() => { setEndingVisible(false) }} animationSpeed={200} /> {/* 光标4:展品关闭后播放的视频 */} {showVideo4 && ( <Video src={getPublicPath('video/maozedong/mzd_02.mp4')} className="fixed inset-0 z-20000" autoPlay playsInline showSkipButton skipKey="maozedong_place4_video1" showReadonlyProgress onSkip={() => { setShowVideo4(false) setGuide4SummaryStep(0) setGuide4SummaryVisible(true) }} onEnded={() => { setShowVideo4(false) setGuide4SummaryStep(0) setGuide4SummaryVisible(true) }} /> )} {/* 光标2:展品关闭后播放的视频 */} {showVideo2 && ( <Video ref={video2Ref} src={getPublicPath('video/maozedong/mzd_5.mp4')} className="fixed inset-0 z-20000" autoPlay playsInline showSkipButton skipKey="maozedong_place4_video2" showReadonlyProgress onEnded={() => { setShowVideo2(false) setQuizStep(1) setQuizVisible(true) }} /> )} {/* 光标2:四道单选题 + 每题答对后的提示 */} <ScaledPortal enabled={quizVisible || successAlertVisible} zIndex={10050}> <> {/* 题目1:中共四大召开时间 */} <SingleChoiceQuizPanel visible={quizVisible && quizStep === 1} zIndex={10000} title="【单选】中共四大召开的时间是:" options={[ { value: 'A', label: 'A.1923年6月' }, { value: 'B', label: 'B.1924年1月' }, { value: 'C', label: 'C.1925年1月' }, { value: 'D', label: 'D.1926年7月' }, ]} correctAnswer="C" onWrongSelect={(value) => { if (value === 'A') { return '1923年6月,中共三大召开,确定了国共合作方针。请你再想想吧!' } if (value === 'B') { return '1924年1月,国民党一大召开,国共合作正式形成。请你再想想吧!' } if (value === 'D') { return '1926年7月,北伐战争开始。请你再想想吧!' } return '请结合时间线再仔细思考一下~' }} onSubmit={(_value, isCorrect) => { if (!isCorrect) return setQuizVisible(false) setSuccessAlertContent('中共四大于1925年1月11日至22日在上海召开。') setSuccessAlertVisible(true) }} /> {/* 题目2:召开地点 */} <SingleChoiceQuizPanel visible={quizVisible && quizStep === 2} zIndex={10000} title="【单选】中共四大召开的地点是:" options={[ { value: 'A', label: 'A.北京' }, { value: 'B', label: 'B.上海' }, { value: 'C', label: 'C.广州' }, { value: 'D', label: 'D.武汉' }, ]} correctAnswer="B" onWrongSelect={(value) => { if (value === 'A') { return '现在中国共产党全国代表大会多在北京召开,但是中共四大不是哦!请你再想想吧!' } if (value === 'C') { return '中共三大在广州召开,请你再想想吧!' } if (value === 'D') { return '中共五大在武汉召开,请你再想想吧!' } return '请再仔细对照题干信息选择~' }} onSubmit={(_value, isCorrect) => { if (!isCorrect) return setQuizVisible(false) setSuccessAlertContent('') setSuccessAlertVisible(true) }} /> {/* 题目3:首次明确提出的重要问题 */} <SingleChoiceQuizPanel visible={quizVisible && quizStep === 3} zIndex={10000} title="【单选】中共四大第一次明确提出的重要问题是:" options={[ { value: 'A', label: 'A.党的建设问题' }, { value: 'B', label: 'B.武装斗争问题' }, { value: 'C', label: 'C.无产阶级领导权和工农联盟问题' }, { value: 'D', label: 'D.土地革命问题' }, ]} correctAnswer="C" onWrongSelect={(value) => { if (value === 'A') { return '古田会议更系统阐述党的建设问题哦!请你再想想吧!' } if (value === 'B') { return '八七会议更系统阐述武装斗争问题哦!请你再想想吧!' } if (value === 'D') { return '八七会议后提出土地革命问题哦!请你再想想吧!' } return '请再仔细比较不同会议的主要议题~' }} onSubmit={(_value, isCorrect) => { if (!isCorrect) return setQuizVisible(false) setSuccessAlertContent('') setSuccessAlertVisible(true) }} /> {/* 题目4:党的基本组织形式 */} <SingleChoiceQuizPanel visible={quizVisible && quizStep === 4} zIndex={10000} title="【单选】中共四大确立的党的基本组织形式是:" options={[ { value: 'A', label: 'A.组' }, { value: 'B', label: 'B.支部' }, // { value: "C", label: "C.区委" }, // { value: "D", label: "D.中央局" }, ]} correctAnswer="B" onWrongSelect={(value) => { if (value === 'A') { return '中共四大以前党的基本组织形式是组或者小组,请你再想想吧!' } return '请注意中共四大之后对基层组织形式的规定~' }} onSubmit={(_value, isCorrect) => { if (!isCorrect) return setQuizVisible(false) setSuccessAlertContent( '中共四大明确“支部是党的基本组织”,规定“有三名党员即可成立一个支部”。' ) setSuccessAlertVisible(true) // 全部答对后标记展品2为已访问 setVisited((prev) => { const next = new Set(prev) next.add(2) return next }) }} /> {/* 每题答对后的统一提示框 */} <SuccessAlert visible={successAlertVisible} content={successAlertContent} onContinue={() => { setSuccessAlertVisible(false) //答题结束,标记展品4为已查看 markVisited('place4', 2) // 进入下一题 setQuizStep((prev) => { const next = prev + 1 if (next >= 1 && next <= 4) { setQuizVisible(true) } return next }) }} /> </> </ScaledPortal> </div> ) } export default MaozedongPlace4