feat: 添加新页面和更新导航逻辑,增强用户体验

- 在 Maozedong 组件中添加新的图像按钮,更新导航至不同的地点页面。
- 在路由配置中引入新的地点页面组件,支持用户访问不同的展览位置。
- 确保导航逻辑与新页面一致,提升用户交互体验。
This commit is contained in:
zhongyidian committed 2026-02-26 11:12:06 +08:00
1 parent 7bbeb10e57
commit 2c8bc73e57
24 files changed
+699 -3

No files matched your search

+188
View File
@@ -0,0 +1,188 @@
import {
ExhibitOverlay,
GuideSteps,
GuideStepsItem,
Image,
Title,
} from "@/components";
import { useNavigate, useParams } from "react-router-dom";
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
import { useState } from "react";
import Cursor from "@/components/cursor";
import { useCursorController } from "@/hooks/useCursorController";
// starName 固定为 maozedong
const starName = "maozedong";
// 展品 ID 与资源路径映射,ID 用来做唯一标识
const exhibitSrcMap: Record<1 | 2 | 3 | 4 | 5 | 6, string> = {
1: "maozedong/place4/场景4展品1",
2: "maozedong/place4/场景4展品2",
3: "maozedong/place4/场景4展品3",
4: "maozedong/place4/场景4展品4",
5: "maozedong/place4/场景4展品5",
6: "maozedong/place4/场景4展品6",
};
const MaozedongPlace4 = () => {
const navigate = useNavigate();
const { moduleName } = useParams<{
moduleName: string;
}>();
// 引导对话显示状态
const [visible, setVisible] = useState(false);
// 当前激活的展品 ID
const [activeExhibitId, setActiveExhibitId] = useState<
1 | 2 | 3 | 4 | 5 | 6 | null
>(null);
// 已访问的展品(本页内状态;如需持久化可接入 store)
const [visited, setVisited] = useState<Set<1 | 2 | 3 | 4 | 5 | 6>>(
() => new Set()
);
// Cursor 顺序控制:1 -> 2 -> 3 -> 4 -> 5 -> 6
const { isEnabled } = useCursorController({
initialEnabled: [1],
dependencies: {
2: [1],
3: [1, 2],
4: [1, 2, 3],
5: [1, 2, 3, 4],
6: [1, 2, 3, 4, 5],
},
visited,
});
const handleOpenExhibit = (id: 1 | 2 | 3 | 4 | 5 | 6) => {
setActiveExhibitId(id);
};
if (!moduleName) return null;
const progressCount = visited.size;
const total = 6;
const completed = progressCount >= total;
const subtitle = completed
? "关于中共四大(已完成)"
: `关于中共四大(${progressCount}/${total})`;
return (
<div
className="w-full h-full bg-cover bg-center bg-no-repeat"
style={{
backgroundImage: getBackgroundImage(`${starName}/place4/场景4`),
}}
>
{/* 标题 */}
<Title
title="唤起工农群众"
subtitle={subtitle}
className="absolute top-10 left-1/2 -translate-x-1/2"
/>
{completed && (<Image
className="absolute right-0 bottom-0"
src={getStaticImage("components/place/离开场景")}
button
onClick={() => {
if (moduleName && starName) {
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-179 bottom-163"
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)}
/>
{/* 光标4 */}
<Cursor
className="absolute left-212 bottom-123"
onClick={() => handleOpenExhibit(4)}
read={visited.has(4)}
disabled={!isEnabled(4)}
/>
{/* 光标5 */}
<Cursor
className="absolute right-186 bottom-162"
onClick={() => handleOpenExhibit(5)}
read={visited.has(5)}
disabled={!isEnabled(5)}
/>
{/* 光标6 */}
<Cursor
className="absolute right-153 bottom-123"
onClick={() => handleOpenExhibit(6)}
read={visited.has(6)}
disabled={!isEnabled(6)}
/>
{/* 场景对话 */}
<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>
{/* 展品遮罩层 */}
<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);
}}
/>
</div>
);
};
export default MaozedongPlace4;