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 { useClueStore } from "@/store/clueStore"; import type { ClueHint } from "@/components/clue"; import { usePuzzleAnimation } from "@/contexts/PuzzleAnimationContext"; 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 [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 } = useClueStore(); 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 = localStorage.getItem(GUIDE_STORAGE_KEY); if (!hasShownGuide) { setShowGuide(true); } }; // 处理学习引导关闭 const handleGuideClose = () => { setShowGuide(false); localStorage.setItem(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完成状态 localStorage.setItem(`${starName}-reflection-scene1-completed`, "true"); if (moduleName && starName) { 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}-详情`); }; // 初始化线索(如果还没有) 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} /> {/* 成功提示弹窗 */} { 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); } }} /> {/* 学习引导弹窗 */} 同学你好,欢迎来到二十世纪初的上海。
辛亥革命之后,民主共和的观念深入人心。面对中外反动势力,社会各界更广泛地行动起来,以各自的方式争取着民主自由和国家尊严。
你需要在本场景中找出4条线索,并正确回答所有问题后,才能拨开时局迷雾,进入下一个场景。
{/* 题目1:今天的日期是? */} {/* 题目2:今天的日记写什么呢? */} {/* 题目3:作为五四运动的见证者、参与者,你觉得中国革命有望通过怎样的方式实现? */} {/* 完成提示弹窗 */}
); }; export default SunzhongshanReflectionScene1;