feat:init
This commit is contained in:
1 parent
53d0eeac6b
commit
ae0c050010
494 files changed
+17701
-2318
No files matched your search
@@ -0,0 +1,273 @@
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
Image,
|
||||
Title,
|
||||
Overlay,
|
||||
} from "@/components";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
|
||||
import { useState } from "react";
|
||||
import Cursor from "@/components/cursor";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射,ID 用来做唯一标识
|
||||
const exhibitSrcMap: Record<1 | 2 | 3 | 4, string> = {
|
||||
1: "chenyun/place1/场景1展品1",
|
||||
2: "chenyun/place1/场景1展品2",
|
||||
3: "chenyun/place1/场景1展品3",
|
||||
4: "chenyun/place1/场景1展品4",
|
||||
};
|
||||
const ChenyunPlace1 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
// 学习说明对话框显示状态
|
||||
const [showIntroDialog, setShowIntroDialog] = useState(false);
|
||||
// 引导对话显示状态
|
||||
const [visible, setVisible] = useState(true);
|
||||
// 当前激活的展品 ID(只存 ID,不直接存路径,便于作为唯一标识)
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | 3 | 4 | null>(
|
||||
null
|
||||
);
|
||||
// 已浏览展品的 ID 集合
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2 | 3 | 4) => {
|
||||
setActiveExhibitId(index);
|
||||
};
|
||||
|
||||
const handleStartLearning = () => {
|
||||
setShowIntroDialog(false);
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 4;
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place1/场景1`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="水乡少年·艰辛成长"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/home`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute left-145 top-100"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
{/* 展品2 */}
|
||||
<Cursor
|
||||
className="absolute left-198 top-100"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
/>
|
||||
{/* 展品3 */}
|
||||
<Cursor
|
||||
className="absolute right-170 bottom-60"
|
||||
onClick={() => handleOpenExhibit(3)}
|
||||
read={visited.has(3)}
|
||||
/>
|
||||
{/* 展品4 */}
|
||||
<Cursor
|
||||
className="absolute right-98 top-130 cursor"
|
||||
onClick={() => handleOpenExhibit(4)}
|
||||
read={visited.has(4)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage("chenyun/place1/继续前进")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place2`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<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);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 学习说明对话框 */}
|
||||
{showIntroDialog && (
|
||||
<Overlay
|
||||
selectors={[]}
|
||||
visible={showIntroDialog}
|
||||
maskColor="rgba(0, 0, 0, 0.6)"
|
||||
zIndex={50}
|
||||
>
|
||||
<LearningIntroduction handleStartLearning={handleStartLearning} />
|
||||
</Overlay>
|
||||
)}
|
||||
|
||||
{/* 引导 */}
|
||||
<GuideSteps
|
||||
visible={visible}
|
||||
onVisibleChange={setVisible}
|
||||
showMask={true}
|
||||
highlightSelectors={[]}
|
||||
>
|
||||
<GuideStepsItem speaker="student">
|
||||
小沪!这就是陈云爷爷小时候生活的房子吗?看起来和普通农家差不多,他童年过得艰苦吗?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
这座房子就是陈云故居,位于上海市青浦区练塘镇下塘街95号,是一座坐南朝北、面向河畔的两层楼江南民居。...
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
实际上是陈云舅父母的家,也是少年陈云从4岁至14岁生活的地方。童年的陈云,家庭生活十分不幸。他两岁时父亲病故,四岁时,母亲也悲苦地死去...
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
父母去世后,由外婆抚养。陈云从小跟舅父廖文光和舅母廖倪氏一起生活。家里靠种田和做小生意勉强维持生计。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 学习说明内容
|
||||
const LearningIntroduction = ({
|
||||
handleStartLearning,
|
||||
}: {
|
||||
handleStartLearning: () => void;
|
||||
}) => {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="relative w-full h-full bg-gradient-to-b from-[#f5f1e8] via-[#ede8dc] to-[#e8e0d1] shadow-[0_20px_60px_rgba(0,0,0,0.4)] border-4 border-[#d4c5a9] overflow-hidden">
|
||||
{/* 内容层 */}
|
||||
<div className="relative h-full w-full p-16 pb-20 overflow-hidden flex flex-col">
|
||||
{/* 装饰性顶部线条 */}
|
||||
<div className="absolute top-0 left-0 right-0 h-2 bg-gradient-to-r from-transparent via-[#c9b99b] to-transparent"></div>
|
||||
|
||||
{/* 标题 */}
|
||||
<div className="text-center mb-8 flex-shrink-0">
|
||||
<h1 className="text-6xl font-bold text-[#5c4a37] mb-4 tracking-wide">
|
||||
走进故居-对话模块学习说明
|
||||
</h1>
|
||||
<div className="w-32 h-1 bg-gradient-to-r from-transparent via-[#8b7355] to-transparent mx-auto"></div>
|
||||
</div>
|
||||
|
||||
{/* 介绍文字 */}
|
||||
<div className="mb-8 space-y-4 flex-shrink-0">
|
||||
<p className="text-3xl text-[#6b5d47] leading-relaxed text-center font-medium">
|
||||
同学你好,欢迎来到走进故居-对话学习模块!
|
||||
</p>
|
||||
<p className="text-3xl text-[#6b5d47] leading-relaxed text-center">
|
||||
进入陈云故居场景后,我们将通过参观陈云故居和陈云纪念馆的形式,带你游览陈云同志经历的7个阶段:
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 7个阶段列表 - 卡片式设计 */}
|
||||
<div className="mb-8 bg-[rgba(255,255,255,0.6)] rounded-2xl p-6 border-2 border-[#d4c5a9] flex-shrink-0">
|
||||
<div className="flex flex-wrap items-center justify-center gap-4 text-2xl">
|
||||
{[
|
||||
"水乡少年 艰辛成长",
|
||||
"商务启航 投身革命",
|
||||
"苏区淬炼 崭露头角",
|
||||
"延安担当经济破局",
|
||||
"恢复时期经济奠基",
|
||||
"建设时期 务实兴邦",
|
||||
"改革浪潮 擘画实业",
|
||||
].map((stage, index, array) => (
|
||||
<div key={index} className="flex items-center">
|
||||
<span className="px-4 py-2 bg-[rgba(139,115,85,0.15)] rounded-lg text-[#5c4a37] font-semibold">
|
||||
{stage}
|
||||
</span>
|
||||
{index < array.length - 1 && (
|
||||
<span className="mx-2 text-[#8b7355] font-bold text-3xl">
|
||||
→
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 功能说明列表 */}
|
||||
<div className="mb-8 space-y-4 flex-1 overflow-hidden">
|
||||
<div className="h-full overflow-hidden">
|
||||
{[
|
||||
"走进故居-对话学习模块会包含多个场景,场景中有蓝色动态光点的展品,表示未浏览,可通过点击光点来学习展品背后的故事,学习展品后蓝色动态光点会变为绿色静态光点,表示已浏览;",
|
||||
"场景中的展品有可能会包含一个或多个拼图,游览过程中如获得拼图,会自动掉落拼图并收入拼图盒中,拼图盒可以点开查看当前拼图收集情况,点击单个拼图可以回到获得拼图的场景再次学习;",
|
||||
"所有有蓝色动态光点的展品全部学习后才能进入下一个场景进行学习;",
|
||||
"每个阶段学习过后,会有学习回顾环节,以导图的形式总结了阶段的学习内容;",
|
||||
].map((feature, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-start gap-6 bg-[rgba(255,255,255,0.4)] rounded-xl p-6 border-l-4 border-[#8b7355] mb-4"
|
||||
>
|
||||
<span className="flex-shrink-0 w-12 h-12 bg-gradient-to-br from-[#8b7355] to-[#6b5d47] text-white text-3xl font-bold rounded-full flex items-center justify-center shadow-md">
|
||||
{index + 1}
|
||||
</span>
|
||||
<p className="text-2xl text-[#5c4a37] leading-relaxed flex-1 pt-1">
|
||||
{feature}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 开始学习按钮 */}
|
||||
<div className="flex justify-center flex-shrink-0">
|
||||
<button
|
||||
onClick={handleStartLearning}
|
||||
className="relative cursor-pointer px-20 py-5 bg-gradient-to-r from-[#8b7355] to-[#6b5d47] text-white text-4xl font-bold rounded-2xl shadow-[0_8px_20px_rgba(139,115,85,0.4)] hover:shadow-[0_12px_30px_rgba(139,115,85,0.6)] hover:from-[#9b8365] hover:to-[#7b6d57] transition-all duration-300 active:scale-95 border-2 border-[#a08f75]"
|
||||
>
|
||||
<span className="relative z-10">开始学习</span>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white to-transparent opacity-0 hover:opacity-20 rounded-2xl transition-opacity duration-300"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace1;
|
||||
@@ -0,0 +1,164 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1 | 2, string> = {
|
||||
1: "chenyun/place2/场景2展品1",
|
||||
2: "chenyun/place2/场景2展品2",
|
||||
};
|
||||
|
||||
// 展品描述映射
|
||||
const exhibitDescriptionMap: Record<1 | 2, string> = {
|
||||
1: "同学你看,这里有一幅陈云提写的颜安小学。陈云在青浦县乙种商业学校学习了一个多月后,又因经济困难不得不辍学回家。多亏当地知识分子、颜安小学校长杜枢,他免费保荐陈云入颜安小学高小部读书。颜安小学实行的新式教育开阔了陈云的视野,五四运动后,颜安小学师生积极投入反帝爱国运动,为陈云日后加入中国共产党埋下了思想的种子。",
|
||||
2: "",
|
||||
};
|
||||
const ChenyunPlace2 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
// 当前激活展品 ID,只存 ID 做唯一标识
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | null>(null);
|
||||
// 已浏览展品 ID 集合
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
// GuideSteps 显示状态
|
||||
const [guideVisible, setGuideVisible] = useState(false);
|
||||
// GuideSteps 当前步骤
|
||||
const [guideStep, setGuideStep] = useState(0);
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2) => {
|
||||
if (index === 1) {
|
||||
// 展品1:点击时同时打开展品和引导对话,从第1步开始
|
||||
setActiveExhibitId(1);
|
||||
setGuideVisible(true);
|
||||
setGuideStep(0);
|
||||
} else {
|
||||
// 展品2:直接打开
|
||||
setActiveExhibitId(index);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听GuideSteps步骤变化,仅同步当前步骤
|
||||
const handleGuideStepChange = (step: number) => {
|
||||
setGuideStep(step);
|
||||
};
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 2;
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place2/场景2`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="水乡少年·艰辛成长"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place1`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute left-100 top-100"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
{/* 展品2 */}
|
||||
<Cursor
|
||||
className="absolute left-210 top-100"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-160"
|
||||
src={getStaticImage("chenyun/place2/继续前进2")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place3`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<ExhibitOverlay
|
||||
visible={activeExhibitId !== null}
|
||||
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""}
|
||||
description={
|
||||
activeExhibitId ? exhibitDescriptionMap[activeExhibitId] : undefined
|
||||
}
|
||||
autoPlayDescription={activeExhibitId === 1}
|
||||
onClose={() => {
|
||||
if (activeExhibitId !== null) {
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(activeExhibitId);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
setActiveExhibitId(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1的引导对话 */}
|
||||
<GuideSteps
|
||||
visible={guideVisible}
|
||||
onVisibleChange={setGuideVisible}
|
||||
currentStep={guideStep}
|
||||
onStepChange={handleGuideStepChange}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10000}
|
||||
>
|
||||
<GuideStepsItem speaker="student">
|
||||
那陈云爷爷是怎么有机会到图中的青浦县乙种商业学校读书的呀?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
因为家贫,初小读完的陈云便辍学在家。后在舅母亲戚的资助下,陈云才到青浦县乙种商业学校学习珠算和记账的,他在很短时间里就基本掌握了珠算,还初步学会写账,这为陈云日后从事经济工作打下了基础。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
陈云在党内以“铁算盘”著称,他在经济工作中能熟练使用算盘,就得益于少年时在青浦县立乙种商业学校的学习。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace2;
|
||||
@@ -0,0 +1,171 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
Video,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1 | 2, string> = {
|
||||
1: "chenyun/place3/场景3展品1",
|
||||
2: "chenyun/place3/场景3展品2",
|
||||
};
|
||||
const ChenyunPlace3 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | null>(null);
|
||||
const [videoVisible, setVideoVisible] = useState(false);
|
||||
// GuideSteps 显示状态
|
||||
const [guideVisible, setGuideVisible] = useState(false);
|
||||
// GuideSteps 当前步骤
|
||||
const [guideStep, setGuideStep] = useState(0);
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2) => {
|
||||
if (index === 1) {
|
||||
// 展品1:点击时同时打开展品和引导对话,从第1步开始
|
||||
setActiveExhibitId(1);
|
||||
setGuideVisible(true);
|
||||
setGuideStep(0);
|
||||
} else {
|
||||
// 展品2:先播放视频,结束后再打开展品
|
||||
setVideoVisible(true);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听GuideSteps步骤变化,仅同步当前步骤
|
||||
const handleGuideStepChange = (step: number) => {
|
||||
setGuideStep(step);
|
||||
};
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 2;
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place3/场景3`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 商务启航·投身革命*/}
|
||||
<Title
|
||||
title="商务启航·投身革命"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place2`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute right-200 bottom-75"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
{/* 展品2 */}
|
||||
<Cursor
|
||||
className="absolute right-130 bottom-75"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage("chenyun/place3/继续前进3")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place4`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 展品2视频播放遮罩(全屏) */}
|
||||
{videoVisible && (
|
||||
<div className="fixed inset-0 z-[11001] bg-black">
|
||||
<Video
|
||||
src={getPublicPath("video/chenyun/chenyun_04.mp4")}
|
||||
autoPlay
|
||||
playsInline
|
||||
showSkipButton
|
||||
controls={false}
|
||||
onEnded={() => {
|
||||
setVideoVisible(false);
|
||||
setVisited((p) => new Set(p).add(2));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<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);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1的引导对话 */}
|
||||
<GuideSteps
|
||||
visible={guideVisible}
|
||||
onVisibleChange={setGuideVisible}
|
||||
currentStep={guideStep}
|
||||
onStepChange={handleGuideStepChange}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10000}
|
||||
>
|
||||
<GuideStepsItem speaker="student">
|
||||
陈云14岁就去了上海商务印书馆当学徒,他主要负责哪些工作呢?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
从颜安小学毕业后,陈云进入了商务印书馆当学徒,开始在柜台接待顾客,打珠算、写信封、练包装、理货物、修文具。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
陈云的珠算能力在商务印书馆工作期间有了很大提高。由于工作认真负责,三年的学徒期,陈云提前两年就破格到商务印书馆虹口分店(现为1925书局)当店员。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace3;
|
||||
@@ -0,0 +1,187 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1 | 2, string> = {
|
||||
1: "chenyun/place4/场景4展品1",
|
||||
2: "chenyun/place4/场景4展品2",
|
||||
};
|
||||
const ChenyunPlace4 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | null>(null);
|
||||
// 展品1引导对话
|
||||
const [guideVisible, setGuideVisible] = useState(false);
|
||||
const [guideStep, setGuideStep] = useState(0);
|
||||
// 展品2的引导对话
|
||||
const [guideVisible2, setGuideVisible2] = useState(false);
|
||||
const [guideStep2, setGuideStep2] = useState(0);
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2) => {
|
||||
if (index === 1) {
|
||||
// 展品1:点击时同时打开展品和引导对话
|
||||
setActiveExhibitId(1);
|
||||
setGuideVisible(true);
|
||||
setGuideStep(0);
|
||||
} else {
|
||||
// 展品2:点击时同时打开展品和引导对话
|
||||
setActiveExhibitId(2);
|
||||
setGuideVisible2(true);
|
||||
setGuideStep2(0);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听GuideSteps步骤变化,仅同步当前步骤
|
||||
const handleGuideStepChange = (step: number) => {
|
||||
setGuideStep(step);
|
||||
};
|
||||
|
||||
const handleGuideStepChange2 = (step: number) => {
|
||||
setGuideStep2(step);
|
||||
};
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 2;
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place4/场景4`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="苏区淬炼·崭露头角"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place3`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute left-180 top-120"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
{/* 展品2 */}
|
||||
<Cursor
|
||||
className="absolute right-2 top-100"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage("chenyun/place3/继续前进3")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place5`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<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);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1的引导对话 */}
|
||||
<GuideSteps
|
||||
visible={guideVisible}
|
||||
onVisibleChange={setGuideVisible}
|
||||
currentStep={guideStep}
|
||||
onStepChange={handleGuideStepChange}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10000}
|
||||
>
|
||||
<GuideStepsItem speaker="student">
|
||||
这组史料看起来陈云爷爷前往中央苏区了,他在中央苏区主要负责哪些工作呢?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
1932年3月,陈云担任中共临时中央政治局常委,兼任全国总工会党团书记。1933年1月,陈云离开上海前往中央苏区首府瑞金,继续参加中共中央和全国总工会的领导工作。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
虽然陈云在中央苏区的任务主要是领导工人运动,但是陈云总是能针对一些棘手的经济问题提出较出色的建议。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
在中央苏区时期,陈云也关注和积极参与解决了许多经济难题。1934年,在中共六届五中全会上,陈云被选为中央政治局委员、常委,兼任中央白区工作部部长。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
|
||||
{/* 展品2的引导对话 */}
|
||||
<GuideSteps
|
||||
visible={guideVisible2}
|
||||
onVisibleChange={setGuideVisible2}
|
||||
currentStep={guideStep2}
|
||||
onStepChange={handleGuideStepChange2}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10000}
|
||||
>
|
||||
<GuideStepsItem speaker="student">
|
||||
苏区的经济工作一定不简单,陈云是如何开展工作的呢?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
中央苏区时期的经济斗争,是陈云经济工作能力的“淬炼场”。陈云分析了“左”倾经济政策的表现、危害以及原因,他强调,当务之急是重新严格审查各个企业、工厂以及商店、大小作坊的实际承受力和经济支付能力,
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
从实际出发,实事求是地制定符合中央苏维埃区域每一个工厂、企业、作坊发展需求的劳动政策。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
陈云提议建立合作社,广泛吸收失业工人加入,多听取工人建议、增强企业管理的民主性,从而更好地建设苏区经济。这些做法为他日后主持全国财经工作积累了宝贵经验。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace4;
|
||||
@@ -0,0 +1,159 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
Video,
|
||||
Overlay,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1 | 2 | 3, string> = {
|
||||
1: "chenyun/place5/场景5展品1",
|
||||
2: "chenyun/place5/场景5展品2",
|
||||
3: "chenyun/place5/场景5展品3",
|
||||
};
|
||||
// 展品描述映射
|
||||
const exhibitDescriptionMap: Record<1 | 2 | 3, string> = {
|
||||
1: "",
|
||||
2: "延安时期因为国民党的封锁,陕甘宁边区经济困难。陈云转战陕甘宁边区主持财经工作,他遇到了很多经济难题。1944年新春伊始,陈云开始担任西北财经办事处副主任,工作转到财经方面,这是陈云以主要精力从事领导经济工作的开始。当时,陕甘宁边区在国民党严密封锁下,财经状况严峻,边区物价猛涨,老百姓日常生活必需的布匹和粮食十分缺乏。国民党顽固派封锁边区,企图“不让一粒粮、一尺布进入边区”,同时千方百计阻止边区食盐出口。",
|
||||
3: "",
|
||||
};
|
||||
const ChenyunPlace5 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | 3 | null>(
|
||||
null
|
||||
);
|
||||
const [videoVisible3, setVideoVisible3] = useState(false);
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2 | 3) => {
|
||||
if (index === 3) {
|
||||
// 展品3:播放视频,不打开展品
|
||||
setVideoVisible3(true);
|
||||
return;
|
||||
}
|
||||
setActiveExhibitId(index);
|
||||
};
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 3;
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place5/场景5`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="延安担当·经济破局"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place4`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute left-30 top-70"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
{/* 展品2 */}
|
||||
<Cursor
|
||||
className="absolute left-107 top-72"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
/>
|
||||
|
||||
{/* 展品3 */}
|
||||
<Cursor
|
||||
className="absolute right-170 top-84"
|
||||
onClick={() => handleOpenExhibit(3)}
|
||||
read={visited.has(3)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-5 right-20"
|
||||
src={getStaticImage("chenyun/place5/继续前进4")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place6`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 展品3视频播放(全屏) */}
|
||||
{videoVisible3 && (
|
||||
<Video
|
||||
src={getPublicPath("video/chenyun/chenyun_07.mp4")}
|
||||
className="w-full h-full"
|
||||
autoPlay
|
||||
playsInline
|
||||
showSkipButton
|
||||
onEnded={() => {
|
||||
setVideoVisible3(false);
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(3);
|
||||
return next;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<ExhibitOverlay
|
||||
visible={activeExhibitId !== null}
|
||||
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""}
|
||||
description={
|
||||
activeExhibitId ? exhibitDescriptionMap[activeExhibitId] : undefined
|
||||
}
|
||||
autoPlayDescription={activeExhibitId === 2}
|
||||
onClose={() => {
|
||||
if (activeExhibitId !== null) {
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(activeExhibitId);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
setActiveExhibitId(null);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace5;
|
||||
@@ -0,0 +1,137 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1, string> = {
|
||||
1: "chenyun/place6/场景6展品1",
|
||||
};
|
||||
const ChenyunPlace6 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | null>(null);
|
||||
const [guideVisible, setGuideVisible] = useState(false);
|
||||
const [guideStep, setGuideStep] = useState(0);
|
||||
|
||||
const handleOpenExhibit = () => {
|
||||
// 展品1:点击时同时打开展品和引导对话,从第1步开始
|
||||
setActiveExhibitId(1);
|
||||
setGuideVisible(true);
|
||||
setGuideStep(0);
|
||||
};
|
||||
|
||||
const handleGuideStepChange = (step: number) => {
|
||||
setGuideStep(step);
|
||||
};
|
||||
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place6/场景6`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="恢复时期·经济奠基"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place5`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute left-230 bottom-80"
|
||||
onClick={handleOpenExhibit}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage("chenyun/place6/继续前进5")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place7`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<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);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1的引导对话 */}
|
||||
<GuideSteps
|
||||
visible={guideVisible}
|
||||
onVisibleChange={setGuideVisible}
|
||||
currentStep={guideStep}
|
||||
onStepChange={handleGuideStepChange}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10000}
|
||||
>
|
||||
<GuideStepsItem speaker="student">
|
||||
这是中央人民政府院财政经济委员会的印章,到这个时候陈云已经从地方到中央工作了吗?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
是的,新中国刚成立时,中国共产党接管的是一个民穷财尽、物价飞涨的烂摊子。面对财政经济上的严重困难,陈云在1949年受命担任新成立的中央财政经济委员会(简称中财委)主任,主持领导全国财政经济工作。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
陈云挂帅后的首仗就是打击投机、平抑物价。通过“银元之战”“两白一黑”战役等几次严峻斗争,只用不到一年时间,就迅速稳定了金融物价。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace6;
|
||||
@@ -0,0 +1,382 @@
|
||||
import { useState, useRef } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
Video,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
type SingleChoiceOption,
|
||||
type DragFillResult,
|
||||
QuizPanel,
|
||||
} 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. 推动了淮海战役的胜利(错误选项,选后提示:淮海战役于1949年1月胜利结束,发生在这次“银元之战”前,不存在因果关系)",
|
||||
},
|
||||
{
|
||||
value: "B",
|
||||
label:
|
||||
"B. 有利于稳定人民的发行和地位(正确选项,选后提示:“银元之战”属于当时人民政府整顿金融的重要举措,黄金、银元投机不利于人民币币值稳定和流通,因此“银元之战”打击贵属投机活动,有利于稳定人民币的发行和地位)",
|
||||
},
|
||||
{
|
||||
value: "C",
|
||||
label:
|
||||
"C. 巩固了新中国人民政权(错误选项,选后提示:1949年6月新中国政权尚未建立)",
|
||||
},
|
||||
];
|
||||
|
||||
const ChenyunPlace7 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | null>(null);
|
||||
const [videoVisible1, setVideoVisible1] = useState(false);
|
||||
const [videoPlaying, setVideoPlaying] = useState(false);
|
||||
const videoRef = useRef<VideoRef>(null);
|
||||
// 单选题
|
||||
const [quizVisible, setQuizVisible] = useState(false);
|
||||
const [quizAnswer, setQuizAnswer] = useState<string>("");
|
||||
const [quizError, setQuizError] = useState<string>("");
|
||||
// 展品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<VideoRef>(null);
|
||||
const [guideVisible2, setGuideVisible2] = useState(false);
|
||||
const [guideStep2, setGuideStep2] = useState(0);
|
||||
const [quiz2Visible, setQuiz2Visible] = useState(false);
|
||||
const [quiz2Error, setQuiz2Error] = useState<string>("");
|
||||
const [quiz2Value, setQuiz2Value] = useState<DragFillResult[]>([]);
|
||||
// 成功提示
|
||||
const [successAlertVisible, setSuccessAlertVisible] = useState(false);
|
||||
// 标记拖拽题是否已完成
|
||||
const [quiz2Completed, setQuiz2Completed] = useState(false);
|
||||
|
||||
const handleOpenExhibit = (_index: 1) => {
|
||||
// 展品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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place7/场景7`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="恢复时期·经济奠基"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<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("再想一想,注意题干中的时间和提示信息哦~");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 视频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>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace7;
|
||||
@@ -0,0 +1,158 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getStaticImage } from "@/lib/utils";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
// starName 固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1 | 2, string> = {
|
||||
1: "chenyun/place8/场景8展品1",
|
||||
2: "chenyun/place8/场景8展品2",
|
||||
};
|
||||
const ChenyunPlace8 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | null>(null);
|
||||
// 展品2的对话引导
|
||||
const [guideVisible, setGuideVisible] = useState(false);
|
||||
const [guideStep, setGuideStep] = useState(0);
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2) => {
|
||||
setActiveExhibitId(index);
|
||||
// 如果是展品2,显示对话引导
|
||||
if (index === 2) {
|
||||
setGuideVisible(true);
|
||||
setGuideStep(0);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听对话引导步骤变化
|
||||
const handleGuideStepChange = (step: number) => {
|
||||
setGuideStep(step);
|
||||
};
|
||||
|
||||
// 监听对话引导完成
|
||||
const handleGuideVisibleChange = (visible: boolean) => {
|
||||
setGuideVisible(visible);
|
||||
};
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 2;
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place8/场景8`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="建设时期·务实兴邦"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place7`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute right-175 top-75"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
{/* 展品2 */}
|
||||
<Cursor
|
||||
className="absolute right-100 bottom-55"
|
||||
onClick={() => handleOpenExhibit(2)}
|
||||
read={visited.has(2)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-150"
|
||||
src={getStaticImage("chenyun/place8/继续前进6")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place9`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 遮罩层 */}
|
||||
<ExhibitOverlay
|
||||
visible={activeExhibitId !== null}
|
||||
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""}
|
||||
description={
|
||||
activeExhibitId === 1
|
||||
? `打赢"银元之战""两白一黑"战役的过程彰显了中国共产党治理经济的卓越能力!这里有一份"一五"计划报告的手稿,陈云在"一五"计划的编制中做出了重大贡献。一九五四年,陈云的主要工作之一,就是主持编制第一个五年计划纲要。这次编制工作是在前四次基础上进行的,陈云提出计划编制工作中要注意几个问题:首先是工业投资金额,其次是市场供应和人民生活,第三是农业发展速度,这三个问题对编制计划有指导意义。第一个五年计划纲要草案的重点是优先发展重工业,特别是156项重点工程。当时陈云重点抓重工业建设和粮食保障,通过"统购统销"稳定粮价,为重点工程项目筑牢根基,亲手铺就了我国工业化的起步之路。`
|
||||
: undefined
|
||||
}
|
||||
onClose={() => {
|
||||
if (activeExhibitId !== null) {
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(activeExhibitId);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
setActiveExhibitId(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品2的对话引导 - 在展品遮罩层上方显示 */}
|
||||
<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>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChenyunPlace8;
|
||||
@@ -0,0 +1,177 @@
|
||||
import { useState, useRef } from "react";
|
||||
import {
|
||||
ExhibitOverlay,
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
Video,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
} from "@/components";
|
||||
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/place9/场景9展品1",
|
||||
};
|
||||
const ChenyunPlace9 = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
|
||||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | null>(null);
|
||||
// 视频播放状态
|
||||
const [videoVisible, setVideoVisible] = useState(false);
|
||||
const [videoPlaying, setVideoPlaying] = useState(false);
|
||||
const videoRef = useRef<VideoRef>(null);
|
||||
// 对话引导状态
|
||||
const [guideVisible, setGuideVisible] = useState(false);
|
||||
const [guideStep, setGuideStep] = useState(0);
|
||||
|
||||
const handleOpenExhibit = (_index: 1) => {
|
||||
// 展品1:播放视频
|
||||
setVideoVisible(true);
|
||||
setVideoPlaying(true);
|
||||
};
|
||||
|
||||
// 监听对话引导步骤变化
|
||||
const handleGuideStepChange = (step: number) => {
|
||||
setGuideStep(step);
|
||||
};
|
||||
|
||||
// 监听对话引导完成
|
||||
const handleGuideVisibleChange = (visible: boolean) => {
|
||||
setGuideVisible(visible);
|
||||
if (!visible && videoVisible) {
|
||||
setVideoVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
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 (
|
||||
<div
|
||||
className="w-full h-full bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage(`chenyun/place9/场景9`),
|
||||
}}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<Title
|
||||
title="改革时期·擘画实业"
|
||||
subtitle={subtitle}
|
||||
subtitleClassName={subtitleClassName}
|
||||
className="absolute top-10 left-1/2 -translate-x-1/2"
|
||||
/>
|
||||
|
||||
{/* 返回上一章 */}
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/place8`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 展品1 */}
|
||||
<Cursor
|
||||
className="absolute right-26 top-88"
|
||||
onClick={() => handleOpenExhibit(1)}
|
||||
read={visited.has(1)}
|
||||
/>
|
||||
|
||||
{/* 离开场景 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage("chenyun/place9/离开场景")}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/home`);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 展品1视频播放(全屏) */}
|
||||
{videoVisible && (
|
||||
<div className="fixed inset-0 z-[9999] bg-black">
|
||||
<Video
|
||||
ref={videoRef}
|
||||
src={getPublicPath("video/chenyun/chenyun_14.mp4")}
|
||||
className="w-full h-full"
|
||||
autoPlay={videoPlaying}
|
||||
playsInline
|
||||
preload="auto"
|
||||
muted={!videoPlaying}
|
||||
showSkipButton
|
||||
skipText="跳过"
|
||||
onEnded={() => {
|
||||
setVideoPlaying(false);
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(1);
|
||||
return next;
|
||||
});
|
||||
// 视频播放完成后,显示对话引导
|
||||
setGuideVisible(true);
|
||||
setGuideStep(0);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 视频播放完成后的对话引导 */}
|
||||
<GuideSteps
|
||||
visible={guideVisible}
|
||||
onVisibleChange={handleGuideVisibleChange}
|
||||
currentStep={guideStep}
|
||||
onStepChange={handleGuideStepChange}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10001}
|
||||
>
|
||||
<GuideStepsItem speaker="guide">
|
||||
我们已经沿着陈云的足迹,从练塘水乡走到改革开放的前沿,读懂了他"适合老百姓的要求,做了一点事"的初心。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
接下来,请你跨越时空,走进1949年刚解放时期的上海,参与到当时那场轰轰烈烈的"银元之战"和"米棉之战"之中去,在实践决策中体会,陈云"多谋善断""敢闯务实"的卓越智慧与战略魄力,感受我国集中力量办大事的制度优势如何在经济战场中彰显威力。
|
||||
</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 ChenyunPlace9;
|
||||
Reference in new issue
Block a user