fix: update quiz flows and chenyun reflection progression

Add the requested Rong Desheng quiz gates and fix Chen Yun reflection progression so success prompts and trend chart state advance correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.7 committed 2026-05-13 09:54:21 +08:00
1 parent 284302341c
commit 68ba22a33f
7 files changed
+159 -99

No files matched your search

+84 -65
View File
@@ -3,16 +3,19 @@ import {
GuideSteps,
GuideStepsItem,
Image,
MultipleChoiceQuizPanel,
SingleChoiceQuizPanel,
Title,
Video,
} from '@/components'
import { SuccessAlert } from '@/components/layout'
import Cursor from '@/components/cursor'
import { useCursorController } from '@/hooks/useCursorController'
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
import { useMemo, useState } from 'react'
import { useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { saveRongdeshengStore, useRongdeshengStore } from '@/store/rongdeshengStore'
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
const starName = 'rongdesheng'
const place = 'place2'
@@ -23,11 +26,12 @@ const RongdeshengPlace2 = () => {
const { markExhibitVisited, getVisitedExhibits, setLastVisitedPlace } = useRongdeshengStore()
const persistedVisited = useMemo(
() => new Set(getVisitedExhibits(place) as (1 | 2 | 3 | 4 | 5)[]),
[getVisitedExhibits]
)
const [visited, setVisited] = useState<Set<1 | 2 | 3 | 4 | 5>>(() => new Set(persistedVisited))
// 获取碎片动画触发方法
const { triggerPuzzleAnimation } = usePuzzleAnimation()
// 从 store 获取已访问的展品,转换为 Set 用于兼容现有代码
const visitedExhibits = getVisitedExhibits(place)
const visited = new Set(visitedExhibits)
const total = 5
const progressCount = visited.size
@@ -60,6 +64,8 @@ const RongdeshengPlace2 = () => {
const [quiz4Visible, setQuiz4Visible] = useState(false)
const [guide5BeforeVisible, setGuide5BeforeVisible] = useState(false)
const [guide5BeforeStep, setGuide5BeforeStep] = useState(0)
const [quiz5Visible, setQuiz5Visible] = useState(false)
const [quiz5SuccessVisible, setQuiz5SuccessVisible] = useState(false)
const [guide5AfterVisible, setGuide5AfterVisible] = useState(false)
const [guide5AfterStep, setGuide5AfterStep] = useState(0)
@@ -98,22 +104,15 @@ const RongdeshengPlace2 = () => {
setGuide1AfterVideoVisible(true)
}
if (id === 2) {
setVisited((prev) => {
const next = new Set(prev)
if (!next.has(2)) {
next.add(2)
markExhibitVisited(place, 2)
saveRongdeshengStore()
}
return next
})
markExhibitVisited(place, 2)
// 触发碎片4获取动画
triggerPuzzleAnimation(4)
}
if (id === 4) {
setQuiz4Visible(true)
}
if (id === 5) {
setGuide5AfterStep(0)
setGuide5AfterVisible(true)
setQuiz5Visible(true)
}
}
@@ -197,15 +196,11 @@ const RongdeshengPlace2 = () => {
}
// 其余展品先保持关闭即完成
setVisited((prev) => {
const next = new Set(prev)
if (!next.has(closingId)) {
next.add(closingId)
markExhibitVisited(place, closingId)
saveRongdeshengStore()
}
return next
})
markExhibitVisited(place, closingId)
// 触发碎片5获取动画(展品3 -> 碎片5)
if (closingId === 3) {
triggerPuzzleAnimation(5)
}
}}
/>
@@ -267,7 +262,7 @@ const RongdeshengPlace2 = () => {
speaker="student"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_07.mp3')}
>
哇,这是福新面粉公司的老照片!荣德生先生为什么选择办面粉,面粉厂又为什么在上海创办?福新面粉厂后来发展得怎么样?
哇,这是福新面粉公司的老照片!荣德生先生为什么选择办面粉,面粉厂又为什么在上海创办?福新面粉厂后来发展得怎么样?
</GuideStepsItem>
<GuideStepsItem
speaker="guide"
@@ -293,11 +288,14 @@ const RongdeshengPlace2 = () => {
>
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_09.mp3')}
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_09_1.mp3')}
>
目睹洋面粉倾销的荣先生与兄长一起在无锡创办了保兴面粉厂,1912年,荣氏兄弟又看准了上海的区位优势——交通便利、人口密集、市场需求大,于是在上海创办了福新面粉厂,引进了当时最先进的生产设备。
目睹洋面粉倾销的荣先生先是与兄长一起在无锡创办了保兴面粉厂,1912年,荣氏兄弟又看准了上海的区位优势——交通便利、人口密集、市场需求大,于是在上海创办了福新面粉厂,引进了当时最先进的生产设备。
</GuideStepsItem>
<GuideStepsItem speaker="guide">
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_09_2.mp3')}
>
之后他们趁热打铁,又在上海接连创办了福新二厂、三厂,还收买或租办了中兴面粉厂等,改为福新四厂、六厂,形成了规模化的面粉生产体系。短短几年间,福新面粉厂的产量就占据了上海面粉市场的半壁江山。
</GuideStepsItem>
</GuideSteps>
@@ -320,12 +318,15 @@ const RongdeshengPlace2 = () => {
</GuideStepsItem>
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_11.mp3')}
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_11_1.mp3')}
>
是的!1915年,他与兄长在上海招股创办了申新纺织无限公司,并开办申新一厂。他们之所以选择纺织业,是因为当时中国的棉纱市场被外资垄断,老百姓的棉布多依赖进口。
是的!荣德生先生深知,民族工业要强大,不能只靠一个行业。1915年,他与兄长在上海招股创办了申新纺织无限公司,并开办申新一厂。无限公司承担无限责任,荣氏将全部身家与振兴民族纺织业牢牢绑定。
</GuideStepsItem>
<GuideStepsItem speaker="guide">
申新纺织公司的创办,就是要打破这种垄断局面,为国人生产品质优良的棉纱、棉布。
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_11_2.mp3')}
>
他们之所以选择纺织业,是因为当时中国的棉纱市场被外资垄断,老百姓穿的棉布大多依赖进口。申新纺织公司的创办,就是要打破这种垄断局面,为国人生产优质的棉纱、棉布。
</GuideStepsItem>
</GuideSteps>
@@ -349,15 +350,9 @@ const RongdeshengPlace2 = () => {
}}
onSuccessContinue={() => {
setQuiz4Visible(false)
setVisited((prev) => {
const next = new Set(prev)
if (!next.has(4)) {
next.add(4)
markExhibitVisited(place, 4)
saveRongdeshengStore()
}
return next
})
markExhibitVisited(place, 4)
// 触发碎片6获取动画(展品4 -> 碎片6)
triggerPuzzleAnimation(6)
}}
/>
@@ -379,19 +374,43 @@ const RongdeshengPlace2 = () => {
}}
onSuccessContinue={() => {
setQuiz1Visible(false)
setVisited((prev) => {
const next = new Set(prev)
if (!next.has(1)) {
next.add(1)
markExhibitVisited(place, 1)
saveRongdeshengStore()
}
return next
})
markExhibitVisited(place, 1)
// 触发碎片3获取动画(展品1 -> 碎片3)
triggerPuzzleAnimation(3)
}}
/>
{/* 展品5:打开即对话 + 视频后对话并标记完成 */}
<MultipleChoiceQuizPanel
visible={quiz5Visible}
zIndex={10001}
title="【多选】荣氏企业能成为“面粉大王”“纺织巨子”,核心原因有哪些?"
options={[
{ value: 'A', label: 'A.打造了质量过硬的拳头产品,形成行业标准' },
{ value: 'B', label: 'B.推行兼顾劳资利益的人文管理模式,激发工人积极性' },
{ value: 'C', label: 'C.精准把握区位优势,实现规模化生产' },
{ value: 'D', label: 'D.一味依靠外资扶持发展产业' },
]}
correctAnswer={['A', 'B', 'C']}
errorMessage="很遗憾选择有误,荣氏企业是民族工业自主发展的代表,未依靠外资扶持,其成功源于优质产品、人文管理和精准布局。请你再想想吧!"
minSelections={1}
onSubmit={(_values, isCorrect) => {
if (!isCorrect) return
setQuiz5Visible(false)
setQuiz5SuccessVisible(true)
}}
/>
<SuccessAlert
visible={quiz5SuccessVisible}
content="荣氏企业凭借优质产品、人文管理、精准的产业布局实现规模化发展,是民族工业自主发展的典范。"
onClose={() => {
setQuiz5SuccessVisible(false)
setGuide5AfterStep(0)
setGuide5AfterVisible(true)
}}
/>
{/* 展品5:打开即对话 + 视频后答题,答对后显示对话并标记完成 */}
<GuideSteps
visible={guide5BeforeVisible}
onVisibleChange={setGuide5BeforeVisible}
@@ -420,15 +439,9 @@ const RongdeshengPlace2 = () => {
onVisibleChange={(v) => {
setGuide5AfterVisible(v)
if (!v) {
setVisited((prev) => {
const next = new Set(prev)
if (!next.has(5)) {
next.add(5)
markExhibitVisited(place, 5)
saveRongdeshengStore()
}
return next
})
markExhibitVisited(place, 5)
// 触发碎片7获取动画(展品5 -> 碎片7)
triggerPuzzleAnimation(7)
}
}}
currentStep={guide5AfterStep}
@@ -439,14 +452,20 @@ const RongdeshengPlace2 = () => {
>
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_14.mp3')}
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_14_1.mp3')}
>
在荣德生先生推行的以“劳资双方利益要兼顾”为出发点的劳工自治区管理模式下,工人在企业里得到尊重和关怀,干事的积极性自然高涨。他们不仅严格把控生产环节,还主动参与技术改进。
</GuideStepsItem>
<GuideStepsItem speaker="guide">
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_14_2.mp3')}
>
再加上荣先生坚持每天清晨用前一天的面粉做疙瘩汤亲自检验品质的严谨态度,形成了“人文管理+品质把控”的双重保障。
</GuideStepsItem>
<GuideStepsItem speaker="guide">
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_14_3.mp3')}
>
这种立足创新、聚焦工人福利的全方位关照,让荣氏产品质量远超同行,成功抵御了洋货倾销,也让“兵船”牌面粉和“人钟牌”棉纱成为行业标准。
</GuideStepsItem>
</GuideSteps>
+67 -26
View File
@@ -4,15 +4,18 @@ import {
GuideSteps,
GuideStepsItem,
Image,
SingleChoiceQuizPanel,
Title,
Video,
} from '@/components'
import Cursor from '@/components/cursor'
import { useCursorController } from '@/hooks/useCursorController'
import { getBackgroundImage, getPublicPath, getStaticImage } from '@/lib/utils'
import { useMemo, useState } from 'react'
import { useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { saveRongdeshengStore, useRongdeshengStore } from '@/store/rongdeshengStore'
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
import { setCourseTimeProgress } from '@/lib/utils/api-common'
const starName = 'rongdesheng'
const place = 'place4'
@@ -23,11 +26,12 @@ const RongdeshengPlace4 = () => {
const { markExhibitVisited, getVisitedExhibits, setLastVisitedPlace } = useRongdeshengStore()
const persistedVisited = useMemo(
() => new Set(getVisitedExhibits(place) as (1 | 2 | 3 | 4)[]),
[getVisitedExhibits]
)
const [visited, setVisited] = useState<Set<1 | 2 | 3 | 4>>(() => new Set(persistedVisited))
// 获取碎片动画触发方法
const { triggerPuzzleAnimation } = usePuzzleAnimation()
// 从 store 获取已访问的展品,转换为 Set 用于兼容现有代码
const visitedExhibits = getVisitedExhibits(place)
const visited = new Set(visitedExhibits)
const total = 4
const progressCount = visited.size
@@ -55,6 +59,7 @@ const RongdeshengPlace4 = () => {
const [guide1AfterVideoStep, setGuide1AfterVideoStep] = useState(0)
const [guide2Visible, setGuide2Visible] = useState(false)
const [guide2Step, setGuide2Step] = useState(0)
const [quiz2Visible, setQuiz2Visible] = useState(false)
const [guide3Visible, setGuide3Visible] = useState(false)
const [guide3Step, setGuide3Step] = useState(0)
const [guide4Visible, setGuide4Visible] = useState(false)
@@ -156,6 +161,7 @@ const RongdeshengPlace4 = () => {
onClick={() => {
setLastVisitedPlace('place4')
saveRongdeshengStore()
setCourseTimeProgress(19)
navigate(`/${moduleName}/${starName}/home`)
}}
/>
@@ -169,15 +175,20 @@ const RongdeshengPlace4 = () => {
const closingId = activeExhibitId
setActiveExhibitId(null)
// 展品1在视频后对话结束再改状态;2/3/4关闭展品即改状态
if (closingId === 2 || closingId === 3 || closingId === 4) {
setVisited((prev) => {
const next = new Set(prev)
next.add(closingId)
markExhibitVisited(place, closingId)
saveRongdeshengStore()
return next
})
// 展品1在视频后对话结束再改状态;展品2答题后再改状态;3/4关闭展品即改状态
if (closingId === 2) {
setQuiz2Visible(true)
}
if (closingId === 3 || closingId === 4) {
markExhibitVisited(place, closingId)
// 触发碎片获取动画(展品3 -> 碎片13,展品4 -> 碎片14)
if (closingId === 3) {
triggerPuzzleAnimation(13)
} else if (closingId === 4) {
triggerPuzzleAnimation(14)
}
if (closingId === 4) {
setShowEndingVideo(true)
@@ -242,15 +253,9 @@ const RongdeshengPlace4 = () => {
onVisibleChange={(v) => {
setGuide1AfterVideoVisible(v)
if (!v) {
setVisited((prev) => {
const next = new Set(prev)
if (!next.has(1)) {
next.add(1)
markExhibitVisited(place, 1)
saveRongdeshengStore()
}
return next
})
markExhibitVisited(place, 1)
// 触发碎片11获取动画(展品1 -> 碎片11)
triggerPuzzleAnimation(11)
}
}}
currentStep={guide1AfterVideoStep}
@@ -284,15 +289,51 @@ const RongdeshengPlace4 = () => {
</GuideStepsItem>
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_26.mp3')}
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_26_1.mp3')}
>
1948年,解放战争接近尾声,很多实业家纷纷撤离大陆,前往台湾或海外。但荣德生先生专程从无锡来到上海,发表声明,明确表态绝不离开大陆。他在给海外亲友的信中写道:“民族工业的根基在大陆,离开这片土地,实业救国便成空谈。”
</GuideStepsItem>
<GuideStepsItem speaker="guide">
<GuideStepsItem
speaker="guide"
audioSrc={getPublicPath('audio/rongdesheng/mp3_rongdesheng_26_2.mp3')}
>
他不仅自己留下,还力排众议,阻止了荣氏企业迁台的计划,保住了大量的工厂设备、技术人才和生产资料。这份坚守,为新中国成立后的民族工业留存了重要力量,也体现了一位民族实业家的家国情怀。
</GuideStepsItem>
</GuideSteps>
<SingleChoiceQuizPanel
visible={quiz2Visible}
zIndex={10001}
title="【单选】1948年荣德生坚决不离开大陆并阻止企业迁台,主要是因为:"
options={[
{ value: 'A', label: 'A.担心财产损失' },
{ value: 'B', label: 'B.家人不愿离开' },
{ value: 'C', label: 'C.对新中国充满希望,坚守实业救国初心' },
]}
correctAnswer="C"
onWrongSelect={(value) => {
if (value === 'A') {
return '荣德生作为民族实业家,毕生以实业救国、报国惠民为初心,其决策的核心是家国大义,而非个人财产得失,因此担心财产损失并非他阻止企业迁台的原因。请你再想想吧!'
}
if (value === 'B') {
return '荣德生阻止企业迁台是基于自己对民族工业发展的深刻认知与坚定的爱国信念,是他独立且主动的抉择,并非受家人意愿的影响。请你再想想吧!'
}
}}
successAlertProps={{
content:
'荣德生毕生信奉“实业救国”,他认为民族工业的根基在大陆,对新中国的经济发展充满希望,希望能继续为国家和人民贡献力量,这是他坚守的核心原因。',
}}
onSubmit={(_value, isCorrect) => {
if (!isCorrect) return
}}
onSuccessContinue={() => {
setQuiz2Visible(false)
markExhibitVisited(place, 2)
// 触发碎片12获取动画(展品2 -> 碎片12)
triggerPuzzleAnimation(12)
}}
/>
<GuideSteps
visible={guide3Visible}
onVisibleChange={setGuide3Visible}