- 在多个场景中引入音频文件,增强互动性和沉浸感。 - 更新引导对话文本,确保信息准确性和一致性。 - 调整组件结构,清理冗余代码,提升可维护性。 - 引入结束窗口,鼓励用户深入了解黄炎培的教育理念。
245 lines
7.6 KiB
TypeScript
245 lines
7.6 KiB
TypeScript
import { useState, useRef } from "react";
|
||
import { Title, Image, Cursor, StudyGuideModal, Video } from "@/components";
|
||
import { MultipleChoiceQuizPanel } from "@/components/layout/quiz";
|
||
import { SuccessAlert, ErrorAlert } from "@/components/layout";
|
||
import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils";
|
||
import { useNavigate, useParams } from "react-router-dom";
|
||
import ViseAssemblyDialog from "./scene3/ViseAssemblyDialog";
|
||
import type { VideoRef } from "@/components/video";
|
||
import { QuizDialog } from "./components";
|
||
|
||
const starName = "huangyanpei";
|
||
|
||
const HuangyanpeiReflectionScene3 = () => {
|
||
const navigate = useNavigate();
|
||
const { moduleName } = useParams<{
|
||
moduleName: string;
|
||
}>();
|
||
|
||
//喇叭考题弹窗
|
||
const [showQuizDialog, setShowQuizDialog] = useState(false);
|
||
|
||
const [showGuide1, setShowGuide1] = useState(true);
|
||
const [showDialog, setShowDialog] = useState(false);
|
||
const [showQuiz, setShowQuiz] = useState(false);
|
||
const [showSuccessAlert, setShowSuccessAlert] = useState(false);
|
||
const [showErrorAlert, setShowErrorAlert] = useState(false);
|
||
const [showErrorAlertForQuiz, setShowErrorAlertForQuiz] = useState(false);
|
||
const [showCompleteGuide, setShowCompleteGuide] = useState(false);
|
||
const [showVideo, setShowVideo] = useState(false);
|
||
const [visited, setVisited] = useState<Set<number>>(new Set());
|
||
const videoRef = useRef<VideoRef>(null);
|
||
|
||
if (!moduleName) {
|
||
return null;
|
||
}
|
||
|
||
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(
|
||
`huangyanpei/reflection/scene3/11_001`
|
||
),
|
||
}}
|
||
>
|
||
<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={() => {
|
||
navigate(`/${moduleName}/${starName}/reflection2`);
|
||
}}
|
||
/>
|
||
|
||
<Image
|
||
className="absolute left-5 top-5"
|
||
src={getStaticImage("huangyanpei/reflection/components/喇叭1")}
|
||
button
|
||
onClick={() => {
|
||
// 检查是否完成前两个任务(visited.has(1) && visited.has(2))
|
||
if (visited.has(1) && visited.has(2)) {
|
||
setShowQuizDialog(true);
|
||
} else {
|
||
setShowErrorAlertForQuiz(true);
|
||
}
|
||
}}
|
||
/>
|
||
|
||
{/* 第一段引导 */}
|
||
<StudyGuideModal
|
||
visible={showGuide1}
|
||
onContinue={() => {
|
||
setShowGuide1(false);
|
||
}}
|
||
audioSrc={getPublicPath("audio/huangyanpei/mp3_huangyanpei_25.mp3")}
|
||
>
|
||
终于到中华职业学校啦!这里是中国近代职教的摇篮,"免学费、包分配",还能学真手艺,快来练就一技之长。
|
||
{"\n"}
|
||
你选了学技术,那就来挑战制作中华职校的"明星产品"——台钳吧!当年这台钳还拿过巴拿马万国博览会金奖呢!
|
||
</StudyGuideModal>
|
||
|
||
{/* 互动展品光标:组装台钳互动 */}
|
||
<Cursor
|
||
className="absolute right-100 bottom-55"
|
||
onClick={() => {
|
||
if (!showGuide1) {
|
||
if (visited.has(2)) {
|
||
setShowDialog(true);
|
||
} else {
|
||
setShowErrorAlert(true);
|
||
}
|
||
}
|
||
}}
|
||
read={visited.has(1)}
|
||
/>
|
||
|
||
{/* 答题光标 */}
|
||
<Cursor
|
||
className="absolute left-145 top-68"
|
||
onClick={() => {
|
||
if (!showGuide1) {
|
||
setShowQuiz(true);
|
||
}
|
||
}}
|
||
read={visited.has(2)}
|
||
/>
|
||
|
||
{/* 组装台钳互动弹窗 */}
|
||
<ViseAssemblyDialog
|
||
visible={showDialog}
|
||
onClose={() => setShowDialog(false)}
|
||
onComplete={() => {
|
||
setShowDialog(false);
|
||
setShowCompleteGuide(true);
|
||
setVisited((prev) => {
|
||
const next = new Set(prev);
|
||
next.add(1);
|
||
return next;
|
||
});
|
||
}}
|
||
/>
|
||
|
||
{/* 多选题答题框 */}
|
||
<MultipleChoiceQuizPanel
|
||
visible={showQuiz}
|
||
title="【多选】 制作台钳需要哪些工具?"
|
||
options={[
|
||
{ value: "A", label: "A. 锯子" },
|
||
{ value: "B", label: "B. 毛笔" },
|
||
{ value: "C", label: "C. 锉刀" },
|
||
{ value: "D", label: "D. 铁锤" },
|
||
]}
|
||
correctAnswer={["A", "C", "D"]}
|
||
errorMessage={(selectedValues) => {
|
||
// 如果选择了B,显示包含"毛笔是写字的哦"的提示
|
||
if (selectedValues.includes("B")) {
|
||
return "毛笔是写字的哦!台钳是铁制品,得用锯子、锉刀、铁锤这些工具,再选一次吧!";
|
||
}
|
||
// 其他情况(单选A或C或D,或者AC、CD、AD等组合)
|
||
return "台钳是铁制品,得用锯子、锉刀、铁锤这些工具,再选一次吧!";
|
||
}}
|
||
minSelections={1}
|
||
onSubmit={(values, isCorrect) => {
|
||
if (isCorrect) {
|
||
setShowQuiz(false);
|
||
setShowSuccessAlert(true);
|
||
}
|
||
}}
|
||
zIndex={10001}
|
||
/>
|
||
|
||
{/* 成功提示弹窗 */}
|
||
<SuccessAlert
|
||
visible={showSuccessAlert}
|
||
title="满分!"
|
||
content='黄先生说"手脑并用",懂了理论,也要动手实践。'
|
||
onContinue={() => {
|
||
setShowSuccessAlert(false);
|
||
setVisited((prev) => new Set(prev).add(2));
|
||
}}
|
||
onClose={() => {
|
||
setShowSuccessAlert(false);
|
||
}}
|
||
/>
|
||
|
||
{/* 错误提示:请先去学习制作台钳 */}
|
||
<ErrorAlert
|
||
visible={showErrorAlert}
|
||
text="请先去学习台钳制作知识吧!"
|
||
onClose={() => setShowErrorAlert(false)}
|
||
/>
|
||
|
||
{/* 错误提示:请先完成前两个任务 */}
|
||
<ErrorAlert
|
||
visible={showErrorAlertForQuiz}
|
||
text="请先完成前两个任务吧!"
|
||
onClose={() => setShowErrorAlertForQuiz(false)}
|
||
/>
|
||
|
||
{/* 组装台钳完成提示 */}
|
||
<StudyGuideModal
|
||
visible={showCompleteGuide}
|
||
onContinue={() => setShowCompleteGuide(false)}
|
||
verticalAlign="center"
|
||
>
|
||
太厉害啦!你的台钳制作成功,和当年拿金奖的同款哦。
|
||
</StudyGuideModal>
|
||
|
||
{completed && (
|
||
<Image
|
||
className="absolute bottom-0 right-4"
|
||
src={getStaticImage("components/place/继续前进")}
|
||
button
|
||
onClick={() => {
|
||
setShowVideo(true);
|
||
}}
|
||
/>
|
||
)}
|
||
|
||
{showVideo && (
|
||
<Video
|
||
ref={videoRef}
|
||
src={getPublicPath("video/huangyanpei/huangyanpei_09.mp4")}
|
||
className="h-full w-full"
|
||
autoPlay
|
||
playsInline
|
||
showSkipButton
|
||
onEnded={() => {
|
||
setShowVideo(false);
|
||
navigate(`/${moduleName}/${starName}/home`);
|
||
}}
|
||
/>
|
||
)}
|
||
|
||
<QuizDialog
|
||
visible={showQuizDialog}
|
||
onClose={() => setShowQuizDialog(false)}
|
||
onComplete={() => {
|
||
setShowQuizDialog(false);
|
||
setVisited((prev) => new Set(prev).add(3));
|
||
}}
|
||
/>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default HuangyanpeiReflectionScene3;
|