feat:修改英文双引号
This commit is contained in:
commit
4a2be3b4d0
1351 files changed
+56547
No files matched your search
@@ -0,0 +1,406 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import {
|
||||
Title,
|
||||
Image,
|
||||
Cursor,
|
||||
Video,
|
||||
GuideSteps,
|
||||
GuideStepsItem,
|
||||
type SingleChoiceOption,
|
||||
type DragFillResult,
|
||||
SingleChoiceQuizPanel,
|
||||
} from '@/components'
|
||||
import { SuccessAlert, DragQuizPanel } from '@/components/layout'
|
||||
import { getBackgroundImage, getStaticImage, getPublicPath } from '@/lib/utils'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import type { VideoRef } from '@/components/video'
|
||||
import { useChenyunStore, saveChenyunStore } from '@/store/chenyunStore'
|
||||
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
|
||||
|
||||
const STAR_NAME = 'chenyun'
|
||||
const PLACE = 'place7'
|
||||
const EXHIBIT_ID = 1
|
||||
const PUZZLE_PIECE_ID = 10
|
||||
const TOTAL_EXHIBITS = 1
|
||||
|
||||
// ─── 资源路径 ───
|
||||
const BACKGROUND_KEY = `${STAR_NAME}/${PLACE}/场景7`
|
||||
const CONTINUE_IMAGE_KEY = `${STAR_NAME}/${PLACE}/继续前进`
|
||||
const VIDEO_1_SRC = getPublicPath(`video/${STAR_NAME}/chenyun_10.mp4`)
|
||||
const VIDEO_2_SRC = getPublicPath(`video/${STAR_NAME}/chenyun_11.mp4`)
|
||||
const AUDIO_PREFIX = `audio/${STAR_NAME}`
|
||||
|
||||
// ─── 题目1:单选 ───
|
||||
const QUIZ1_OPTIONS: SingleChoiceOption[] = [
|
||||
{ value: 'A', label: 'A.推动了淮海战役的胜利' },
|
||||
{ value: 'B', label: 'B.有利于稳定人民币的发行和地位' },
|
||||
{ value: 'C', label: 'C.巩固了新中国人民政权' },
|
||||
]
|
||||
|
||||
const QUIZ1_CORRECT: string = 'B'
|
||||
|
||||
const QUIZ1_TITLE =
|
||||
'【单选】1949年6月,中共中央指示打击银元投机活动,金条、银元一律由人民银行挂牌收兑,铁路交通事业,税收一律收人民币。同时,上海军管会查封了证券大楼。这次“银元之战”:'
|
||||
|
||||
const QUIZ1_ERROR_HINTS: Record<string, string> = {
|
||||
A: '淮海战役于1949年1月胜利结束,发生在这次“银元之战”前,不存在因果关系。请你再想想吧!',
|
||||
C: '1949年6月新中国政权尚未建立。请你再想想吧',
|
||||
}
|
||||
|
||||
const QUIZ1_FALLBACK_HINT = '再想一想,注意题干中的时间和提示信息哦~'
|
||||
|
||||
const QUIZ1_SUCCESS_CONTENT =
|
||||
'“银元之战”属于当时人民政府整顿金融的重要举措,黄金、银元投机不利于人民币币值稳定和流通,因此“银元之战”打击贵金属投机活动,有利于稳定人民币的发行和地位。'
|
||||
|
||||
// ─── 题目2:拖拽 ───
|
||||
const QUIZ2_BLANKS = [
|
||||
{ id: 'blank-1', label: '____' },
|
||||
{ id: 'blank-2', label: '____' },
|
||||
{ id: 'blank-3', label: '____' },
|
||||
]
|
||||
|
||||
const QUIZ2_OPTIONS = [
|
||||
{ value: '棉纱', label: '棉纱' },
|
||||
{ value: '大米', label: '大米' },
|
||||
{ value: '煤炭', label: '煤炭' },
|
||||
{ value: '石油', label: '石油' },
|
||||
]
|
||||
|
||||
const QUIZ2_CORRECT_SET = new Set(['棉纱', '大米', '煤炭'])
|
||||
|
||||
const QUIZ2_PREFIX =
|
||||
'【拖拽】新中国成立后,为了稳定物价,中央政府组织了“两白一黑”的集中调运,“两白一黑”指的是'
|
||||
|
||||
const QUIZ2_ERROR = '石油当时不是主要调控对象。请你再想想吧!'
|
||||
|
||||
const isQuiz2Correct = (answers: DragFillResult[]): boolean => {
|
||||
if (answers.length !== QUIZ2_CORRECT_SET.size) return false
|
||||
const filled = new Set(answers.map((a) => a.optionValue))
|
||||
if (filled.size !== QUIZ2_CORRECT_SET.size) return false
|
||||
for (const value of QUIZ2_CORRECT_SET) {
|
||||
if (!filled.has(value)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const ChenyunPlace7 = () => {
|
||||
const navigate = useNavigate()
|
||||
const { moduleName } = useParams<{ moduleName: string }>()
|
||||
const { triggerPuzzleAnimation } = usePuzzleAnimation()
|
||||
const { markExhibitVisited, getVisitedExhibits, setLastVisitedPlace } = useChenyunStore()
|
||||
|
||||
const visited = new Set(getVisitedExhibits(PLACE))
|
||||
const completed = visited.size >= TOTAL_EXHIBITS
|
||||
|
||||
// ─── 第一阶段:视频1 + 对话1 + 单选题 ───
|
||||
const videoRef1 = useRef<VideoRef>(null)
|
||||
const [video1Visible, setVideo1Visible] = useState(false)
|
||||
const [video1Playing, setVideo1Playing] = useState(false)
|
||||
const [guide1Visible, setGuide1Visible] = useState(false)
|
||||
const [guide1Step, setGuide1Step] = useState(0)
|
||||
const [quiz1Visible, setQuiz1Visible] = useState(false)
|
||||
const [quiz1Completed, setQuiz1Completed] = useState(false)
|
||||
|
||||
// ─── 第二阶段:视频2 + 对话2 + 拖拽题 ───
|
||||
const videoRef2 = useRef<VideoRef>(null)
|
||||
const [video2Visible, setVideo2Visible] = useState(false)
|
||||
const [video2Playing, setVideo2Playing] = useState(false)
|
||||
const [guide2Visible, setGuide2Visible] = useState(false)
|
||||
const [guide2Step, setGuide2Step] = useState(0)
|
||||
const [quiz2Visible, setQuiz2Visible] = useState(false)
|
||||
const [quiz2Value, setQuiz2Value] = useState<DragFillResult[]>([])
|
||||
const [quiz2Error, setQuiz2Error] = useState('')
|
||||
const [quiz2Completed, setQuiz2Completed] = useState(false)
|
||||
|
||||
// ─── 成功提示 ───
|
||||
const [successVisible, setSuccessVisible] = useState(false)
|
||||
const [successContent, setSuccessContent] = useState('')
|
||||
|
||||
// ─── 流程辅助 ───
|
||||
const resetFlow = useCallback(() => {
|
||||
setVideo1Visible(false)
|
||||
setVideo1Playing(false)
|
||||
setGuide1Visible(false)
|
||||
setGuide1Step(0)
|
||||
setQuiz1Visible(false)
|
||||
setQuiz1Completed(false)
|
||||
|
||||
setVideo2Visible(false)
|
||||
setVideo2Playing(false)
|
||||
setGuide2Visible(false)
|
||||
setGuide2Step(0)
|
||||
setQuiz2Visible(false)
|
||||
setQuiz2Value([])
|
||||
setQuiz2Error('')
|
||||
setQuiz2Completed(false)
|
||||
|
||||
setSuccessVisible(false)
|
||||
setSuccessContent('')
|
||||
}, [])
|
||||
|
||||
const enterPhase1 = useCallback(() => {
|
||||
setVideo1Visible(true)
|
||||
setVideo1Playing(false)
|
||||
setGuide1Visible(true)
|
||||
setGuide1Step(0)
|
||||
}, [])
|
||||
|
||||
const enterPhase2 = useCallback(() => {
|
||||
setVideo2Visible(true)
|
||||
setVideo2Playing(false)
|
||||
setGuide2Visible(true)
|
||||
setGuide2Step(0)
|
||||
}, [])
|
||||
|
||||
// 点击展品光标:每次都从头走完整流程
|
||||
const handleOpenExhibit = useCallback(() => {
|
||||
resetFlow()
|
||||
enterPhase1()
|
||||
}, [resetFlow, enterPhase1])
|
||||
|
||||
// 对话1 结束 → 播放视频1
|
||||
const handleGuide1VisibleChange = (visible: boolean) => {
|
||||
setGuide1Visible(visible)
|
||||
if (!visible && video1Visible) {
|
||||
setVideo1Playing(true)
|
||||
videoRef1.current?.play()
|
||||
}
|
||||
}
|
||||
|
||||
// 对话2 结束 → 播放视频2
|
||||
const handleGuide2VisibleChange = (visible: boolean) => {
|
||||
setGuide2Visible(visible)
|
||||
if (!visible && video2Visible) {
|
||||
setVideo2Playing(true)
|
||||
videoRef2.current?.play()
|
||||
}
|
||||
}
|
||||
|
||||
// 视频1 结束:标记访问 + 触发拼图 + 出题1
|
||||
const handleVideo1Ended = () => {
|
||||
setVideo1Playing(false)
|
||||
markExhibitVisited(PLACE, EXHIBIT_ID)
|
||||
triggerPuzzleAnimation(PUZZLE_PIECE_ID)
|
||||
setQuiz1Visible(true)
|
||||
}
|
||||
|
||||
// 题1 答对:弹成功提示,关闭后进入第二阶段
|
||||
const handleQuiz1Submit = () => {
|
||||
setQuiz1Visible(false)
|
||||
setQuiz1Completed(true)
|
||||
setSuccessContent(QUIZ1_SUCCESS_CONTENT)
|
||||
setSuccessVisible(true)
|
||||
}
|
||||
|
||||
// 视频2 结束:出题2
|
||||
const handleVideo2Ended = () => {
|
||||
setVideo2Playing(false)
|
||||
setQuiz2Visible(true)
|
||||
}
|
||||
|
||||
// 题2 实时校验:填齐后判定
|
||||
const handleQuiz2Change = (val: DragFillResult[]) => {
|
||||
setQuiz2Value(val)
|
||||
setQuiz2Error('')
|
||||
if (val.length < QUIZ2_CORRECT_SET.size) return
|
||||
|
||||
if (!isQuiz2Correct(val)) {
|
||||
setQuiz2Error(QUIZ2_ERROR)
|
||||
return
|
||||
}
|
||||
|
||||
setQuiz2Visible(false)
|
||||
setVideo1Visible(false)
|
||||
setVideo2Visible(false)
|
||||
setQuiz2Completed(true)
|
||||
setSuccessContent('')
|
||||
setSuccessVisible(true)
|
||||
}
|
||||
|
||||
// 成功提示关闭:题1答对后才进入第二阶段;题2答对后则停留在场景
|
||||
const handleSuccessDismiss = () => {
|
||||
setSuccessVisible(false)
|
||||
if (quiz1Completed && !quiz2Completed && !quiz2Visible) {
|
||||
enterPhase2()
|
||||
}
|
||||
}
|
||||
|
||||
if (!moduleName) return null
|
||||
|
||||
const subtitle = completed ? '已完成' : `${visited.size}/${TOTAL_EXHIBITS}`
|
||||
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(BACKGROUND_KEY) }}
|
||||
>
|
||||
{/* 标题 */}
|
||||
<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}/${STAR_NAME}/place6`)}
|
||||
/>
|
||||
|
||||
{/* 展品1 光标 */}
|
||||
<Cursor
|
||||
className="absolute left-230 top-88"
|
||||
onClick={handleOpenExhibit}
|
||||
read={visited.has(EXHIBIT_ID)}
|
||||
/>
|
||||
|
||||
{/* 继续前进 - 仅在完成所有展品后显示 */}
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage(CONTINUE_IMAGE_KEY)}
|
||||
button
|
||||
onClick={() => {
|
||||
setLastVisitedPlace('place8')
|
||||
saveChenyunStore()
|
||||
navigate(`/${moduleName}/${STAR_NAME}/place8`)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 视频1(全屏) */}
|
||||
{video1Visible && (
|
||||
<div className="fixed inset-0 z-9999 bg-black">
|
||||
<Video
|
||||
ref={videoRef1}
|
||||
src={VIDEO_1_SRC}
|
||||
className="w-full h-full"
|
||||
autoPlay={video1Playing}
|
||||
playsInline
|
||||
preload="auto"
|
||||
muted={!video1Playing}
|
||||
showSkipButton
|
||||
onEnded={handleVideo1Ended}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 对话1(叠加在视频1之上) */}
|
||||
<GuideSteps
|
||||
visible={guide1Visible}
|
||||
onVisibleChange={handleGuide1VisibleChange}
|
||||
currentStep={guide1Step}
|
||||
onStepChange={setGuide1Step}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10001}
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="student"
|
||||
audioSrc={getPublicPath(`${AUDIO_PREFIX}/mp3_chenyun_19.mp3`)}
|
||||
>
|
||||
那"银元之战"是如何取得胜利的呢?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath(`${AUDIO_PREFIX}/mp3_chenyun_20.mp3`)}
|
||||
>
|
||||
由于通货膨胀,国民党发行的法币、金圆券变成了一堆废纸。当时坊间流传“大街过三道,物价跳三跳”。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
有人计算,一百元法币,在一九三七年可买两头牛,一九四五年只能买两个鸡蛋,一九四七年只能买一个煤球,到一九四九年五月连一粒米也买不到。可见,当时通货膨胀多么严重。
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem speaker="guide">
|
||||
打击投机资本,稳定金融物价,陈云代中央起草《中共中央关于打击银元使人民币占领阵地的指示》,提出以强硬手段打击投机势力。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
|
||||
{/* 题目1:单选 */}
|
||||
<SingleChoiceQuizPanel
|
||||
visible={quiz1Visible}
|
||||
zIndex={10002}
|
||||
title={QUIZ1_TITLE}
|
||||
options={QUIZ1_OPTIONS}
|
||||
correctAnswer={QUIZ1_CORRECT}
|
||||
onSubmit={handleQuiz1Submit}
|
||||
onWrongSelect={(val) => QUIZ1_ERROR_HINTS[val] || QUIZ1_FALLBACK_HINT}
|
||||
/>
|
||||
|
||||
{/* 视频2(全屏) */}
|
||||
{video2Visible && (
|
||||
<div className="fixed inset-0 z-10010 bg-black">
|
||||
<Video
|
||||
ref={videoRef2}
|
||||
src={VIDEO_2_SRC}
|
||||
className="w-full h-full"
|
||||
autoPlay={video2Playing}
|
||||
playsInline
|
||||
preload="auto"
|
||||
muted={!video2Playing}
|
||||
showSkipButton
|
||||
skipText="跳过"
|
||||
onEnded={handleVideo2Ended}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 对话2(叠加在视频2之上) */}
|
||||
<GuideSteps
|
||||
visible={guide2Visible}
|
||||
onVisibleChange={handleGuide2VisibleChange}
|
||||
currentStep={guide2Step}
|
||||
onStepChange={setGuide2Step}
|
||||
showMask={false}
|
||||
highlightSelectors={[]}
|
||||
zIndex={10011}
|
||||
>
|
||||
<GuideStepsItem
|
||||
speaker="student"
|
||||
audioSrc={getPublicPath(`${AUDIO_PREFIX}/mp3_chenyun_21.mp3`)}
|
||||
>
|
||||
那"两白一黑"战役是如何打赢的呢?
|
||||
</GuideStepsItem>
|
||||
<GuideStepsItem
|
||||
speaker="guide"
|
||||
audioSrc={getPublicPath(`${AUDIO_PREFIX}/mp3_chenyun_22.mp3`)}
|
||||
>
|
||||
“银元之战”的胜利并没有遏制住投机者的嚣张气焰,物价稳定仅十几天后,投机者就由银元投机转向“两白一黑”的投机,即:棉纱、大米和煤炭,引发了又一次全国性涨价狂潮。
|
||||
</GuideStepsItem>
|
||||
</GuideSteps>
|
||||
|
||||
{/* 题目2:拖拽 */}
|
||||
<DragQuizPanel
|
||||
visible={quiz2Visible}
|
||||
zIndex={10012}
|
||||
questionPrefix={QUIZ2_PREFIX}
|
||||
questionSuffix="。"
|
||||
options={QUIZ2_OPTIONS}
|
||||
blanks={QUIZ2_BLANKS}
|
||||
value={quiz2Value}
|
||||
error={quiz2Error}
|
||||
onChange={handleQuiz2Change}
|
||||
/>
|
||||
|
||||
{/* 成功提示(盖在视频/题目之上) */}
|
||||
{successVisible && (
|
||||
<div className="fixed inset-0" style={{ zIndex: 20000 }}>
|
||||
<SuccessAlert
|
||||
visible
|
||||
title="恭喜你, 选择正确!"
|
||||
content={successContent}
|
||||
onClose={handleSuccessDismiss}
|
||||
onContinue={handleSuccessDismiss}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChenyunPlace7
|
||||
Reference in new issue
Block a user