import { ExhibitOverlay, Image, Title, Cursor, GuideSteps, GuideStepsItem, SingleChoiceQuizPanel, } from "@/components"; import { useNavigate, useParams } from "react-router-dom"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils"; import { useState } from "react"; import SuccessAlert from "@/components/layout/alert/success-alert"; import { useCursorController } from "@/hooks/useCursorController"; import { usePuzzleAnimation } from "@/contexts/PuzzleAnimationContext"; import { useLuxunStore } from "@/store/luxunStore"; // starName 固定为 luxun const starName = "luxun"; // 展品 ID 与资源路径映射 const exhibitSrcMap: Record<1 | 2 | 3 | 4 | 5, string> = { 1: "luxun/place3/6", 2: "luxun/place3/7", 3: "luxun/place3/8", 4: "luxun/place3/9", 5: "luxun/place3/10", }; const quiz2DefaultError = "再想一想,注意题干中的时间和提示信息哦~"; const quiz2Explanations: Record = { A: "鲁迅身处旧中国文艺思惰僵化、缺乏革新活力的时代,他认为“没有拿来的,人不能自成为新人”。翻译外国作品正是为了打破文化封闭,为中国文艺引进新思想、新方法,为沉寂的文坛注入新血液。", B: "当时中国青年普遍受传统旧思想束缚,接触先进文化的渠道有限。鲁迅希望通过翻译外国进步作品,让青年接触世界范围内的先进文化理念、思想成果,拓宽视野、启发心智,助力青年觉醒。", C: "鲁迅的核心斗争方式是“以笔为刃”,通过文学创作、翻译、杂文批判等方式开展思想启蒙和文化斗争,从未直接参与武装革命的战略部署。", D: "在国民党“文化围剿”、进步思想遭严控的背景下,鲁迅将翻译视为重要的斗争武器——通过引进外国进步文学、马克思主义理论等,揭露旧中国的黑暗与愚昧,唤醒民众的思想意识,助力思想启蒙运动。", }; // 光标5-题目:纪念瞿秋白的译文集 const quiz5DefaultError = "再想一想,结合前面的旁白内容哦~"; const quiz5Explanations: Record = { A: "《仿自由书》是鲁迅在上海创作的杂文集,收录了1933年所作的多篇杂文,核心内容是针砭国民党当局的虚伪统治、批判社会乱象,并非为纪念瞿秋白编校的译文集。", B: "《南腔北调集》是鲁迅的一部杂文集,收录了1927年至1933年的杂文作品,书名源于鲁迅对自己文章“不入调、不入流”的自嘲,内容涵盖文化批判、社会评论等,与纪念瞿秋白及译文集无关。", C: "恭喜你,选对啦。", D: "《故事新编》是鲁迅的历史小说集,酝酿多年后在大陆新村9号完成定稿。作品以神话传说、历史典故为载体借古讽今,批判现实社会的腐朽与愚昧,并非译文集,更与纪念瞿秋白无关。", }; const LuxunPlace3 = () => { const navigate = useNavigate(); const { moduleName } = useParams<{ moduleName: string; }>(); //碎片动画触发方法 const { triggerPuzzleAnimation } = usePuzzleAnimation(); const [activeExhibitId, setActiveExhibitId] = useState< 1 | 2 | 3 | 4 | 5 | null >(null); // 使用持久化的访问状态 const place = "place3"; const { markExhibitVisited, getVisitedExhibits } = useLuxunStore(); // 从 store 获取已访问的展品,转换为 Set 用于兼容现有代码 const visitedExhibits = getVisitedExhibits(place); const visited = new Set(visitedExhibits); // Cursor 顺序控制:1 -> 2 -> 3 -> 4 -> 5 const { isEnabled } = useCursorController({ initialEnabled: [1], dependencies: { 2: [1], 3: [2], 4: [3], 5: [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 [quiz2Visible, setQuiz2Visible] = useState(false); const [successAlert2Visible, setSuccessAlert2Visible] = useState(false); const [quiz2Error, setQuiz2Error] = useState(quiz2DefaultError); // 光标3的引导对话状态 const [guide3Visible, setGuide3Visible] = useState(false); const [guide3Step, setGuide3Step] = useState(0); // 光标4的引导对话状态 const [guide4Visible, setGuide4Visible] = useState(false); const [guide4Step, setGuide4Step] = useState(0); // 光标5的题目 & 成功提示 & 引导对话状态 const [quiz5Visible, setQuiz5Visible] = useState(false); const [quiz5Error, setQuiz5Error] = useState(quiz5DefaultError); const [successAlert5Visible, setSuccessAlert5Visible] = useState(false); const [guide5Visible, setGuide5Visible] = useState(false); const [guide5Step, setGuide5Step] = useState(0); const handleOpenExhibit = (index: 1 | 2 | 3 | 4 | 5) => { if (index === 1) { // 光标1:点击时同时打开展品和引导对话 setActiveExhibitId(1); setGuide1Visible(true); setGuide1Step(0); } else if (index === 2) { // 光标2:只打开展品(带描述) setActiveExhibitId(2); setGuide2Visible(true); setGuide2Step(0); } else if (index === 3) { // 光标3:点击时同时打开展品和引导对话 setActiveExhibitId(3); setGuide3Visible(true); setGuide3Step(0); } else if (index === 4) { // 光标4:点击时同时打开展品和引导对话 setActiveExhibitId(4); setGuide4Visible(true); setGuide4Step(0); } else { // 光标5:先打开展品,关闭后进入答题 setActiveExhibitId(index); } }; const progressCount = visited.size; const total = 5; 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`); } }} /> {/* 光标1 */} <Cursor className="absolute right-114 bottom-130" onClick={() => handleOpenExhibit(1)} size={0.6} read={visited.has(1)} disabled={!isEnabled(1)} /> {/* 光标2 */} <Cursor className="absolute right-130 bottom-115" onClick={() => handleOpenExhibit(2)} size={0.6} read={visited.has(2)} disabled={!isEnabled(2)} /> {/* 光标3 */} <Cursor className="absolute left-76 bottom-140" onClick={() => handleOpenExhibit(3)} size={0.6} read={visited.has(3)} disabled={!isEnabled(3)} /> {/* 光标4 */} <Cursor className="absolute right-238 bottom-125" onClick={() => handleOpenExhibit(4)} size={0.6} read={visited.has(4)} disabled={!isEnabled(4)} /> {/* 光标5 */} <Cursor className="absolute right-258 bottom-118" onClick={() => handleOpenExhibit(5)} size={0.6} read={visited.has(5)} disabled={!isEnabled(5)} /> {completed && ( <Image className="absolute bottom-0 right-130" src={getStaticImage("luxun/place3/前进按钮")} button onClick={() => { navigate(`/${moduleName}/${starName}/place4`); }} /> )} <ExhibitOverlay visible={activeExhibitId !== null} src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""} onOpen={()=>{ if( activeExhibitId === 1){ triggerPuzzleAnimation(6); } if( activeExhibitId === 2){ triggerPuzzleAnimation(7); } if( activeExhibitId === 3){ triggerPuzzleAnimation(8); } if( activeExhibitId === 4){ triggerPuzzleAnimation(9); } if( activeExhibitId === 5){ triggerPuzzleAnimation(10); } }} description={ activeExhibitId === 5 ? "为了妥善出版亡友遗著,鲁迅亲自选稿、校对、设计封面。为了躲避反动派的审查,他还特意用“诸夏怀霜社”的名义出版,“怀霜”就是为了纪念瞿秋白。1936年《海上述林》上卷出版时,鲁迅的身体已经极度虚弱,但他仍一遍遍翻看样书,说“这是我对秋白最好的纪念”。" : undefined } audioSrc={ activeExhibitId === 5 ? getPublicPath("audio/luxun/mp3_luxun_23.mp3") : undefined } onClose={() => { if (activeExhibitId === 2) { // 光标2:关闭展品框后显示题目 setActiveExhibitId(null); setQuiz2Visible(true); } else if (activeExhibitId === 5) { // 光标5:关闭展品框后显示题目 setActiveExhibitId(null); setQuiz5Visible(true); } else if (activeExhibitId === 1 || activeExhibitId === 3) { // 光标1和光标3:只关闭展品,不标记为已读(等对话关闭时再标记) setActiveExhibitId(null); } else if (activeExhibitId === 4) { // 光标4:只关闭展品,不标记为已读(等对话关闭时再标记) setActiveExhibitId(null); } else { // 其他光标:正常关闭并标记为已读 if (activeExhibitId !== null) { markExhibitVisited(place, activeExhibitId); } setActiveExhibitId(null); } }} /> {/* 光标1的引导对话 */} <GuideSteps visible={guide1Visible} onVisibleChange={(visible) => { setGuide1Visible(visible); if (!visible) { // 对话关闭时,标记光标1为已读 markExhibitVisited(place, 1); } }} currentStep={guide1Step} onStepChange={setGuide1Step} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath("audio/luxun/mp3_luxun_15.mp3")} > 小沪,书架上还有《故事新编》,这不是历史小说吗?鲁迅为什么要在这个时期写古代故事呢? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath("audio/luxun/mp3_luxun_16.mp3")} > 《故事新编》是鲁迅酝酿十几年的作品,最终在大陆新村9号完成定稿。表面上写的是神话传说和历史典故,实则句句都在影射现实。当时反动派妄图用复古思想麻痹民众,鲁迅就用"故事新编"的方式,借古讽今,唤醒民众。 </GuideStepsItem> </GuideSteps> {/* 光标2的引导对话 */} <GuideSteps visible={guide2Visible} onVisibleChange={setGuide2Visible} currentStep={guide2Step} onStepChange={setGuide2Step} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath("audio/luxun/mp3_luxun_17.mp3")} > 这本书里面还收录了《理水》,是大禹治水的故事吗? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath("audio/luxun/mp3_luxun_18.mp3")} > 不错,文章写的是大禹治水“三过家门而不入”的上古传说,实则藏着对现实的尖锐针砭。当时反动派统治腐朽,面对内忧外患只会粉饰太平,还有一群空谈理论、脱离实际的“学者”混淆视听。 </GuideStepsItem> <GuideStepsItem speaker="guide"> 大禹带领民众跋山涉水、实地勘察,摒弃“堵”的旧法改用“疏”的良方,历经千辛万苦终平水患。这哪里是写古代治水?分明是在赞颂脚踏实地、敢破敢立的实干精神,讽刺那些庸碌无为的当权者与空谈家,用远古的正义之光映照现实的黑暗。 </GuideStepsItem> </GuideSteps> {/* 光标2的题目 */} <SingleChoiceQuizPanel visible={quiz2Visible} title="【单选】鲁迅在上海大陆新村9号居住期间,翻译外国作品的核心目的不包括:" options={[ { value: "A", label: "A.为中国文艺引进新思想、新血液", }, { value: "B", label: "B.让中国青年接触更先进的文化理念", }, { value: "C", label: "C.直接参与武装革命的战略部署", }, { value: "D", label: "D.以翻译为武器助力思想启蒙", }, ]} correctAnswer="C" errorMessage={quiz2Error} onSubmit={(value, isCorrect) => { if (isCorrect) { setQuiz2Error(quiz2DefaultError); setQuiz2Visible(false); setSuccessAlert2Visible(true); } }} onWrongSelect={(value) => { const explanation = quiz2Explanations[value]; if (explanation) { setQuiz2Error(explanation); return explanation; } setQuiz2Error(quiz2DefaultError); return quiz2DefaultError; }} zIndex={10001} /> {/* 光标2的成功提示 */} <SuccessAlert visible={successAlert2Visible} content={ "鲁迅的核心斗争方式是“以笔为刃”,通过文学创作、翻译、杂文批判等方式开展思想启蒙和文化斗争,从未直接参与武装革命的战略部署。" } onContinue={() => { setSuccessAlert2Visible(false); // 标记光标2为已读 markExhibitVisited(place, 2); }} /> {/* 光标3的引导对话 */} <GuideSteps visible={guide3Visible} onVisibleChange={(visible) => { setGuide3Visible(visible); if (!visible) { // 对话关闭时,标记光标3为已读 markExhibitVisited(place, 3); } }} currentStep={guide3Step} onStepChange={setGuide3Step} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath("audio/luxun/mp3_luxun_19.mp3")} > 我还看到书架上有很多翻译作品,这也是他在这儿完成的吗? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath("audio/luxun/mp3_luxun_20.mp3")} > 没错!鲁迅在这儿翻译了《死魂灵》《表》等大量外国作品。他说"没有拿来的,人不能自成为新人",就是想通过翻译,为中国文艺引进新思想、新方法,让更多人看到世界的真相,找到救国的道路。 </GuideStepsItem> </GuideSteps> {/* 光标4的引导对话 */} <GuideSteps visible={guide4Visible} onVisibleChange={(visible) => { setGuide4Visible(visible); if (!visible) { // 对话关闭时,标记光标4为已读 markExhibitVisited(place, 4); } }} currentStep={guide4Step} onStepChange={setGuide4Step} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath("audio/luxun/mp3_luxun_21.mp3")} > 小沪,这两本书看起来格外厚重,它和鲁迅在这儿的经历有什么关联呢? </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath("audio/luxun/mp3_luxun_22.mp3")} > 这不是鲁迅的著作,却是他在大陆新村9号倾注了全部心血的作品——为亡友瞿秋白编辑的译文集《海上述林》。1935年6月,瞿秋白被国民党反动派杀害,鲁迅悲痛万分,当即决定要为挚友出版译文集,让他的思想和精神流传下去。 </GuideStepsItem> </GuideSteps> {/* 光标5的题目 */} <SingleChoiceQuizPanel visible={quiz5Visible} title="【单选】鲁迅在上海大陆新村9号居住期间,为纪念瞿秋白编校的译文集是:" options={[ { value: "A", label: "A.《仿自由书》" }, { value: "B", label: "B.《南腔北调集》" }, { value: "C", label: "C.《海上述林》" }, { value: "D", label: "D.《故事新编》" }, ]} correctAnswer="C" errorMessage={quiz5Error} onSubmit={(value, isCorrect) => { if (isCorrect) { setQuiz5Error(quiz5DefaultError); setQuiz5Visible(false); setSuccessAlert5Visible(true); } }} onWrongSelect={(value) => { const explanation = quiz5Explanations[value]; if (explanation) { setQuiz5Error(explanation); return explanation; } setQuiz5Error(quiz5DefaultError); return quiz5DefaultError; }} zIndex={10001} /> {/* 光标5的成功提示 */} <SuccessAlert visible={successAlert5Visible} onContinue={() => { setSuccessAlert5Visible(false); // 标记光标5为已读 markExhibitVisited(place, 5); // 打开光标5的引导对话 setGuide5Visible(true); setGuide5Step(0); }} /> {/* 光标5的引导对话 */} <GuideSteps visible={guide5Visible} onVisibleChange={(visible) => { setGuide5Visible(visible); }} currentStep={guide5Step} onStepChange={setGuide5Step} showMask={false} highlightSelectors={[]} zIndex={10000} > <GuideStepsItem speaker="student" audioSrc={getPublicPath("audio/luxun/mp3_luxun_24.mp3")} > 原来这本书不仅是译文集,更是两人革命友谊和共同信仰的见证! </GuideStepsItem> <GuideStepsItem speaker="guide" audioSrc={getPublicPath("audio/luxun/mp3_luxun_25.mp3")} > 太对了!鲁迅和瞿秋白的故事不仅在于《海上述林》的字里行间,这座小楼的三楼也藏着他们为了革命事业并肩战斗的初心。 </GuideStepsItem> </GuideSteps> </div> ); }; export default LuxunPlace3;