feat: 更新 ESLint 和 Prettier 配置,增强代码质量管理
- 在 .gitignore 中添加 public/audio/* 以忽略音频文件。 - 更新 bun.lock,添加 eslint-config-prettier 和 eslint-plugin-prettier 依赖,确保 ESLint 与 Prettier 的兼容性。 - 修改 eslint.config.ts,整合 Prettier 规则,优化代码风格一致性。 - 在 package.json 中添加 lint:fix 和 format 脚本,简化代码格式化和修复流程。 - 更新 tailwind.config.ts 和其他组件文件,统一代码风格,提升可读性。
This commit is contained in:
1 parent
5d00adc1a5
commit
76c67b492e
216 files changed
+12454
-13976
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useState, useRef } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useEffect, useMemo, useState, useRef } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import {
|
||||
Image,
|
||||
Video,
|
||||
@@ -8,231 +8,221 @@ import {
|
||||
type DragFillResult,
|
||||
LetterToChenyun,
|
||||
EndingOverlay,
|
||||
} from "@/components";
|
||||
import { getBackgroundImage, getPublicPath, getStaticImage } from "@/lib/utils";
|
||||
import { SuccessAlert, DragQuizPanel } from "@/components/layout";
|
||||
import { MultipleChoiceQuizPanel } from "@/components/layout/quiz";
|
||||
import { GuideSteps, GuideStepsItem } from "@/components";
|
||||
import { usePuzzleAnimation } from "@/contexts/PuzzleAnimationContext";
|
||||
} from '@/components'
|
||||
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
|
||||
import { SuccessAlert, DragQuizPanel } from '@/components/layout'
|
||||
import { MultipleChoiceQuizPanel } from '@/components/layout/quiz'
|
||||
import { GuideSteps, GuideStepsItem } from '@/components'
|
||||
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
|
||||
type QuizOption = {
|
||||
value: string;
|
||||
label: string;
|
||||
isCorrect?: boolean;
|
||||
explanation?: string; // 错误选项的解释
|
||||
};
|
||||
value: string
|
||||
label: string
|
||||
isCorrect?: boolean
|
||||
explanation?: string // 错误选项的解释
|
||||
}
|
||||
|
||||
type QuizAnchor = {
|
||||
id: string;
|
||||
time: number;
|
||||
title: string;
|
||||
prompt: string;
|
||||
type: "single" | "multiple" | "drag";
|
||||
options: QuizOption[];
|
||||
id: string
|
||||
time: number
|
||||
title: string
|
||||
prompt: string
|
||||
type: 'single' | 'multiple' | 'drag'
|
||||
options: QuizOption[]
|
||||
// 拖拽题专用
|
||||
blanks?: { id: string; label: string }[];
|
||||
explanation?: string;
|
||||
};
|
||||
blanks?: { id: string; label: string }[]
|
||||
explanation?: string
|
||||
}
|
||||
|
||||
// 星名固定为 chenyun
|
||||
const starName = "chenyun";
|
||||
const starName = 'chenyun'
|
||||
|
||||
// 通用提示文案
|
||||
const MULTIPLE_DEFAULT_ERROR =
|
||||
"你的选择还不够全面哦~请你再想想吧!";
|
||||
const MULTIPLE_DEFAULT_ERROR = '你的选择还不够全面哦~请你再想想吧!'
|
||||
|
||||
// 锚点数据:可根据实际视频时长调整 time
|
||||
const QUIZ_ANCHORS: QuizAnchor[] = [
|
||||
{
|
||||
id: "quiz-1",
|
||||
id: 'quiz-1',
|
||||
time: 60 * 5 + 52, //5.52分钟
|
||||
title: "题目1",
|
||||
prompt: "陈云经济思想的核心内容指的是(\xa0\xa0\xa0\xa0)。",
|
||||
type: "multiple",
|
||||
title: '题目1',
|
||||
prompt: '陈云经济思想的核心内容指的是(\xa0\xa0\xa0\xa0)。',
|
||||
type: 'multiple',
|
||||
options: [
|
||||
{ value: "A", label: "综合平衡", isCorrect: true },
|
||||
{ value: 'A', label: '综合平衡', isCorrect: true },
|
||||
{
|
||||
value: "B",
|
||||
label: "鸟笼比喻",
|
||||
value: 'B',
|
||||
label: '鸟笼比喻',
|
||||
},
|
||||
{ value: "C", label: "正确的处理好计划与市场的关系", isCorrect: true },
|
||||
{ value: "D", label: "经济建设的目的论", isCorrect: true },
|
||||
{ value: 'C', label: '正确的处理好计划与市场的关系', isCorrect: true },
|
||||
{ value: 'D', label: '经济建设的目的论', isCorrect: true },
|
||||
],
|
||||
explanation: "鸟笼比喻是陈云提出的一个比喻。请你再想想吧!",
|
||||
explanation: '鸟笼比喻是陈云提出的一个比喻。请你再想想吧!',
|
||||
},
|
||||
{
|
||||
id: "quiz-2",
|
||||
id: 'quiz-2',
|
||||
time: 60 * 10 + 1, //10.01分钟
|
||||
title: "题目2",
|
||||
prompt: "陈云说过以下哪些话能着重体现出他的经济思想?",
|
||||
type: "multiple",
|
||||
title: '题目2',
|
||||
prompt: '陈云说过以下哪些话能着重体现出他的经济思想?',
|
||||
type: 'multiple',
|
||||
options: [
|
||||
{
|
||||
value: "A",
|
||||
label: "不唯上、不唯书、只唯实,交换、比较、反复",
|
||||
value: 'A',
|
||||
label: '不唯上、不唯书、只唯实,交换、比较、反复',
|
||||
isCorrect: true,
|
||||
},
|
||||
{ value: "B", label: "无农不稳,无粮则乱", isCorrect: true },
|
||||
{ value: "C", label: "个人名利淡如水,党的事业重如山", isCorrect: true },
|
||||
{ value: 'B', label: '无农不稳,无粮则乱', isCorrect: true },
|
||||
{ value: 'C', label: '个人名利淡如水,党的事业重如山', isCorrect: true },
|
||||
{
|
||||
value: "D",
|
||||
label: "领导机关制定政策,要用百分之九十以上的时间作调查研究工作",
|
||||
value: 'D',
|
||||
label: '领导机关制定政策,要用百分之九十以上的时间作调查研究工作',
|
||||
isCorrect: true,
|
||||
},
|
||||
],
|
||||
explanation: "你的选择还不够全面哦~请你再想想吧!",
|
||||
explanation: '你的选择还不够全面哦~请你再想想吧!',
|
||||
},
|
||||
{
|
||||
id: "quiz-3",
|
||||
id: 'quiz-3',
|
||||
time: 16 * 60 + 26, //16:26
|
||||
title: "题目3",
|
||||
prompt: "新时代的青年可以从陈云身上学习到",
|
||||
type: "drag",
|
||||
title: '题目3',
|
||||
prompt: '新时代的青年可以从陈云身上学习到',
|
||||
type: 'drag',
|
||||
options: [
|
||||
{ value: "积极的人生态度", label: "A.积极的人生态度", isCorrect: true },
|
||||
{ value: "刻苦的学习精神", label: "B.刻苦的学习精神", isCorrect: true },
|
||||
{ value: "朴素的节俭精神", label: "C.朴素的节俭精神", isCorrect: true },
|
||||
{ value: "只唯上的工作作风", label: "D.只唯上的工作作风" },
|
||||
{ value: '积极的人生态度', label: 'A.积极的人生态度', isCorrect: true },
|
||||
{ value: '刻苦的学习精神', label: 'B.刻苦的学习精神', isCorrect: true },
|
||||
{ value: '朴素的节俭精神', label: 'C.朴素的节俭精神', isCorrect: true },
|
||||
{ value: '只唯上的工作作风', label: 'D.只唯上的工作作风' },
|
||||
],
|
||||
blanks: [
|
||||
{ id: "blank-1", label: "____" },
|
||||
{ id: "blank-2", label: "____" },
|
||||
{ id: "blank-3", label: "____" },
|
||||
{ id: 'blank-1', label: '____' },
|
||||
{ id: 'blank-2', label: '____' },
|
||||
{ id: 'blank-3', label: '____' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "quiz-4",
|
||||
id: 'quiz-4',
|
||||
time: 60 * 5 + 21, // 5:21
|
||||
title: "题目4",
|
||||
prompt: "以下哪些陈云的生活小事值得我们学习?",
|
||||
type: "multiple",
|
||||
title: '题目4',
|
||||
prompt: '以下哪些陈云的生活小事值得我们学习?',
|
||||
type: 'multiple',
|
||||
options: [
|
||||
{ value: "A", label: "光盘行动,不浪费粮食", isCorrect: true },
|
||||
{ value: "B", label: "打了 32 个补丁的棉坎肩他穿了 38 年", isCorrect: true },
|
||||
{ value: "C", label: "2-3 厘米长的铅笔头仍然留用", isCorrect: true },
|
||||
{ value: "D", label: "搓肥皂时关闭水龙头,节约用水", isCorrect: true },
|
||||
{ value: 'A', label: '光盘行动,不浪费粮食', isCorrect: true },
|
||||
{ value: 'B', label: '打了 32 个补丁的棉坎肩他穿了 38 年', isCorrect: true },
|
||||
{ value: 'C', label: '2-3 厘米长的铅笔头仍然留用', isCorrect: true },
|
||||
{ value: 'D', label: '搓肥皂时关闭水龙头,节约用水', isCorrect: true },
|
||||
],
|
||||
explanation: MULTIPLE_DEFAULT_ERROR,
|
||||
},
|
||||
{
|
||||
id: "quiz-5",
|
||||
id: 'quiz-5',
|
||||
time: 60 * 16 + 23, // 16:23
|
||||
title: "题目5",
|
||||
prompt: "新时代的青年要从陈云身上学习哪些精神品质?",
|
||||
type: "multiple",
|
||||
title: '题目5',
|
||||
prompt: '新时代的青年要从陈云身上学习哪些精神品质?',
|
||||
type: 'multiple',
|
||||
options: [
|
||||
{ value: "A", label: "谦虚谨慎,实事求是的工作作风", isCorrect: true },
|
||||
{ value: "B", label: "勤俭朴素,艰苦奋斗的优良作风", isCorrect: true },
|
||||
{ value: "C", label: "密切联系群众,关心群众生活", isCorrect: true },
|
||||
{ value: 'A', label: '谦虚谨慎,实事求是的工作作风', isCorrect: true },
|
||||
{ value: 'B', label: '勤俭朴素,艰苦奋斗的优良作风', isCorrect: true },
|
||||
{ value: 'C', label: '密切联系群众,关心群众生活', isCorrect: true },
|
||||
{
|
||||
value: "D",
|
||||
label: "只唯上的工作作风",
|
||||
value: 'D',
|
||||
label: '只唯上的工作作风',
|
||||
isCorrect: false,
|
||||
explanation: "\"只唯上\"的工作作风与陈云同志实事求是的精神相悖。请你再想想吧!",
|
||||
explanation: '"只唯上"的工作作风与陈云同志实事求是的精神相悖。请你再想想吧!',
|
||||
},
|
||||
],
|
||||
explanation: MULTIPLE_DEFAULT_ERROR,
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
const ChenyunInternalization = () => {
|
||||
const navigate = useNavigate();
|
||||
const { moduleName } = useParams<{ moduleName: string }>();
|
||||
const navigate = useNavigate()
|
||||
const { moduleName } = useParams<{ moduleName: string }>()
|
||||
// 获取碎片动画触发方法
|
||||
const { triggerPuzzleAnimation } = usePuzzleAnimation();
|
||||
const [activeSuccess, setActiveSuccess] = useState<string | null>(null);
|
||||
const [resumeCallback, setResumeCallback] = useState<(() => void) | null>(
|
||||
null
|
||||
);
|
||||
const { triggerPuzzleAnimation } = usePuzzleAnimation()
|
||||
const [activeSuccess, setActiveSuccess] = useState<string | null>(null)
|
||||
const [resumeCallback, setResumeCallback] = useState<(() => void) | null>(null)
|
||||
// 拖拽题状态
|
||||
const [dragQuizValues, setDragQuizValues] = useState<
|
||||
Record<string, DragFillResult[]>
|
||||
>({});
|
||||
const [dragQuizErrors, setDragQuizErrors] = useState<Record<string, string>>(
|
||||
{}
|
||||
);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
const [postGuideVisible, setPostGuideVisible] = useState(false);
|
||||
const [showLetter, setShowLetter] = useState(false);
|
||||
const [showLetterVideo, setShowLetterVideo] = useState(false);
|
||||
const [showStudyGuide, setShowStudyGuide] = useState(false);
|
||||
const videoRef = useRef<VideoRef>(null);
|
||||
const letterVideoRef = useRef<VideoRef>(null);
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
const [dragQuizValues, setDragQuizValues] = useState<Record<string, DragFillResult[]>>({})
|
||||
const [dragQuizErrors, setDragQuizErrors] = useState<Record<string, string>>({})
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [showVideo, setShowVideo] = useState(false)
|
||||
const [postGuideVisible, setPostGuideVisible] = useState(false)
|
||||
const [showLetter, setShowLetter] = useState(false)
|
||||
const [showLetterVideo, setShowLetterVideo] = useState(false)
|
||||
const [showStudyGuide, setShowStudyGuide] = useState(false)
|
||||
const videoRef = useRef<VideoRef>(null)
|
||||
const letterVideoRef = useRef<VideoRef>(null)
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setVisible(true);
|
||||
}, []);
|
||||
setVisible(true)
|
||||
}, [])
|
||||
|
||||
// 组件卸载时清理背景音乐
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current;
|
||||
const audio = audioRef.current
|
||||
return () => {
|
||||
if (audio) {
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
audio.pause()
|
||||
audio.currentTime = 0
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
}, [])
|
||||
|
||||
// 视频加载完成后自动播放
|
||||
const handleVideoCanPlay = () => {
|
||||
if (showVideo && videoRef.current) {
|
||||
videoRef.current.play().catch((error) => {
|
||||
console.warn("视频播放失败:", error);
|
||||
});
|
||||
console.warn('视频播放失败:', error)
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 信件视频加载完成后自动播放
|
||||
const handleLetterVideoCanPlay = () => {
|
||||
if (showLetterVideo && letterVideoRef.current) {
|
||||
letterVideoRef.current.play().catch((error) => {
|
||||
console.warn("信件视频播放失败:", error);
|
||||
});
|
||||
console.warn('信件视频播放失败:', error)
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
const anchors: VideoAnchor[] = useMemo(
|
||||
() =>
|
||||
QUIZ_ANCHORS.map((item) => {
|
||||
const correctAnswers = item.options
|
||||
.filter((opt) => opt.isCorrect)
|
||||
.map((opt) => opt.value);
|
||||
const correctAnswers = item.options.filter((opt) => opt.isCorrect).map((opt) => opt.value)
|
||||
|
||||
// 拖拽题处理
|
||||
if (item.type === "drag" && item.blanks) {
|
||||
if (item.type === 'drag' && item.blanks) {
|
||||
return {
|
||||
id: item.id,
|
||||
time: item.time,
|
||||
once: true,
|
||||
afterResume: "remove",
|
||||
afterResume: 'remove',
|
||||
render: ({ resume }) => {
|
||||
// 拖拽题:处理选项拖拽与校验
|
||||
const handleDragChange = (val: DragFillResult[]) => {
|
||||
setDragQuizValues((prev) => ({ ...prev, [item.id]: val }));
|
||||
setDragQuizErrors((prev) => ({ ...prev, [item.id]: "" }));
|
||||
setDragQuizValues((prev) => ({ ...prev, [item.id]: val }))
|
||||
setDragQuizErrors((prev) => ({ ...prev, [item.id]: '' }))
|
||||
|
||||
if (val.length < correctAnswers.length) return;
|
||||
if (val.length < correctAnswers.length) return
|
||||
|
||||
// 检查是否包含了所有正确答案(不要求顺序)
|
||||
const filledAnswers = val.map((v) => v.optionValue);
|
||||
const answerSet = new Set(correctAnswers);
|
||||
const filledSet = new Set(filledAnswers);
|
||||
const filledAnswers = val.map((v) => v.optionValue)
|
||||
const answerSet = new Set(correctAnswers)
|
||||
const filledSet = new Set(filledAnswers)
|
||||
const isCorrect =
|
||||
answerSet.size === filledSet.size &&
|
||||
[...answerSet].every((answer) => filledSet.has(answer));
|
||||
[...answerSet].every((answer) => filledSet.has(answer))
|
||||
|
||||
if (isCorrect) {
|
||||
setActiveSuccess(item.id);
|
||||
setResumeCallback(() => resume);
|
||||
setActiveSuccess(item.id)
|
||||
setResumeCallback(() => resume)
|
||||
} else {
|
||||
setDragQuizErrors((prev) => ({
|
||||
...prev,
|
||||
[item.id]:
|
||||
"这不是陈云的工作作风。请你再想想吧!",
|
||||
}));
|
||||
[item.id]: '这不是陈云的工作作风。请你再想想吧!',
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -255,36 +245,36 @@ const ChenyunInternalization = () => {
|
||||
title="恭喜你, 选择正确!"
|
||||
content="回答正确,请继续探索。"
|
||||
onContinue={() => {
|
||||
setActiveSuccess(null);
|
||||
triggerPuzzleAnimation(16);
|
||||
setActiveSuccess(null)
|
||||
triggerPuzzleAnimation(16)
|
||||
setDragQuizValues((prev) => {
|
||||
const next = { ...prev };
|
||||
delete next[item.id];
|
||||
return next;
|
||||
});
|
||||
const next = { ...prev }
|
||||
delete next[item.id]
|
||||
return next
|
||||
})
|
||||
setDragQuizErrors((prev) => {
|
||||
const next = { ...prev };
|
||||
delete next[item.id];
|
||||
return next;
|
||||
});
|
||||
const cb = resumeCallback;
|
||||
setResumeCallback(null);
|
||||
cb?.();
|
||||
const next = { ...prev }
|
||||
delete next[item.id]
|
||||
return next
|
||||
})
|
||||
const cb = resumeCallback
|
||||
setResumeCallback(null)
|
||||
cb?.()
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 多选题处理
|
||||
if (item.type === "multiple") {
|
||||
if (item.type === 'multiple') {
|
||||
return {
|
||||
id: item.id,
|
||||
time: item.time,
|
||||
once: true,
|
||||
afterResume: "remove",
|
||||
afterResume: 'remove',
|
||||
render: ({ resume }) => (
|
||||
<>
|
||||
<MultipleChoiceQuizPanel
|
||||
@@ -298,32 +288,27 @@ const ChenyunInternalization = () => {
|
||||
correctAnswer={correctAnswers}
|
||||
errorMessage={(selectedValues) => {
|
||||
// 题目1:选到“鸟笼比喻(B)”给专属提示;否则未选全给“还不够全面”提示
|
||||
if (item.id === "quiz-1") {
|
||||
if (selectedValues.includes("B")) {
|
||||
return (
|
||||
item.explanation ||
|
||||
"鸟笼比喻是陈云提出的一个比喻。请你再想想吧!"
|
||||
);
|
||||
if (item.id === 'quiz-1') {
|
||||
if (selectedValues.includes('B')) {
|
||||
return item.explanation || '鸟笼比喻是陈云提出的一个比喻。请你再想想吧!'
|
||||
}
|
||||
return MULTIPLE_DEFAULT_ERROR;
|
||||
return MULTIPLE_DEFAULT_ERROR
|
||||
}
|
||||
// 题目5:选到“D”给专属提示;否则未选全给“还不够全面”提示
|
||||
if (item.id === "quiz-5") {
|
||||
if (selectedValues.includes("D")) {
|
||||
const pickedD = item.options.find(
|
||||
(o) => o.value === "D"
|
||||
);
|
||||
return pickedD?.explanation || MULTIPLE_DEFAULT_ERROR;
|
||||
if (item.id === 'quiz-5') {
|
||||
if (selectedValues.includes('D')) {
|
||||
const pickedD = item.options.find((o) => o.value === 'D')
|
||||
return pickedD?.explanation || MULTIPLE_DEFAULT_ERROR
|
||||
}
|
||||
return MULTIPLE_DEFAULT_ERROR;
|
||||
return MULTIPLE_DEFAULT_ERROR
|
||||
}
|
||||
return item.explanation || MULTIPLE_DEFAULT_ERROR;
|
||||
return item.explanation || MULTIPLE_DEFAULT_ERROR
|
||||
}}
|
||||
onSubmit={(values: string[], isCorrect: boolean) => {
|
||||
if (isCorrect) {
|
||||
setActiveSuccess(item.id);
|
||||
if (item.id === "quiz-1") triggerPuzzleAnimation(15);
|
||||
setResumeCallback(() => resume);
|
||||
setActiveSuccess(item.id)
|
||||
if (item.id === 'quiz-1') triggerPuzzleAnimation(15)
|
||||
setResumeCallback(() => resume)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -332,15 +317,15 @@ const ChenyunInternalization = () => {
|
||||
// title="恭喜你, 选择正确!"
|
||||
// content="回答正确,请继续探索。"
|
||||
onContinue={() => {
|
||||
setActiveSuccess(null);
|
||||
const cb = resumeCallback;
|
||||
setResumeCallback(null);
|
||||
cb?.();
|
||||
setActiveSuccess(null)
|
||||
const cb = resumeCallback
|
||||
setResumeCallback(null)
|
||||
cb?.()
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 单选题处理(保留原有逻辑,以防万一)
|
||||
@@ -348,60 +333,50 @@ const ChenyunInternalization = () => {
|
||||
id: item.id,
|
||||
time: item.time,
|
||||
once: true,
|
||||
afterResume: "remove",
|
||||
afterResume: 'remove',
|
||||
render: () => null,
|
||||
};
|
||||
}
|
||||
}),
|
||||
[
|
||||
activeSuccess,
|
||||
resumeCallback,
|
||||
dragQuizValues,
|
||||
dragQuizErrors,
|
||||
triggerPuzzleAnimation,
|
||||
]
|
||||
);
|
||||
[activeSuccess, resumeCallback, dragQuizValues, dragQuizErrors, triggerPuzzleAnimation]
|
||||
)
|
||||
|
||||
if (!moduleName) return null;
|
||||
if (!moduleName) return null
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative h-full w-full bg-black"
|
||||
style={{
|
||||
backgroundImage: getBackgroundImage("components/internalization/bg"),
|
||||
backgroundImage: getBackgroundImage('components/internalization/bg'),
|
||||
}}
|
||||
>
|
||||
{/* 离开按钮 */}
|
||||
<Image
|
||||
className="absolute right-8 top-8 z-10"
|
||||
src={getStaticImage("components/离开")}
|
||||
src={getStaticImage('components/离开')}
|
||||
button
|
||||
onClick={() => navigate(`/${moduleName}/${starName}/home`)}
|
||||
/>
|
||||
|
||||
{/* 内化结束后的背景音乐 */}
|
||||
<audio
|
||||
ref={audioRef}
|
||||
src={getPublicPath("audio/letter/8如愿.m4a")}
|
||||
loop
|
||||
/>
|
||||
<audio ref={audioRef} src={getPublicPath('audio/letter/8如愿.m4a')} loop />
|
||||
|
||||
{showVideo && (
|
||||
<Video
|
||||
ref={videoRef}
|
||||
src={getPublicPath("video/chenyun/chenyun_neihua.mp4")}
|
||||
src={getPublicPath('video/chenyun/chenyun_neihua.mp4')}
|
||||
className="h-full w-full"
|
||||
anchors={anchors}
|
||||
playsInline
|
||||
controls
|
||||
onCanPlay={handleVideoCanPlay}
|
||||
onEnded={() => {
|
||||
setShowVideo(false);
|
||||
setPostGuideVisible(true);
|
||||
setShowVideo(false)
|
||||
setPostGuideVisible(true)
|
||||
if (audioRef.current) {
|
||||
audioRef.current.currentTime = 0;
|
||||
audioRef.current.currentTime = 0
|
||||
audioRef.current.play().catch((error) => {
|
||||
console.warn("背景音乐播放失败:", error);
|
||||
});
|
||||
console.warn('背景音乐播放失败:', error)
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -411,17 +386,17 @@ const ChenyunInternalization = () => {
|
||||
<GuideSteps
|
||||
visible={visible}
|
||||
onVisibleChange={(visible) => {
|
||||
setVisible(visible);
|
||||
setVisible(visible)
|
||||
if (!visible) {
|
||||
setShowVideo(true);
|
||||
handleVideoCanPlay();
|
||||
setShowVideo(true)
|
||||
handleVideoCanPlay()
|
||||
}
|
||||
}}
|
||||
showMask={false}
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="student"
|
||||
audioSrc={getPublicPath("audio/chenyun/mp3_chenyun_36.mp3")}
|
||||
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_36.mp3')}
|
||||
>
|
||||
小沪,跟着你参观陈云纪念馆真是收获满满!看到馆里展示的“米棉之战”史料、全国财经统筹的实物展品,我真切感受到陈云爷爷在建国初期平抑物价、稳定经济的魄力。
|
||||
</GuideStepsItem>
|
||||
@@ -430,7 +405,7 @@ const ChenyunInternalization = () => {
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath("audio/chenyun/mp3_chenyun_37.mp3")}
|
||||
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_37.mp3')}
|
||||
>
|
||||
针对你的这个问题,今天我们有幸邀请到了中国中共党史学会理事,全国陈云思想生平研究会常务理事兼副秘书长,中共一大纪念馆陈列研究部主任,研究馆员房中老师。关于你的问题,我想房老师会给你指点迷津!
|
||||
</GuideStepsItem>
|
||||
@@ -440,10 +415,10 @@ const ChenyunInternalization = () => {
|
||||
<GuideSteps
|
||||
visible={postGuideVisible}
|
||||
onVisibleChange={(visible) => {
|
||||
setPostGuideVisible(visible);
|
||||
setPostGuideVisible(visible)
|
||||
// 引导结束后显示信件
|
||||
if (!visible) {
|
||||
setShowLetter(true);
|
||||
setShowLetter(true)
|
||||
}
|
||||
}}
|
||||
showMask={false}
|
||||
@@ -451,16 +426,14 @@ const ChenyunInternalization = () => {
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="student"
|
||||
audioSrc={getPublicPath("audio/chenyun/mp3_chenyun_38.mp3")}
|
||||
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_38.mp3')}
|
||||
>
|
||||
感谢房老师的讲解!从陈云童年成长的水乡故居,到他主持"银元之战""米棉之战"的史料,再到那台称量粮食的天平、握不住的铅笔头,我真切感受到他"不唯上、不唯书、只唯实"的精神,也懂了他"为老百姓做事"的初心。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="student">
|
||||
这些都让我特别受触动!
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="student">这些都让我特别受触动!</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath("audio/chenyun/mp3_chenyun_39.mp3")}
|
||||
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_39.mp3')}
|
||||
>
|
||||
你的感悟很深刻!陈云同志用一生诠释了“务实”与“为民”——从破解边区经济困境,到擘画国家工业化蓝图,再到改革开放时力挺宝钢建设,每一步都扎根实际、心系百姓。
|
||||
</GuideStepsItem>
|
||||
@@ -474,9 +447,9 @@ const ChenyunInternalization = () => {
|
||||
visible={showLetter}
|
||||
onSubmit={(values) => {
|
||||
// 提交信件的逻辑(values 为多个填空的内容)
|
||||
console.log("提交信件", values);
|
||||
setShowLetter(false);
|
||||
setShowLetterVideo(true);
|
||||
console.log('提交信件', values)
|
||||
setShowLetter(false)
|
||||
setShowLetterVideo(true)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -484,13 +457,13 @@ const ChenyunInternalization = () => {
|
||||
{showLetterVideo && (
|
||||
<Video
|
||||
ref={letterVideoRef}
|
||||
src={getPublicPath("video/letter/neihua_jixin.mp4")}
|
||||
src={getPublicPath('video/letter/neihua_jixin.mp4')}
|
||||
className="h-full w-full"
|
||||
playsInline
|
||||
onCanPlay={handleLetterVideoCanPlay}
|
||||
onEnded={() => {
|
||||
setShowLetterVideo(false);
|
||||
setShowStudyGuide(true);
|
||||
setShowLetterVideo(false)
|
||||
setShowStudyGuide(true)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -502,16 +475,16 @@ const ChenyunInternalization = () => {
|
||||
animationSpeed={200}
|
||||
onContinue={() => {
|
||||
if (audioRef.current) {
|
||||
audioRef.current.pause();
|
||||
audioRef.current.currentTime = 0;
|
||||
audioRef.current.pause()
|
||||
audioRef.current.currentTime = 0
|
||||
}
|
||||
setShowStudyGuide(false);
|
||||
navigate(`/${moduleName}/${starName}/home`);
|
||||
setShowStudyGuide(false)
|
||||
navigate(`/${moduleName}/${starName}/home`)
|
||||
}}
|
||||
audioSrc={getPublicPath("audio/chenyun/mp3_chenyun_40.mp3")}
|
||||
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_40.mp3')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default ChenyunInternalization;
|
||||
export default ChenyunInternalization
|
||||
Reference in new issue
Block a user