feat: 添加音频资源和更新引导对话,提升学习体验

- 在多个场景中引入音频文件,增强互动性和沉浸感。
- 更新引导对话文本,确保信息准确性和一致性。
- 调整组件结构,清理冗余代码,提升可维护性。
- 引入结束窗口,鼓励用户深入了解黄炎培的教育理念。
This commit is contained in:
zhongyidian committed 2026-01-16 00:00:12 +08:00
1 parent 6e106032fd
commit a8723ab4aa
12 files changed
+158 -36

No files matched your search

+27 -3
View File
@@ -36,7 +36,7 @@ export const EndingOverlay = ({
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
// 结语音频:默认自动播放,支持按 channel 分组互斥 // 结语音频:默认自动播放,支持按 channel 分组互斥
const { currentSrc, play, stop } = useAudioManager( const { currentSrc, isPlaying, play, stop } = useAudioManager(
audioChannelId audioChannelId
? { ? {
mode: "channel", mode: "channel",
@@ -83,18 +83,42 @@ export const EndingOverlay = ({
play(audioSrc); play(audioSrc);
}, [visible, autoPlayAudio, audioSrc, play]); }, [visible, autoPlayAudio, audioSrc, play]);
// 全部文字出现后 1 秒自动关闭 // 全部文字出现后自动关闭(如果有音频,需等待音频播放完成)
useEffect(() => { useEffect(() => {
if (!visible) return; if (!visible) return;
if (isAnimating) return; if (isAnimating) return;
if (!text || displayedText !== text) return; if (!text || displayedText !== text) return;
// 如果有音频,需要等待音频播放完成
if (audioSrc) {
// 检查当前播放的音频是否是我们期望的音频,且已播放完成
if (currentSrc === audioSrc && !isPlaying) {
// 音频播放完成后,等待 800ms 再关闭
const timer = setTimeout(() => {
onContinue();
}, 800);
return () => clearTimeout(timer);
}
// 音频还在播放,等待播放完成
return;
}
// 没有音频,文字动画完成后等待 800ms 关闭
const timer = setTimeout(() => { const timer = setTimeout(() => {
onContinue(); onContinue();
}, 800); }, 800);
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [visible, isAnimating, displayedText, text, onContinue]); }, [
visible,
isAnimating,
displayedText,
text,
audioSrc,
currentSrc,
isPlaying,
onContinue,
]);
if (!visible) return null; if (!visible) return null;
+12 -3
View File
@@ -401,13 +401,19 @@ const HuangyanpeiInternalization = () => {
}} }}
showMask={false} showMask={false}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_28.mp3")}
>
小沪,刚刚结束的"小职成长记"太有意思了!我变成百年前的川沙少年选课程、做手工、设计国货推销方案,好像真的走进了黄炎培先生的职教世界。 小沪,刚刚结束的"小职成长记"太有意思了!我变成百年前的川沙少年选课程、做手工、设计国货推销方案,好像真的走进了黄炎培先生的职教世界。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="student"> <GuideStepsItem speaker="student">
但我还有一个疑问:先生当年倡导的"手脑并用、工学结合",放在我们现在的中职学习中,到底有什么样的意义呢? 但我还有一个疑问:先生当年倡导的"手脑并用、工学结合",放在我们现在的中职学习中,到底有什么样的意义呢?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_29.mp3")}
>
这个问题问到点子上啦!黄炎培先生的职教思想,从来不是尘封的历史,而是活在当下的行动指南。今天我们特别邀请到中华职业教育社第十三届理事会常务理事、中华职业学校党总支副书记、校长黄玉璟,让她带我们解码先生精神的时代密码! 这个问题问到点子上啦!黄炎培先生的职教思想,从来不是尘封的历史,而是活在当下的行动指南。今天我们特别邀请到中华职业教育社第十三届理事会常务理事、中华职业学校党总支副书记、校长黄玉璟,让她带我们解码先生精神的时代密码!
</GuideStepsItem> </GuideStepsItem>
</GuideSteps> </GuideSteps>
@@ -424,7 +430,10 @@ const HuangyanpeiInternalization = () => {
showMask={false} showMask={false}
zIndex={60} zIndex={60}
> >
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_30.mp3")}
>
听完黄校长的讲解,相信你对黄炎培先生的职教精神有了更深的理解。现在,就请你把这份感悟写下来,既总结参观的收获,也给自己未来许下一个承诺吧! 听完黄校长的讲解,相信你对黄炎培先生的职教精神有了更深的理解。现在,就请你把这份感悟写下来,既总结参观的收获,也给自己未来许下一个承诺吧!
</GuideStepsItem> </GuideStepsItem>
</GuideSteps> </GuideSteps>
+11 -4
View File
@@ -7,7 +7,7 @@ import {
StudyGuideModal, StudyGuideModal,
} from "@/components"; } from "@/components";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { getBackgroundImage, getStaticImage } from "@/lib/utils"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
import { useState } from "react"; import { useState } from "react";
import Cursor from "@/components/cursor"; import Cursor from "@/components/cursor";
@@ -119,6 +119,7 @@ const HuangyanpeiPlace1 = () => {
setShowGuideModal(false); setShowGuideModal(false);
setVisible(true); setVisible(true);
}} }}
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_01.mp3")}
> >
同学你好,欢迎来到“走进故居·对话”学习模块!{"\n"} 同学你好,欢迎来到“走进故居·对话”学习模块!{"\n"}
此刻你正站在黄炎培先生故居门前,接下来就跟着时光的脉络,拆解黄先生人生里五段滚烫的旅程:思想启蒙、教育实践、创立职教、延安对话、职教传薪。准备好一起走进这段炽热的岁月了吗? 此刻你正站在黄炎培先生故居门前,接下来就跟着时光的脉络,拆解黄先生人生里五段滚烫的旅程:思想启蒙、教育实践、创立职教、延安对话、职教传薪。准备好一起走进这段炽热的岁月了吗?
@@ -135,12 +136,17 @@ const HuangyanpeiPlace1 = () => {
} }
}} }}
showMask={false} showMask={false}
highlightSelectors={[]}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_03.mp3")}
>
小沪,这栋古色古香的江南大院,就是黄炎培先生从小生活、读书的地方吗 小沪,这栋古色古香的江南大院,就是黄炎培先生从小生活、读书的地方吗
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_04.mp3")}
>
没错,1878年10月1日,黄炎培先生就出生在当时江苏省川沙县城关镇(现上海市浦东新区川沙镇)的这处“内史第”,宅子原是他外祖父沈树镛家,也是他后来所说的“生于斯、读于斯、长于斯”之地。 没错,1878年10月1日,黄炎培先生就出生在当时江苏省川沙县城关镇(现上海市浦东新区川沙镇)的这处“内史第”,宅子原是他外祖父沈树镛家,也是他后来所说的“生于斯、读于斯、长于斯”之地。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
@@ -153,6 +159,7 @@ const HuangyanpeiPlace1 = () => {
visible={showAfterDialogGuide} visible={showAfterDialogGuide}
onContinue={() => setShowAfterDialogGuide(false)} onContinue={() => setShowAfterDialogGuide(false)}
ailgn="left" ailgn="left"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_02.mp3")}
> >
1.场景中出现动态光点的展品表示未浏览,可通过点击光点来了解展品背后的故事,通过滚轮可以放大展品,浏览展品后蓝色动态光点会变为已浏览状态。 1.场景中出现动态光点的展品表示未浏览,可通过点击光点来了解展品背后的故事,通过滚轮可以放大展品,浏览展品后蓝色动态光点会变为已浏览状态。
{"\n"} {"\n"}
+9 -3
View File
@@ -7,7 +7,7 @@ import {
GuideStepsItem, GuideStepsItem,
GuideSteps, GuideSteps,
} from "@/components"; } from "@/components";
import { getBackgroundImage, getStaticImage } from "@/lib/utils"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useCursorController } from "@/hooks/useCursorController"; import { useCursorController } from "@/hooks/useCursorController";
@@ -138,10 +138,16 @@ const HuangyanpeiPlace2 = () => {
highlightSelectors={[]} highlightSelectors={[]}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_05.mp3")}
>
哇,这就是南洋公学!是不是现在上海交通大学的前身呀?黄炎培先生中了秀才之后,就来这里读书了吗? 哇,这就是南洋公学!是不是现在上海交通大学的前身呀?黄炎培先生中了秀才之后,就来这里读书了吗?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_06.mp3")}
>
你说得特别对!1901年,黄炎培先生考入南洋公学(今上海交通大学)特班,当时的老师正是蔡元培先生。 你说得特别对!1901年,黄炎培先生考入南洋公学(今上海交通大学)特班,当时的老师正是蔡元培先生。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
+17 -6
View File
@@ -9,7 +9,7 @@ import {
SingleChoiceQuizPanel, SingleChoiceQuizPanel,
} from "@/components"; } from "@/components";
import { SuccessAlert } from "@/components/layout"; import { SuccessAlert } from "@/components/layout";
import { getBackgroundImage, getStaticImage } from "@/lib/utils"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useCursorController } from "@/hooks/useCursorController"; import { useCursorController } from "@/hooks/useCursorController";
@@ -186,10 +186,16 @@ const HuangyanpeiPlace3 = () => {
highlightSelectors={[]} highlightSelectors={[]}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_07.mp3")}
>
这所川沙小学堂就是黄炎培先生“教育救国”的第一个试验田吧?我们现在学习的课程有专业课、实习实训课都提倡技能培养,当年他是不是也很注重动手能力呀? 这所川沙小学堂就是黄炎培先生“教育救国”的第一个试验田吧?我们现在学习的课程有专业课、实习实训课都提倡技能培养,当年他是不是也很注重动手能力呀?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_08.mp3")}
>
太有共鸣啦!1903年,24岁的黄炎培先生和好友张志鹤等人一起,把原来的“观澜书院”改成了“川沙小学堂”,他自己当校长。 太有共鸣啦!1903年,24岁的黄炎培先生和好友张志鹤等人一起,把原来的“观澜书院”改成了“川沙小学堂”,他自己当校长。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
@@ -239,13 +245,18 @@ const HuangyanpeiPlace3 = () => {
visible={guide12Visible} visible={guide12Visible}
onVisibleChange={setGuide12Visible} onVisibleChange={setGuide12Visible}
showMask={true} showMask={true}
highlightSelectors={[]}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_09.mp3")}
>
原来当年还有专门的女子学校呀?在那个年代,女孩子能上学是不是特别不容易?后来的浦东中学也是黄炎培先生办的吗? 原来当年还有专门的女子学校呀?在那个年代,女孩子能上学是不是特别不容易?后来的浦东中学也是黄炎培先生办的吗?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_10.mp3")}
>
你观察得特别仔细!川沙小学堂开学没多久,黄炎培就和堂兄黄洪培、堂嫂陆开群一起,策划创建了“开群女学”——这所学校专门面向社会招收女学生,还用全力支持办学、腾出自家住房的陆开群名字命名。 你观察得特别仔细!川沙小学堂开学没多久,黄炎培就和堂兄黄洪培、堂嫂陆开群一起,策划创建了“开群女学”——这所学校专门面向社会招收女学生,还用全力支持办学、腾出自家住房的陆开群名字命名。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
+20 -5
View File
@@ -210,10 +210,16 @@ const HuangyanpeiPlace4 = () => {
showMask={false} showMask={false}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_13.mp3")}
>
真没想到中华职校还组织过义勇军!我们现在也会参加国防教育、志愿服务,当年的职业教育不仅教技能,还这么注重爱国主义教育呀? 真没想到中华职校还组织过义勇军!我们现在也会参加国防教育、志愿服务,当年的职业教育不仅教技能,还这么注重爱国主义教育呀?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_14.mp3")}
>
没错!黄炎培先生一直怀揣着“教育救国”的理想,职业教育从来都和国家命运紧紧连在一起。 没错!黄炎培先生一直怀揣着“教育救国”的理想,职业教育从来都和国家命运紧紧连在一起。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
@@ -241,10 +247,16 @@ const HuangyanpeiPlace4 = () => {
highlightSelectors={[]} highlightSelectors={[]}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_11.mp3")}
>
职业教育这个词是黄炎培先生创造的吗? 职业教育这个词是黄炎培先生创造的吗?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_12.mp3")}
>
这个词不是他创造的,但体系是他建立的。1917年5月6日,黄炎培联合蔡元培、张謇等48位有识之士,在上海成立了“中华职业教育社”,并发表了《中华职业教育社宣言》。 这个词不是他创造的,但体系是他建立的。1917年5月6日,黄炎培联合蔡元培、张謇等48位有识之士,在上海成立了“中华职业教育社”,并发表了《中华职业教育社宣言》。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
@@ -266,7 +278,10 @@ const HuangyanpeiPlace4 = () => {
showMask={false} showMask={false}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_15.mp3")}
>
这期间,1935年中华职业教育社还与荣氏三兄弟合作,再申新三厂办理劳动工自治区,对工人进行文化教育。 这期间,1935年中华职业教育社还与荣氏三兄弟合作,再申新三厂办理劳动工自治区,对工人进行文化教育。
</GuideStepsItem> </GuideStepsItem>
</GuideSteps> </GuideSteps>
+16 -4
View File
@@ -182,10 +182,16 @@ const HuangyanpeiPlace5 = () => {
showMask={false} showMask={false}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_16.mp3")}
>
抗战胜利后,黄炎培先生除了继续推进职业教育,还参与了政党活动呀?他创建民主政团同盟,是想为国家做些什么呢? 抗战胜利后,黄炎培先生除了继续推进职业教育,还参与了政党活动呀?他创建民主政团同盟,是想为国家做些什么呢?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_17.mp3")}
>
这和当时的历史背景分不开。1940年,国民党政府还坚持“攘外必先安内”的政策,让国共两党的关系越来越紧张。黄炎培等有识之士看到这种严峻形势,觉得中间派应该联合起来,为国家寻求一条和平发展的道路。 这和当时的历史背景分不开。1940年,国民党政府还坚持“攘外必先安内”的政策,让国共两党的关系越来越紧张。黄炎培等有识之士看到这种严峻形势,觉得中间派应该联合起来,为国家寻求一条和平发展的道路。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
@@ -215,10 +221,16 @@ const HuangyanpeiPlace5 = () => {
highlightSelectors={[]} highlightSelectors={[]}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_18.mp3")}
>
哇!这就是历史课上学的“窑洞对”!黄炎培先生和毛主席的这次谈话,是不是谈到了“历史周期率”呀? 哇!这就是历史课上学的“窑洞对”!黄炎培先生和毛主席的这次谈话,是不是谈到了“历史周期率”呀?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_19.mp3")}
>
完全正确!1945年7月1日,黄炎培以国民参政员的身份,带着考察团一行六人赴延安考察,中共中央领导人毛泽东、朱德、周恩来等都亲自到机场迎接。7月4日,他和毛泽东主席长谈了十几个小时,这场对话能和诸葛亮的“隆中对”相媲美。 完全正确!1945年7月1日,黄炎培以国民参政员的身份,带着考察团一行六人赴延安考察,中共中央领导人毛泽东、朱德、周恩来等都亲自到机场迎接。7月4日,他和毛泽东主席长谈了十几个小时,这场对话能和诸葛亮的“隆中对”相媲美。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
+11 -3
View File
@@ -7,7 +7,7 @@ import {
GuideSteps, GuideSteps,
GuideStepsItem, GuideStepsItem,
} from "@/components"; } from "@/components";
import { getBackgroundImage, getStaticImage } from "@/lib/utils"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { EndingOverlay } from "@/components/overlay/EndingOverlay"; import { EndingOverlay } from "@/components/overlay/EndingOverlay";
@@ -127,10 +127,16 @@ const HuangyanpeiPlace6 = () => {
highlightSelectors={[]} highlightSelectors={[]}
zIndex={10000} zIndex={10000}
> >
<GuideStepsItem speaker="student"> <GuideStepsItem
speaker="student"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_20.mp3")}
>
新中国成立后,黄炎培先生还继续从事教育工作吗?我们现在的中职教育体系,是不是也有他当年的理念呀? 新中国成立后,黄炎培先生还继续从事教育工作吗?我们现在的中职教育体系,是不是也有他当年的理念呀?
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem
speaker="guide"
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_21.mp3")}
>
当然啦!1949年10月19日,71岁的黄炎培出任政务院副总理兼轻工业部部长,依然没有放下他毕生追求的职业教育事业。他把中华职教社的骨干力量全部调到北京,亲自起草《关于改革学制的决定》。 当然啦!1949年10月19日,71岁的黄炎培出任政务院副总理兼轻工业部部长,依然没有放下他毕生追求的职业教育事业。他把中华职教社的骨干力量全部调到北京,亲自起草《关于改革学制的决定》。
</GuideStepsItem> </GuideStepsItem>
<GuideStepsItem speaker="guide"> <GuideStepsItem speaker="guide">
@@ -151,6 +157,8 @@ const HuangyanpeiPlace6 = () => {
setHasShownEnding(true); setHasShownEnding(true);
setLeave(true); setLeave(true);
}} }}
animationSpeed={200}
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_22.mp3")}
/> />
</div> </div>
); );
+2 -1
View File
@@ -2,7 +2,7 @@ import { useState, useCallback, useEffect } from "react";
import { Title, Image, Cursor, StudyGuideModal } from "@/components"; import { Title, Image, Cursor, StudyGuideModal } from "@/components";
import { BambooPuzzleGame, QuestionModal } from "./components"; import { BambooPuzzleGame, QuestionModal } from "./components";
import { SuccessAlert } from "@/components/layout"; import { SuccessAlert } from "@/components/layout";
import { getBackgroundImage, getStaticImage } from "@/lib/utils"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
const starName = "huangyanpei"; const starName = "huangyanpei";
@@ -76,6 +76,7 @@ const HuangyanpeiReflectionScene1 = () => {
onContinue={() => { onContinue={() => {
setShowGuideModal(false); setShowGuideModal(false);
}} }}
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_23.mp3")}
> >
同学你好,欢迎来到“跨越时空·体悟”学习模块!{"\n"} 同学你好,欢迎来到“跨越时空·体悟”学习模块!{"\n"}
请登陆“时空回溯・亲历时代”体验仓,下一站:1903,川沙小学堂。{"\n"} 请登陆“时空回溯・亲历时代”体验仓,下一站:1903,川沙小学堂。{"\n"}
+2 -1
View File
@@ -1,6 +1,6 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Title, Image, Cursor, StudyGuideModal } from "@/components"; import { Title, Image, Cursor, StudyGuideModal } from "@/components";
import { getBackgroundImage, getStaticImage } from "@/lib/utils"; import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import ChoiceDialog1 from "./scene2/ChoiceDialog1"; import ChoiceDialog1 from "./scene2/ChoiceDialog1";
import ChoiceDialog2 from "./scene2/ChoiceDialog2"; import ChoiceDialog2 from "./scene2/ChoiceDialog2";
@@ -88,6 +88,7 @@ const HuangyanpeiReflectionScene2 = () => {
<StudyGuideModal <StudyGuideModal
visible={showGuideModal} visible={showGuideModal}
onContinue={() => setShowGuideModal(false)} onContinue={() => setShowGuideModal(false)}
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_24.mp3")}
> >
欢迎来到浦东中学!{"\n"} 欢迎来到浦东中学!{"\n"}
这是近代上海第一所完全中学,黄炎培先生当首任校长,在这里能学到更多实用知识,还能树立成才的理想哦。 这是近代上海第一所完全中学,黄炎培先生当首任校长,在这里能学到更多实用知识,还能树立成才的理想哦。
+15 -1
View File
@@ -24,6 +24,7 @@ const HuangyanpeiReflectionScene3 = () => {
const [showQuiz, setShowQuiz] = useState(false); const [showQuiz, setShowQuiz] = useState(false);
const [showSuccessAlert, setShowSuccessAlert] = useState(false); const [showSuccessAlert, setShowSuccessAlert] = useState(false);
const [showErrorAlert, setShowErrorAlert] = useState(false); const [showErrorAlert, setShowErrorAlert] = useState(false);
const [showErrorAlertForQuiz, setShowErrorAlertForQuiz] = useState(false);
const [showCompleteGuide, setShowCompleteGuide] = useState(false); const [showCompleteGuide, setShowCompleteGuide] = useState(false);
const [showVideo, setShowVideo] = useState(false); const [showVideo, setShowVideo] = useState(false);
const [visited, setVisited] = useState<Set<number>>(new Set()); const [visited, setVisited] = useState<Set<number>>(new Set());
@@ -73,7 +74,12 @@ const HuangyanpeiReflectionScene3 = () => {
src={getStaticImage("huangyanpei/reflection/components/喇叭1")} src={getStaticImage("huangyanpei/reflection/components/喇叭1")}
button button
onClick={() => { onClick={() => {
setShowQuizDialog(true); // 检查是否完成前两个任务(visited.has(1) && visited.has(2))
if (visited.has(1) && visited.has(2)) {
setShowQuizDialog(true);
} else {
setShowErrorAlertForQuiz(true);
}
}} }}
/> />
@@ -83,6 +89,7 @@ const HuangyanpeiReflectionScene3 = () => {
onContinue={() => { onContinue={() => {
setShowGuide1(false); setShowGuide1(false);
}} }}
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_25.mp3")}
> >
终于到中华职业学校啦!这里是中国近代职教的摇篮,"免学费、包分配",还能学真手艺,快来练就一技之长。 终于到中华职业学校啦!这里是中国近代职教的摇篮,"免学费、包分配",还能学真手艺,快来练就一技之长。
{"\n"} {"\n"}
@@ -180,6 +187,13 @@ const HuangyanpeiReflectionScene3 = () => {
onClose={() => setShowErrorAlert(false)} onClose={() => setShowErrorAlert(false)}
/> />
{/* 错误提示:请先完成前两个任务 */}
<ErrorAlert
visible={showErrorAlertForQuiz}
text="请先完成前两个任务吧!"
onClose={() => setShowErrorAlertForQuiz(false)}
/>
{/* 组装台钳完成提示 */} {/* 组装台钳完成提示 */}
<StudyGuideModal <StudyGuideModal
visible={showCompleteGuide} visible={showCompleteGuide}
+16 -2
View File
@@ -1,7 +1,7 @@
import { useState, useCallback, useRef } from "react"; import { useState, useCallback, useRef } from "react";
import { Title, Image, Cursor, Video, StudyGuideModal } from "@/components"; import { Title, Image, Cursor, Video, StudyGuideModal } from "@/components";
import { MultipleChoiceQuizPanel } from "@/components/layout/quiz"; import { MultipleChoiceQuizPanel } from "@/components/layout/quiz";
import { SuccessAlert } from "@/components/layout"; import { SuccessAlert, ErrorAlert } from "@/components/layout";
import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils"; import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import TowelSalesDialog from "./scene4/TowelSalesDialog"; import TowelSalesDialog from "./scene4/TowelSalesDialog";
@@ -24,6 +24,7 @@ const HuangyanpeiReflectionScene4 = () => {
const [showVideo, setShowVideo] = useState(false); const [showVideo, setShowVideo] = useState(false);
const videoRef = useRef<VideoRef>(null); const videoRef = useRef<VideoRef>(null);
const [showGuide1, setShowGuide1] = useState(true); const [showGuide1, setShowGuide1] = useState(true);
const [showErrorAlertForQuiz, setShowErrorAlertForQuiz] = useState(false);
//喇叭考题弹窗 //喇叭考题弹窗
const [showQuizDialog, setShowQuizDialog] = useState(false); const [showQuizDialog, setShowQuizDialog] = useState(false);
@@ -84,7 +85,12 @@ const HuangyanpeiReflectionScene4 = () => {
src={getStaticImage("huangyanpei/reflection/components/喇叭2")} src={getStaticImage("huangyanpei/reflection/components/喇叭2")}
button button
onClick={() => { onClick={() => {
setShowQuizDialog(true); // 检查是否完成前两个任务(visited.has(1) && visited.has(2))
if (visited.has(1) && visited.has(2)) {
setShowQuizDialog(true);
} else {
setShowErrorAlertForQuiz(true);
}
}} }}
/> />
@@ -185,6 +191,7 @@ const HuangyanpeiReflectionScene4 = () => {
onContinue={() => { onContinue={() => {
setShowGuide1(false); setShowGuide1(false);
}} }}
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_26.mp3")}
> >
终于到中华职业学校啦!这里是中国近代职教的摇篮,“免学费、包分配”,还能学真手艺,快来练就一技之长。 终于到中华职业学校啦!这里是中国近代职教的摇篮,“免学费、包分配”,还能学真手艺,快来练就一技之长。
{"\n"} {"\n"}
@@ -214,6 +221,13 @@ const HuangyanpeiReflectionScene4 = () => {
setVisited((prev) => new Set(prev).add(3)); setVisited((prev) => new Set(prev).add(3));
}} }}
/> />
{/* 错误提示:请先完成前两个任务 */}
<ErrorAlert
visible={showErrorAlertForQuiz}
text="请先完成前两个任务吧!"
onClose={() => setShowErrorAlertForQuiz(false)}
/>
</div> </div>
); );
}; };