import { useState, useRef } from "react"; import { ExhibitOverlay, Title, Image, Cursor, Video, GuideSteps, GuideStepsItem, type SingleChoiceOption, type DragFillResult, QuizPanel, StudyGuideModal, } from "@/components"; import { SuccessAlert, DragQuizPanel } from "@/components/layout"; import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils"; import { useNavigate, useParams } from "react-router-dom"; import type { VideoRef } from "@/components/video"; // starName 固定为 chenyun const starName = "chenyun"; // 展品 ID 与资源路径映射 const exhibitSrcMap: Record<1, string> = { 1: "chenyun/place5/场景5展品1", }; // 题目1选项 const QUIZ1_OPTIONS: SingleChoiceOption[] = [ { value: "A", label: "A. 推动了淮海战役的胜利", }, { value: "B", label: "B. 有利于稳定人民的发行和地位", }, { value: "C", label: "C. 巩固了新中国人民政权", }, ]; // 题目1各选项对应的错误提示(原来写在选项括号中的内容) const QUIZ1_ERROR_HINTS: Record = { A: "淮海战役于1949年1月胜利结束,发生在这次“银元之战”前,不存在因果关系。", C: "1949年6月新中国政权尚未建立。", }; const ChenyunPlace7 = () => { const navigate = useNavigate(); const { moduleName } = useParams<{ moduleName: string; }>(); const [visited, setVisited] = useState>(new Set()); const [activeExhibitId, setActiveExhibitId] = useState<1 | null>(null); const [videoVisible1, setVideoVisible1] = useState(false); const [videoPlaying, setVideoPlaying] = useState(false); const videoRef = useRef(null); // 单选题 const [quizVisible, setQuizVisible] = useState(false); const [quizAnswer, setQuizAnswer] = useState(""); const [quizError, setQuizError] = useState(""); // 展品1引导对话 const [guideVisible, setGuideVisible] = useState(false); const [guideStep, setGuideStep] = useState(0); // 第二阶段:对话2 + 视频2 + 题目2 const [videoVisible2, setVideoVisible2] = useState(false); const [videoPlaying2, setVideoPlaying2] = useState(false); const videoRef2 = useRef(null); const [guideVisible2, setGuideVisible2] = useState(false); const [guideStep2, setGuideStep2] = useState(0); const [quiz2Visible, setQuiz2Visible] = useState(false); const [quiz2Error, setQuiz2Error] = useState(""); const [quiz2Value, setQuiz2Value] = useState([]); // 成功提示 const [successAlertVisible, setSuccessAlertVisible] = useState(false); // 标记拖拽题是否已完成 const [quiz2Completed, setQuiz2Completed] = useState(false); // 学习引导弹窗 const [showGuideModal, setShowGuideModal] = useState(true); const handleOpenExhibit = (_index: 1) => { // 如果本场景学习已完成(拖拽题已答对),不再响应点击,避免重复播放 if (quiz2Completed) return; // 展品1:点击时显示视频1场景和引导对话1 setVideoVisible1(true); setVideoPlaying(false); // 视频不自动播放 setGuideVisible(true); setGuideStep(0); }; // 监听GuideSteps步骤变化 const handleGuideStepChange = (step: number) => { setGuideStep(step); }; // 监听对话引导完成 const handleGuideVisibleChange = (visible: boolean) => { setGuideVisible(visible); // 对话引导完成后,开始播放视频 if (!visible && videoVisible1) { setVideoPlaying(true); videoRef.current?.play(); } }; // 对话2步骤变化 const handleGuideStepChange2 = (step: number) => { setGuideStep2(step); }; // 对话2完成 → 播放视频2 const handleGuideVisibleChange2 = (visible: boolean) => { setGuideVisible2(visible); if (!visible && videoVisible2) { setVideoPlaying2(true); videoRef2.current?.play(); } }; // 拖拽题配置 const QUIZ2_BLANKS = [ { id: "blank-1", label: "____" }, { id: "blank-2", label: "____" }, { id: "blank-3", label: "____" }, ]; const QUIZ2_OPTIONS = [ { value: "棉纱", label: "棉纱" }, { value: "大米", label: "大米" }, { value: "煤炭", label: "煤炭" }, { value: "石油", label: "石油" }, ]; const QUIZ2_ANSWER = ["棉纱", "大米", "煤炭"]; const handleQuiz2Change = (val: DragFillResult[]) => { setQuiz2Value(val); setQuiz2Error(""); if (val.length < QUIZ2_ANSWER.length) return; // 获取所有已填入的答案(不要求顺序) const filledAnswers = val.map((v) => v.optionValue); // 检查是否包含了所有正确答案(使用 Set 比较,不要求顺序) const answerSet = new Set(QUIZ2_ANSWER); const filledSet = new Set(filledAnswers); const isCorrect = answerSet.size === filledSet.size && [...answerSet].every((answer) => filledSet.has(answer)); if (isCorrect) { setQuiz2Visible(false); setVideoVisible1(false); setVideoPlaying(false); setVideoVisible2(false); setVideoPlaying2(false); // 标记拖拽题已完成 setQuiz2Completed(true); // 显示成功提示 setSuccessAlertVisible(true); } else { setQuiz2Error("再想一想,石油当时不是主要调控对象~"); } }; const progressCount = visited.size; const total = 1; 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}/place6`); } }} /> {/* 展品1 */} <Cursor className="absolute left-230 top-88" onClick={() => handleOpenExhibit(1)} read={visited.has(1)} /> {/* 继续前进 - 仅在完成所有展品后显示 */} {completed && ( <Image className="absolute bottom-0 right-0" src={getStaticImage("chenyun/place7/继续前进")} button onClick={() => { navigate(`/${moduleName}/${starName}/place8`); }} /> )} {/* 展品1视频播放(全屏) */} {videoVisible1 && ( <div className="fixed inset-0 z-[9999] bg-black"> <Video ref={videoRef} src={getPublicPath("video/chenyun/chenyun_10.mp4")} className="w-full h-full" autoPlay={videoPlaying} playsInline preload="auto" muted={!videoPlaying} showSkipButton onEnded={() => { setVideoPlaying(false); setVisited((prev) => { const next = new Set(prev); next.add(1); return next; }); // 视频播放完成后,出现单选题 setQuizVisible(true); }} /> </div> )} {/* 展品1的引导对话 - 在视频上方显示 */} <GuideSteps visible={guideVisible} onVisibleChange={handleGuideVisibleChange} currentStep={guideStep} onStepChange={handleGuideStepChange} showMask={false} highlightSelectors={[]} zIndex={10001} > <GuideStepsItem speaker="student"> 那"银元之战"是如何取得胜利的呢? </GuideStepsItem> <GuideStepsItem speaker="guide"> 由于通货膨胀,国民党发行的法币、金圆券变成了一堆废纸。当时坊间流传"大街过三道,物价跳三跳"。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 有人计算,一百元法币,在一九三七年可买两头牛,一九四五年只能买两个鸡蛋,一九四七年只能买一个煤球,到一九四九年五月连一粒米也买不到。可见,当时通货膨胀多么严重。 </GuideStepsItem> </GuideSteps> {/* 单选题1:在视频1结束后出现(点击即判定) */} <QuizPanel visible={quizVisible} zIndex={10002} title="题目1(单选题):1949年6月,中央央指导打击银元投机活动,金条、银元一律由人民银行挂牌收兑,铁路交通事业、税收一律收入人民币。同时,上海军管会查封了证券大楼。这次“银元之战”()" options={QUIZ1_OPTIONS} value={quizAnswer} error={quizError} onChange={(val) => { setQuizAnswer(val); if (val === "B") { setQuizVisible(false); setQuizError(""); // 显示成功提示 setSuccessAlertVisible(true); } else { // 使用对应选项的错误提示,如果不存在则使用通用提示 setQuizError( QUIZ1_ERROR_HINTS[val] || "再想一想,注意题干中的时间和提示信息哦~" ); } }} /> {/* 视频2播放(全屏) */} {videoVisible2 && ( <div className="fixed inset-0 z-[10010] bg-black"> <Video ref={videoRef2} src={getPublicPath("video/chenyun/chenyun_11.mp4")} className="w-full h-full" autoPlay={videoPlaying2} playsInline preload="auto" muted={!videoPlaying2} showSkipButton skipText="跳过" onEnded={() => { setVideoPlaying2(false); // 视频2结束后,停在最后一帧并出现题目2 setQuiz2Visible(true); }} /> </div> )} {/* 对话2:在视频2背景上显示 */} <GuideSteps visible={guideVisible2} onVisibleChange={handleGuideVisibleChange2} currentStep={guideStep2} onStepChange={handleGuideStepChange2} showMask={false} highlightSelectors={[]} zIndex={10011} > <GuideStepsItem speaker="student"> 那“两白一黑”战役是如何打赢的呢? </GuideStepsItem> <GuideStepsItem speaker="guide"> “银元之战”的胜利并没有遏制住投机者的嚣张气焰,物价稳定仅十几天后,投机者就由银元投机转向“两白一黑”的投机,即:棉纱、大米和煤炭,引发了又一次全国性涨价狂潮。 </GuideStepsItem> </GuideSteps> {/* 拖拽题2:在视频2结束后出现 */} <DragQuizPanel visible={quiz2Visible} zIndex={10012} title="题目2(拖拽)" questionPrefix='新中国成立后,为了稳定物价,中央政府组织了"两白一黑"的集中调运,"两白一黑"指的是(' questionSuffix=")。" options={QUIZ2_OPTIONS} blanks={QUIZ2_BLANKS} value={quiz2Value} error={quiz2Error} onChange={handleQuiz2Change} /> {/* 遮罩层 */} <ExhibitOverlay visible={activeExhibitId !== null} src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""} onClose={() => { if (activeExhibitId !== null) { setVisited((prev) => { const next = new Set(prev); next.add(activeExhibitId); return next; }); } setActiveExhibitId(null); }} /> {/* 成功提示 */} {successAlertVisible && ( <div className="fixed inset-0" style={{ zIndex: 20000 }}> <SuccessAlert visible={successAlertVisible} title="恭喜你, 选择正确!" onClose={() => { setSuccessAlertVisible(false); // 如果是单选题答对且拖拽题还没开始,继续进入第二阶段 if (quizAnswer === "B" && !quiz2Visible && !quiz2Completed) { setVideoVisible2(true); setVideoPlaying2(false); setGuideVisible2(true); setGuideStep2(0); } }} onContinue={() => { setSuccessAlertVisible(false); // 如果是单选题答对且拖拽题还没开始,继续进入第二阶段 if (quizAnswer === "B" && !quiz2Visible && !quiz2Completed) { setVideoVisible2(true); setVideoPlaying2(false); setGuideVisible2(true); setGuideStep2(0); } }} /> </div> )} {/* 学习引导 */} <StudyGuideModal visible={showGuideModal} onContinue={() => setShowGuideModal(false)} ailgn="left" > 1、场景中出现动态光点的展品表示未浏览,可通过点击光点来了解展品背后的故事,通过滚轮可以放大展品,浏览展品后蓝色动态光点会变为已浏览状态; {"\n"} 2、在学习过程中会掉落拼图碎片,拼图碎片会自动收入拼图盒中,拼图盒可以点击查看当前拼图收集情况,点击单个拼图可以回到获得拼图的场景再次学习; {"\n"} 3、所有动态光点的展品全部学习后才能进入下一个场景学习; </StudyGuideModal> </div> ); }; export default ChenyunPlace7;