feat: add puzzle residence configuration and reflection progress logic

- Introduced `puzzleResidences.ts` to define puzzle residence configurations including properties like display name, position, and puzzle availability.
- Added `reflectionProgress.ts` to manage badge unlocking logic based on place completion, including functions to determine unlocked badges and video sources for scenes.
This commit is contained in:
zhongyidian committed 2026-04-27 11:49:30 +08:00
1 parent e0fa47d21a
commit f5f36f75b5
153 files changed
+3846 -2352

No files matched your search

+77 -27
View File
@@ -8,10 +8,11 @@ import {
type DragFillResult,
LetterToChenyun,
EndingOverlay,
Narration,
} from '@/components'
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
import { SuccessAlert, DragQuizPanel } from '@/components/layout'
import { MultipleChoiceQuizPanel } from '@/components/layout/quiz'
import { MultipleChoiceQuizPanel, SingleChoiceQuizPanel } from '@/components/layout/quiz'
import { GuideSteps, GuideStepsItem } from '@/components'
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
import { setCourseTimeProgress } from '@/lib/utils/api-common'
@@ -44,9 +45,9 @@ const MULTIPLE_DEFAULT_ERROR = '你的选择还不够全面哦~请你再想想
const QUIZ_ANCHORS: QuizAnchor[] = [
{
id: 'quiz-1',
time: 60 * 5 + 52, //5.52分钟
time: 60 * 5 + 53, //5.52分钟
title: '题目1',
prompt: '陈云经济思想的核心内容指的是(\xa0\xa0\xa0\xa0)。',
prompt: '陈云经济思想的核心内容包括:',
type: 'multiple',
options: [
{ value: 'A', label: '综合平衡', isCorrect: true },
@@ -61,7 +62,7 @@ const QUIZ_ANCHORS: QuizAnchor[] = [
},
{
id: 'quiz-2',
time: 60 * 10 + 1, //10.01分钟
time: 60 * 10 + 2, //10.01分钟
title: '题目2',
prompt: '陈云说过以下哪些话能着重体现出他的经济思想?',
type: 'multiple',
@@ -83,7 +84,7 @@ const QUIZ_ANCHORS: QuizAnchor[] = [
},
{
id: 'quiz-3',
time: 16 * 60 + 26, //16:26
time: 16 * 60 + 31, //16:26
title: '题目3',
prompt: '新时代的青年可以从陈云身上学习到',
type: 'drag',
@@ -103,6 +104,21 @@ const QUIZ_ANCHORS: QuizAnchor[] = [
id: 'quiz-4',
time: 60 * 5 + 21, // 5:21
title: '题目4',
prompt: '陈云讲:“经济建设最终目的,是为了改善____的生活水平。”',
type: 'single',
options: [
{
value: 'A',
label: '为官者',
explanation: '这不是陈云提倡的经济建设的最终目的。请你再想想吧!',
},
{ value: 'B', label: '老百姓', isCorrect: true },
],
},
{
id: 'quiz-5',
time: 60 * 16 + 23, // 16:23
title: '题目5',
prompt: '以下哪些陈云的生活小事值得我们学习?',
type: 'multiple',
options: [
@@ -113,25 +129,6 @@ const QUIZ_ANCHORS: QuizAnchor[] = [
],
explanation: MULTIPLE_DEFAULT_ERROR,
},
{
id: 'quiz-5',
time: 60 * 16 + 23, // 16:23
title: '题目5',
prompt: '新时代的青年要从陈云身上学习哪些精神品质?',
type: 'multiple',
options: [
{ value: 'A', label: '谦虚谨慎,实事求是的工作作风', isCorrect: true },
{ value: 'B', label: '勤俭朴素,艰苦奋斗的优良作风', isCorrect: true },
{ value: 'C', label: '密切联系群众,关心群众生活', isCorrect: true },
{
value: 'D',
label: '只唯上的工作作风',
isCorrect: false,
explanation: '"只唯上"的工作作风与陈云同志实事求是的精神相悖。请你再想想吧!',
},
],
explanation: MULTIPLE_DEFAULT_ERROR,
},
]
const ChenyunInternalization = () => {
@@ -144,6 +141,7 @@ const ChenyunInternalization = () => {
// 拖拽题状态
const [dragQuizValues, setDragQuizValues] = useState<Record<string, DragFillResult[]>>({})
const [dragQuizErrors, setDragQuizErrors] = useState<Record<string, string>>({})
const [narrationVisible, setNarrationVisible] = useState(false)
const [visible, setVisible] = useState(false)
const [showVideo, setShowVideo] = useState(false)
const [postGuideVisible, setPostGuideVisible] = useState(false)
@@ -152,7 +150,7 @@ const ChenyunInternalization = () => {
const videoRef = useRef<VideoRef>(null)
useEffect(() => {
setVisible(true)
setNarrationVisible(true)
}, [])
// 视频加载完成后自动播放
@@ -307,7 +305,48 @@ const ChenyunInternalization = () => {
}
}
// 单选题处理(保留原有逻辑,以防万一)
if (item.type === 'single') {
return {
id: item.id,
time: item.time,
once: true,
afterResume: 'remove',
render: ({ resume }) => (
<>
<SingleChoiceQuizPanel
visible={activeSuccess !== item.id}
zIndex={10000}
title={`【单选】${item.prompt}`}
options={item.options.map((opt) => ({
value: opt.value,
label: `${opt.value}. ${opt.label}`,
}))}
correctAnswer={correctAnswers[0]}
onWrongSelect={(value) =>
item.options.find((opt) => opt.value === value)?.explanation
}
onSubmit={(_, isCorrect) => {
if (isCorrect) {
setActiveSuccess(item.id)
setResumeCallback(() => resume)
}
}}
/>
<SuccessAlert
visible={activeSuccess === item.id}
title="恭喜你,选择正确!"
onContinue={() => {
setActiveSuccess(null)
const cb = resumeCallback
setResumeCallback(null)
cb?.()
}}
/>
</>
),
}
}
return {
id: item.id,
time: item.time,
@@ -336,6 +375,17 @@ const ChenyunInternalization = () => {
onClick={() => navigate(`/${moduleName}/${starName}/home`)}
/>
<Narration
visible={narrationVisible}
audioChannelId="chenyun-internalization-narration"
onClose={() => {
setNarrationVisible(false)
setVisible(true)
}}
text={`从练塘水乡的少年时光,到商务印书馆的革命启航;从苏区与延安的经济破局,到新中国成立之初打赢“银元之战”“米棉之战”,再到建设与改革岁月里擘画实业、奠基兴国,我们已循着陈云同志的足迹,走过一段波澜壮阔的奋斗征程。那些“全国一盘棋”的统筹智慧、“不唯上、不唯书、只唯实”的务实品格、“为老百姓做事”的为民初心,穿越历史烟云,依旧闪耀着时代光芒。历史的回响已在耳畔,精神的传承更需躬身践行。新时代的青年,应该从历史感悟走向思想内化,读懂陈云经济思想的深刻内涵,汲取指引青春成长、担当时代使命的精神力量,让伟人风范在新时代薪火相传。`}
animationSpeed={200}
/>
{showVideo && (
<Video
ref={videoRef}
@@ -434,7 +484,7 @@ const ChenyunInternalization = () => {
onContinue={() => {
setShowStudyGuide(false)
setCourseTimeProgress(24)
navigate(`/${moduleName}/${starName}/home`)
navigate('/menu')
}}
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_40.mp3')}
/>