import React, { useState, useRef, useEffect } from "react"; import { useNavigate, useParams } from "react-router-dom"; import { Image, ClueHintModal, ClueBookModal, flyToAnimation, Video, StudyGuideModal, Cursor, } from "@/components"; import { SuccessAlert, ErrorAlert } 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"; const starName = "sunzhongshan"; const sceneId = `${starName}/reflection/scene3`; const GUIDE_STORAGE_KEY = `${sceneId}-guide-shown`; // 线索配置 - 根据实际图片调整位置 const clueConfigs: ClueHint[] = [ { id: `${sceneId}/clue1`, name: "线索1", position: { top: "38%", left: "8%", width: "24%", height: "60%", }, }, { id: `${sceneId}/clue2`, name: "线索2", position: { top: "26%", left: "43%", width: "40%", height: "26%", }, }, { id: `${sceneId}/clue3`, name: "线索3", position: { top: "44%", left: "10%", width: "85%", height: "50%", }, }, { id: `${sceneId}/clue4`, name: "线索4", position: { top: "75%", left: "95.5%", width: "0%", height: "0%", }, }, ]; const SunzhongshanReflectionScene3 = () => { const navigate = useNavigate(); const { moduleName } = useParams<{ moduleName: string; }>(); const [showClueHint, setShowClueHint] = useState(false); const [showClueBook, setShowClueBook] = useState(false); const [showSuccessAlert, setShowSuccessAlert] = useState(false); const [successAlertContent, setSuccessAlertContent] = useState(""); const [showErrorAlert, setShowErrorAlert] = useState(false); const [errorAlertContent, setErrorAlertContent] = 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); // 场景切换:true 表示 bg 场景,false 表示"窃窃私语"场景 const [isMainScene, setIsMainScene] = useState(false); // 控制 Cursor 显示:获取线索1后显示,点击后进入主场景 const [showCursor, setShowCursor] = useState(false); 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("获得该线索!快去线索簿查看详细信息吧!"); setShowSuccessAlert(true); // 如果是在"窃窃私语"场景收集了线索1,显示 Cursor if (!isMainScene && clueId === `${sceneId}/clue1`) { setShowCursor(true); } }, }); } }; // 处理背包点击 - 只收集线索4,不打开线索提示框 const handleBackpackClick = () => { // 如果不在主场景,提示需要先获取线索1 if (!isMainScene) { setErrorAlertContent(showCursor ? "该线索已收集" : "请先获取线索1"); setShowErrorAlert(true); return; } const clue4Id = `${sceneId}/clue4`; const clue4Name = "线索4"; // 如果线索4已收集,显示提示 if (isClueCollected(clue4Id)) { setSuccessAlertContent("该线索已收集"); setShowSuccessAlert(true); return; } // 收集线索4 collectClue(clue4Id, clue4Name); // 获取线索4的 ref const clue4Ref = getClueRef(clue4Id); // 执行飞行动画 if (clue4Ref.current && clueBookButtonRef.current) { flyToAnimation({ fromRef: clue4Ref 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) => { // 题目2的两个选项都正确,所以总是成功 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); }; // 处理 Cursor 点击 - 切换到主场景 const handleCursorClick = () => { setShowCursor(false); setIsMainScene(true); }; // 获取线索图片 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]); // 如果线索1已收集但还在"窃窃私语"场景,显示 Cursor useEffect(() => { const clue1Id = `${sceneId}/clue1`; if (!isMainScene && isClueCollected(clue1Id)) { setShowCursor(true); } }, [isMainScene, isClueCollected]); // 根据当前场景决定背景图片和显示的线索 const currentBackground = isMainScene ? getBackgroundImage(`${starName}/reflection/scene3/bg`) : getBackgroundImage(`${starName}/reflection/scene3/窃窃私语`); // 根据当前场景过滤线索:窃窃私语场景只显示线索1,主场景显示线索2、3、4 const visibleClues = isMainScene ? clueConfigs.filter((clue) => clue.id !== `${sceneId}/clue1`) : clueConfigs.filter((clue) => clue.id === `${sceneId}/clue1`); return (
{/* 视频播放 - 覆盖在页面内容之上 */} {showVideo && (
)} {/* 关闭按钮 */} { if (moduleName && starName) { navigate(`/${moduleName}/${starName}/reflection`); } }} /> {/* Cursor - 获取线索1后显示,点击进入主场景 */} {showCursor && !isMainScene && ( )} {/* 线索点击区域 */} {visibleClues.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") { 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); } }} /> {/* 错误提示弹窗 */} setShowErrorAlert(false)} zIndex={10001} onMaskClick={() => setShowErrorAlert(false)} /> {/* 学习引导弹窗 */} 后来,学校建立了中国社会主义青年团团支部,你积极靠拢,成为一名光荣的团员。 国共合作大背景下,国民革命正在如火如荼地开展,北伐也在积极酝酿之中。你在自己的岗位上认真工作,也密切关注着时局和两党动态。 {"\n"} 本游戏需要在场景中找出4条线索,并回答正确所有问题后才能完成本游戏探索。 {/* 题目1:冯玉祥发动"北京政变"后邀请孙中山北上共商国是,各界对此事的看法如何? */} {/* 题目2:今天的日记写什么呢? */} {/* 题目3:毅然北上赴会的孙中山先生,为争取国家和平统一作出了哪些努力? */} {/* 完成提示弹窗 */} 辛亥革命拉开了中国完全意义上的近代民族民主革命的序幕。北洋军阀首领袁世凯窃取革命成果后,各地军阀势力对内割据混战,对外出卖国家利益,在政治上谋求专制和独裁,俨然成为民族独立、民主政治、民生幸福之路上的头号绊脚石。 为了改变这一时期的困局,孙中山尝试过高举护法旗帜,两度领导护法运动;与新生的中国共产党展开合作,与无产阶级工农群众共建起统一战线;为了团结一切可以团结的力量,调动一切可以调动的因素,在生命最后的日子里抱病北上,一路不遗余力地向社会各界宣传反帝反封建主张。他经历了太多挫折,却始终以“行”求“知”。
); }; export default SunzhongshanReflectionScene3;