Commit non-media application and asset changes while leaving audio, video, and environment files out of version control. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
249 lines
7.9 KiB
TypeScript
249 lines
7.9 KiB
TypeScript
/**
|
|
* 银元之战主组件
|
|
* 整合银元之战的所有子组件:文件、线索、题目、引导提示
|
|
*/
|
|
import { useEffect } from 'react'
|
|
import { YinyuanFile } from './YinyuanFile'
|
|
import { YinyuanClues } from './YinyuanClues'
|
|
import { YinyuanQuizzes } from './YinyuanQuizzes'
|
|
import { YinyuanGuides } from './YinyuanGuides'
|
|
import { useYinyuanState } from './useYinyuanState'
|
|
import { usePuzzleAnimation } from '@/contexts/PuzzleAnimationContext'
|
|
import { usePuzzleStore } from '@/store/puzzleStore'
|
|
import { starName } from '../constants'
|
|
import type { FileType } from '../shared/types'
|
|
import type { ClueData } from '../clue/types'
|
|
|
|
export interface YinyuanBattleProps {
|
|
/** 当前展开的文件 */
|
|
expandedFile: FileType | null
|
|
/** 是否所有线索都已查看 */
|
|
isAllViewed: boolean
|
|
/** 线索状态 */
|
|
clueStates: Record<string, boolean>
|
|
/** 米棉之战是否已解决 */
|
|
isMimianSolved: boolean
|
|
/** 文件点击回调 */
|
|
onFileClick: () => void
|
|
/** 线索点击回调 */
|
|
onClueClick: (clue: ClueData, clueKey: string) => void
|
|
/** 播放视频回调 */
|
|
onPlayVideo: (fileType: FileType) => void
|
|
}
|
|
|
|
/**
|
|
* 银元之战主组件
|
|
* 管理银元之战的所有状态和逻辑
|
|
*/
|
|
export const YinyuanBattle = ({
|
|
expandedFile,
|
|
isAllViewed,
|
|
clueStates,
|
|
isMimianSolved,
|
|
onFileClick,
|
|
onClueClick,
|
|
onPlayVideo,
|
|
}: YinyuanBattleProps) => {
|
|
const state = useYinyuanState()
|
|
const { triggerPuzzleAnimation } = usePuzzleAnimation()
|
|
const { isPuzzleUnlocked } = usePuzzleStore()
|
|
|
|
// 当米棉之战解决后,隐藏银元之战的走势图
|
|
useEffect(() => {
|
|
if (isMimianSolved) {
|
|
state.setShowTrendChartIcon(false)
|
|
// 如果 guide2 正在显示,也关闭它
|
|
if (state.showGuide2) {
|
|
state.setShowGuide2(false)
|
|
}
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [isMimianSolved])
|
|
|
|
// 监听"前往解决"按钮出现的条件,显示第一个提示
|
|
useEffect(() => {
|
|
const shouldShowGuide1 =
|
|
isAllViewed &&
|
|
!state.isYinyuanSolved &&
|
|
!state.showQuiz1 &&
|
|
!state.showNarration2 &&
|
|
!state.showQuiz2 &&
|
|
!state.showSuccessAlert &&
|
|
!state.hasShownGuide1
|
|
|
|
if (shouldShowGuide1) {
|
|
// 延迟一下,确保按钮已经渲染
|
|
const timer = setTimeout(() => {
|
|
state.setShowGuide1(true)
|
|
state.setHasShownGuide1(true)
|
|
}, 300)
|
|
return () => clearTimeout(timer)
|
|
}
|
|
}, [
|
|
isAllViewed,
|
|
state.isYinyuanSolved,
|
|
state.showQuiz1,
|
|
state.showNarration2,
|
|
state.showQuiz2,
|
|
state.showSuccessAlert,
|
|
state.hasShownGuide1,
|
|
state.setShowGuide1,
|
|
state.setHasShownGuide1,
|
|
])
|
|
|
|
// 监听走势图图标出现的条件,显示第二个提示
|
|
// 注意:如果米棉之战已解决,则不显示走势图提示
|
|
useEffect(() => {
|
|
const shouldShowGuide2 =
|
|
state.isYinyuanSolved && state.showTrendChartIcon && !state.hasShownGuide2 && !isMimianSolved // 米棉之战解决后不再显示提示
|
|
|
|
if (shouldShowGuide2) {
|
|
// 延迟一下,确保走势图已经渲染
|
|
const timer = setTimeout(() => {
|
|
state.setShowGuide2(true)
|
|
state.setHasShownGuide2(true)
|
|
}, 300)
|
|
return () => clearTimeout(timer)
|
|
}
|
|
}, [
|
|
state.isYinyuanSolved,
|
|
state.showTrendChartIcon,
|
|
state.hasShownGuide2,
|
|
state.setShowGuide2,
|
|
state.setHasShownGuide2,
|
|
isMimianSolved,
|
|
])
|
|
|
|
// 监听走势图大图打开的条件,显示第三个提示
|
|
useEffect(() => {
|
|
const shouldShowGuide3 = state.showTrendChartDetail && !state.hasShownGuide3
|
|
|
|
if (shouldShowGuide3) {
|
|
// 延迟一下,确保大图已经打开
|
|
const timer = setTimeout(() => {
|
|
state.setShowGuide3(true)
|
|
state.setHasShownGuide3(true)
|
|
}, 300)
|
|
return () => clearTimeout(timer)
|
|
}
|
|
}, [
|
|
state.showTrendChartDetail,
|
|
state.hasShownGuide3,
|
|
state.setShowGuide3,
|
|
state.setHasShownGuide3,
|
|
])
|
|
|
|
// 处理多选题1提交
|
|
const handleQuiz1Submit = (values: string[], isCorrect: boolean) => {
|
|
if (isCorrect) {
|
|
// 关闭多选题1,显示旁白文字(图2)
|
|
state.setShowQuiz1(false)
|
|
state.setNarration2Text(
|
|
`六月五日,上海政府抛出十万银元,力图以银元制服银元,使价格回跌。全市举行了“反对银元投机,保障人民生活”的游行和宣传。上海市军委会主任陈毅在全市集会上警告投机奸商“赶快洗手不干,否则勿谓言之不预”。但这两手收效仍微。十万银元被投机商人一吸而空,六月七日银元每元的价格涨到一千八百元人民币。陈云同志判断:“单纯的经济手段已不足以震慑敌人,必须辅以坚定的行政与法律手段。”`
|
|
)
|
|
state.setShowNarration2(true)
|
|
}
|
|
}
|
|
|
|
// 处理旁白2关闭
|
|
const handleNarration2Close = () => {
|
|
state.setShowNarration2(false)
|
|
// 关闭旁白后显示多选题2
|
|
state.setShowQuiz2(true)
|
|
}
|
|
|
|
// 处理多选题2提交
|
|
const handleQuiz2Submit = (values: string[], isCorrect: boolean) => {
|
|
if (isCorrect) {
|
|
// 关闭多选题2,显示成功提示框
|
|
state.setShowQuiz2(false)
|
|
state.setShowSuccessAlert(true)
|
|
}
|
|
}
|
|
|
|
// 处理成功提示框继续
|
|
const handleSuccessAlertContinue = () => {
|
|
// 关闭聚光灯、标记银元之战为已解决、显示走势图
|
|
state.setIsYinyuanSolved(true)
|
|
state.setShowSuccessAlert(false)
|
|
|
|
// 检查碎片13是否已解锁,如果未解锁则触发动画
|
|
const pieceId = 13
|
|
if (!isPuzzleUnlocked(starName, pieceId)) {
|
|
triggerPuzzleAnimation(pieceId)
|
|
}
|
|
}
|
|
|
|
// 处理走势图点击
|
|
const handleTrendChartClick = () => {
|
|
// 关闭第三个提示框
|
|
state.setShowGuide3(false)
|
|
// 点击走势图:隐藏文件上的走势图图标,播放米棉之战视频
|
|
state.setShowTrendChartIcon(false)
|
|
state.setShowTrendChartDetail(false)
|
|
// 播放米棉之战视频
|
|
onPlayVideo('mimian')
|
|
}
|
|
|
|
// 处理走势图大图关闭
|
|
const handleTrendChartDetailClose = () => {
|
|
// 关闭第三个提示框
|
|
state.setShowGuide3(false)
|
|
state.setShowTrendChartDetail(false)
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{/* 文件组件 */}
|
|
<YinyuanFile
|
|
expandedFile={expandedFile}
|
|
isSolved={state.isYinyuanSolved}
|
|
showTrendChartIcon={state.showTrendChartIcon}
|
|
isAllViewed={isAllViewed}
|
|
showQuiz1={state.showQuiz1}
|
|
showNarration2={state.showNarration2}
|
|
showQuiz2={state.showQuiz2}
|
|
showSuccessAlert={state.showSuccessAlert}
|
|
onFileClick={onFileClick}
|
|
onTrendChartClick={() => {
|
|
state.setShowGuide2(false)
|
|
state.setShowTrendChartDetail(true)
|
|
}}
|
|
onSolveClick={() => {
|
|
state.setShowGuide1(false)
|
|
state.setShowQuiz1(true)
|
|
}}
|
|
/>
|
|
|
|
{/* 线索组件 */}
|
|
<YinyuanClues expandedFile={expandedFile} clueStates={clueStates} onClueClick={onClueClick} />
|
|
|
|
{/* 题目组件 */}
|
|
<YinyuanQuizzes
|
|
showQuiz1={state.showQuiz1}
|
|
showNarration2={state.showNarration2}
|
|
narration2Text={state.narration2Text}
|
|
showQuiz2={state.showQuiz2}
|
|
showSuccessAlert={state.showSuccessAlert}
|
|
onQuiz1Submit={handleQuiz1Submit}
|
|
onNarration2Close={handleNarration2Close}
|
|
onQuiz2Submit={handleQuiz2Submit}
|
|
onSuccessAlertContinue={handleSuccessAlertContinue}
|
|
/>
|
|
|
|
{/* 引导提示组件 */}
|
|
<YinyuanGuides
|
|
showGuide1={state.showGuide1}
|
|
showGuide2={state.showGuide2}
|
|
showGuide3={state.showGuide3}
|
|
showTrendChartDetail={state.showTrendChartDetail}
|
|
onGuide1Close={() => state.setShowGuide1(false)}
|
|
onGuide2Close={() => state.setShowGuide2(false)}
|
|
onGuide3Close={() => state.setShowGuide3(false)}
|
|
onTrendChartDetailClose={handleTrendChartDetailClose}
|
|
onTrendChartClick={handleTrendChartClick}
|
|
/>
|
|
</>
|
|
)
|
|
}
|