feat: 添加连线题和选择题功能,增强互动性
- 在多个组件中引入 MatchQuizPanel 和 SingleChoiceQuizPanel,提升用户参与度。 - 更新 HuangyanpeiPlace1、HuangyanpeiPlace3、LuxunPlace1、LuxunPlace2 组件,增加新的选择题和连线题,丰富学习内容。 - 调整成功提示逻辑,确保用户体验流畅。 - 优化视频播放中的锚点逻辑,提升互动性和学习效果。
This commit is contained in:
1 parent
02a3f00a9b
commit
966b47ede3
12 files changed
+1128
-42
No files matched your search
@@ -7,10 +7,12 @@ import {
|
||||
Cursor,
|
||||
SingleChoiceQuizPanel,
|
||||
Video,
|
||||
type VideoAnchor,
|
||||
} from "@/components";
|
||||
import type { VideoRef } from "@/components/video";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
|
||||
import { useState } from "react";
|
||||
import { useState, useRef, useMemo } from "react";
|
||||
import SuccessAlert from "@/components/layout/alert/success-alert";
|
||||
import { useCursorController } from "@/hooks/useCursorController";
|
||||
import { usePuzzleAnimation } from "@/contexts/PuzzleAnimationContext";
|
||||
@@ -27,10 +29,14 @@ const exhibitSrcMap: Record<1 | 2 | 3, string> = {
|
||||
|
||||
const quizDefaultError = "请结合刚刚的旁白内容,再思考一下吧!";
|
||||
const quizExplanations: Record<string, string> = {
|
||||
A: "陈独秀与鲁迅有思想交往,但他并未在这间“红色庇护所”中避难、与鲁迅夜谈革命议题。",
|
||||
B: "恭喜你,选对啦。",
|
||||
C: "李大钊于1927年牺牲,时间上不符合这间客房被用作“红色庇护所”的背景。",
|
||||
D: "周恩来虽长期在上海从事革命活动,但并未在这里避难并与鲁迅夜谈。",
|
||||
// A: "陈独秀与鲁迅有思想交往,但他并未在这间“红色庇护所”中避难、与鲁迅夜谈革命议题。",
|
||||
// B: "恭喜你,选对啦。",
|
||||
// C: "李大钊于1927年牺牲,时间上不符合这间客房被用作“红色庇护所”的背景。",
|
||||
// D: "周恩来虽长期在上海从事革命活动,但并未在这里避难并与鲁迅夜谈。",
|
||||
A: "请你结合刚刚学习的内容,再思考一下吧!",
|
||||
B: "恭喜你,选择正确!",
|
||||
C: "请你结合刚刚学习的内容,再思考一下吧!",
|
||||
D: "请你结合刚刚学习的内容,再思考一下吧!",
|
||||
};
|
||||
|
||||
const LuxunPlace5 = () => {
|
||||
@@ -72,6 +78,10 @@ const LuxunPlace5 = () => {
|
||||
// 结尾视频与对话
|
||||
const [showEndingVideo, setShowEndingVideo] = useState(false);
|
||||
const [endingGuideVisible, setEndingGuideVisible] = useState(false);
|
||||
// 视频锚点相关状态
|
||||
const [activeVideoSuccess, setActiveVideoSuccess] = useState(false);
|
||||
const [resumeVideoCallback, setResumeVideoCallback] = useState<(() => void) | null>(null);
|
||||
const videoRef = useRef<VideoRef>(null);
|
||||
|
||||
const handleOpenExhibit = (index: 1 | 2 | 3) => {
|
||||
if (index === 3) {
|
||||
@@ -83,6 +93,66 @@ const LuxunPlace5 = () => {
|
||||
setActiveExhibitId(index);
|
||||
};
|
||||
|
||||
// 视频锚点配置
|
||||
const videoAnchors: VideoAnchor[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: "quiz-anchor",
|
||||
time: 5,
|
||||
once: true,
|
||||
afterResume: "remove",
|
||||
render: ({ resume }) => (
|
||||
<>
|
||||
<SingleChoiceQuizPanel
|
||||
visible={!activeVideoSuccess}
|
||||
title='【单选】毛泽东主席称赞鲁迅先生为"最伟大和最英勇的___"。'
|
||||
options={[
|
||||
{ value: "A", label: "A. 旗手" },
|
||||
{ value: "B", label: "B. 作家" },
|
||||
{ value: "C", label: "C. 战士" },
|
||||
]}
|
||||
correctAnswer="A"
|
||||
onWrongSelect={(value: string) => {
|
||||
switch (value) {
|
||||
case "B":
|
||||
return "这不是毛泽东主席的原话。请你再想想吧!";
|
||||
case "C":
|
||||
return "这不是毛泽东主席的原话。请你再想想吧!";
|
||||
default:
|
||||
return "请你再想想吧!";
|
||||
}
|
||||
}}
|
||||
onSubmit={(value: string, isCorrect: boolean) => {
|
||||
if (isCorrect) {
|
||||
setActiveVideoSuccess(true);
|
||||
setResumeVideoCallback(() => resume);
|
||||
}
|
||||
}}
|
||||
zIndex={20000}
|
||||
/>
|
||||
|
||||
<SuccessAlert
|
||||
visible={activeVideoSuccess}
|
||||
onContinue={() => {
|
||||
setActiveVideoSuccess(false);
|
||||
const cb = resumeVideoCallback;
|
||||
setResumeVideoCallback(null);
|
||||
cb?.();
|
||||
}}
|
||||
onClose={() => {
|
||||
setActiveVideoSuccess(false);
|
||||
const cb = resumeVideoCallback;
|
||||
setResumeVideoCallback(null);
|
||||
cb?.();
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
[activeVideoSuccess, resumeVideoCallback]
|
||||
);
|
||||
|
||||
const progressCount = visited.size;
|
||||
const total = 3;
|
||||
const completed = progressCount >= total;
|
||||
@@ -304,11 +374,14 @@ const LuxunPlace5 = () => {
|
||||
{/* 结尾视频播放 */}
|
||||
{showEndingVideo && (
|
||||
<Video
|
||||
ref={videoRef}
|
||||
src={getPublicPath("video/luxun/luxun_06.mp4")}
|
||||
className="fixed inset-0 z-[20000]"
|
||||
controls
|
||||
autoPlay
|
||||
playsInline
|
||||
showSkipButton
|
||||
anchors={videoAnchors}
|
||||
onEnded={() => {
|
||||
setEndingGuideVisible(true);
|
||||
}}
|
||||
|
||||
Reference in new issue
Block a user