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:
zhongyidian committed 2026-03-05 13:50:47 +08:00
1 parent 5d00adc1a5
commit 76c67b492e
216 files changed
+12454 -13976

No files matched your search

@@ -2,33 +2,33 @@
* 银元之战主组件
* 整合银元之战的所有子组件:文件、线索、题目、引导提示
*/
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";
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;
expandedFile: FileType | null
/** 是否所有线索都已查看 */
isAllViewed: boolean;
isAllViewed: boolean
/** 线索状态 */
clueStates: Record<string, boolean>;
clueStates: Record<string, boolean>
/** 米棉之战是否已解决 */
isMimianSolved: boolean;
isMimianSolved: boolean
/** 文件点击回调 */
onFileClick: () => void;
onFileClick: () => void
/** 线索点击回调 */
onClueClick: (clue: ClueData, clueKey: string) => void;
onClueClick: (clue: ClueData, clueKey: string) => void
/** 播放视频回调 */
onPlayVideo: (fileType: FileType) => void;
onPlayVideo: (fileType: FileType) => void
}
/**
@@ -44,21 +44,21 @@ export const YinyuanBattle = ({
onClueClick,
onPlayVideo,
}: YinyuanBattleProps) => {
const state = useYinyuanState();
const { triggerPuzzleAnimation } = usePuzzleAnimation();
const { isPuzzleUnlocked } = usePuzzleStore();
const state = useYinyuanState()
const { triggerPuzzleAnimation } = usePuzzleAnimation()
const { isPuzzleUnlocked } = usePuzzleStore()
// 当米棉之战解决后,隐藏银元之战的走势图
useEffect(() => {
if (isMimianSolved) {
state.setShowTrendChartIcon(false);
state.setShowTrendChartIcon(false)
// 如果 guide2 正在显示,也关闭它
if (state.showGuide2) {
state.setShowGuide2(false);
state.setShowGuide2(false)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isMimianSolved]);
}, [isMimianSolved])
// 监听"前往解决"按钮出现的条件,显示第一个提示
useEffect(() => {
@@ -69,15 +69,15 @@ export const YinyuanBattle = ({
!state.showNarration2 &&
!state.showQuiz2 &&
!state.showSuccessAlert &&
!state.hasShownGuide1;
!state.hasShownGuide1
if (shouldShowGuide1) {
// 延迟一下,确保按钮已经渲染
const timer = setTimeout(() => {
state.setShowGuide1(true);
state.setHasShownGuide1(true);
}, 300);
return () => clearTimeout(timer);
state.setShowGuide1(true)
state.setHasShownGuide1(true)
}, 300)
return () => clearTimeout(timer)
}
}, [
isAllViewed,
@@ -89,24 +89,21 @@ export const YinyuanBattle = ({
state.hasShownGuide1,
state.setShowGuide1,
state.setHasShownGuide1,
]);
])
// 监听走势图图标出现的条件,显示第二个提示
// 注意:如果米棉之战已解决,则不显示走势图提示
useEffect(() => {
const shouldShowGuide2 =
state.isYinyuanSolved &&
state.showTrendChartIcon &&
!state.hasShownGuide2 &&
!isMimianSolved; // 米棉之战解决后不再显示提示
state.isYinyuanSolved && state.showTrendChartIcon && !state.hasShownGuide2 && !isMimianSolved // 米棉之战解决后不再显示提示
if (shouldShowGuide2) {
// 延迟一下,确保走势图已经渲染
const timer = setTimeout(() => {
state.setShowGuide2(true);
state.setHasShownGuide2(true);
}, 300);
return () => clearTimeout(timer);
state.setShowGuide2(true)
state.setHasShownGuide2(true)
}, 300)
return () => clearTimeout(timer)
}
}, [
state.isYinyuanSolved,
@@ -115,86 +112,85 @@ export const YinyuanBattle = ({
state.setShowGuide2,
state.setHasShownGuide2,
isMimianSolved,
]);
])
// 监听走势图大图打开的条件,显示第三个提示
useEffect(() => {
const shouldShowGuide3 =
state.showTrendChartDetail && !state.hasShownGuide3;
const shouldShowGuide3 = state.showTrendChartDetail && !state.hasShownGuide3
if (shouldShowGuide3) {
// 延迟一下,确保大图已经打开
const timer = setTimeout(() => {
state.setShowGuide3(true);
state.setHasShownGuide3(true);
}, 300);
return () => clearTimeout(timer);
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.setShowQuiz1(false)
state.setNarration2Text(
`六月五日,上海政府抛出十万银元,力图以银元制服银元,使价格回跌。全市举行了"反对银元投机,保障人民生活"的游行和宣传。上海市军委会主任陈毅在全市集会上警告投机奸商"赶快洗手不干,否则勿谓言之不预"。但这两手收效仍微。十万银元被投机商人一吸而空,六月七日银元每元的价格涨到一千八百元人民币。陈云同志判断:"单纯的经济手段已不足以震慑敌人,必须辅以坚定的行政与法律手段。"`
);
state.setShowNarration2(true);
)
state.setShowNarration2(true)
}
};
}
// 处理旁白2关闭
const handleNarration2Close = () => {
state.setShowNarration2(false);
state.setShowNarration2(false)
// 关闭旁白后显示多选题2
state.setShowQuiz2(true);
};
state.setShowQuiz2(true)
}
// 处理多选题2提交
const handleQuiz2Submit = (values: string[], isCorrect: boolean) => {
if (isCorrect) {
// 关闭多选题2,显示成功提示框
state.setShowQuiz2(false);
state.setShowSuccessAlert(true);
state.setShowQuiz2(false)
state.setShowSuccessAlert(true)
}
};
}
// 处理成功提示框继续
const handleSuccessAlertContinue = () => {
// 关闭聚光灯、标记银元之战为已解决、显示走势图
state.setIsYinyuanSolved(true);
state.setShowSuccessAlert(false);
state.setIsYinyuanSolved(true)
state.setShowSuccessAlert(false)
// 检查碎片13是否已解锁,如果未解锁则触发动画
const pieceId = 13;
const pieceId = 13
if (!isPuzzleUnlocked(starName, pieceId)) {
triggerPuzzleAnimation(pieceId);
triggerPuzzleAnimation(pieceId)
}
};
}
// 处理走势图点击
const handleTrendChartClick = () => {
// 关闭第三个提示框
state.setShowGuide3(false);
state.setShowGuide3(false)
// 点击走势图:隐藏文件上的走势图图标,播放米棉之战视频
state.setShowTrendChartIcon(false);
state.setShowTrendChartDetail(false);
state.setShowTrendChartIcon(false)
state.setShowTrendChartDetail(false)
// 播放米棉之战视频
onPlayVideo("mimian");
};
onPlayVideo('mimian')
}
// 处理走势图大图关闭
const handleTrendChartDetailClose = () => {
// 关闭第三个提示框
state.setShowGuide3(false);
state.setShowTrendChartDetail(false);
};
state.setShowGuide3(false)
state.setShowTrendChartDetail(false)
}
return (
<>
@@ -210,21 +206,17 @@ export const YinyuanBattle = ({
showSuccessAlert={state.showSuccessAlert}
onFileClick={onFileClick}
onTrendChartClick={() => {
state.setShowGuide2(false);
state.setShowTrendChartDetail(true);
state.setShowGuide2(false)
state.setShowTrendChartDetail(true)
}}
onSolveClick={() => {
state.setShowGuide1(false);
state.setShowQuiz1(true);
state.setShowGuide1(false)
state.setShowQuiz1(true)
}}
/>
{/* 线索组件 */}
<YinyuanClues
expandedFile={expandedFile}
clueStates={clueStates}
onClueClick={onClueClick}
/>
<YinyuanClues expandedFile={expandedFile} clueStates={clueStates} onClueClick={onClueClick} />
{/* 题目组件 */}
<YinyuanQuizzes
@@ -252,5 +244,5 @@ export const YinyuanBattle = ({
onTrendChartClick={handleTrendChartClick}
/>
</>
);
};
)
}
@@ -2,53 +2,47 @@
* 银元之战线索区域组件
* 包含线索1、线索2、电话的展示
*/
import { Image } from "@/components";
import { cn, getStaticImage } from "@/lib/utils";
import { ClueItem } from "../shared/ClueItem";
import type { FileType } from "../shared/types";
import type { ClueData } from "../clue/types";
import { YINYUAN_CLUE_DATA } from "../constants/yinyuan";
import { Image } from '@/components'
import { cn, getStaticImage } from '@/lib/utils'
import { ClueItem } from '../shared/ClueItem'
import type { FileType } from '../shared/types'
import type { ClueData } from '../clue/types'
import { YINYUAN_CLUE_DATA } from '../constants/yinyuan'
export interface YinyuanCluesProps {
/** 当前展开的文件 */
expandedFile: FileType | null;
expandedFile: FileType | null
/** 线索状态 */
clueStates: Record<string, boolean>;
clueStates: Record<string, boolean>
/** 线索点击回调 */
onClueClick: (clue: ClueData, clueKey: string) => void;
onClueClick: (clue: ClueData, clueKey: string) => void
}
/**
* 银元之战线索区域组件
* 显示线索1、线索2和电话
*/
export const YinyuanClues = ({
expandedFile,
clueStates,
onClueClick,
}: YinyuanCluesProps) => {
const isExpanded = expandedFile === "yinyuan";
export const YinyuanClues = ({ expandedFile, clueStates, onClueClick }: YinyuanCluesProps) => {
const isExpanded = expandedFile === 'yinyuan'
return (
<>
{/* 银元之战:线索1 */}
<div
className={cn([
"absolute left-190 bottom-8 transition-all duration-300 delay-100",
"hover:scale-105 hover:brightness-115",
isExpanded
? "opacity-100 translate-y-0"
: "opacity-0 translate-y-10 pointer-events-none",
'absolute left-190 bottom-8 transition-all duration-300 delay-100',
'hover:scale-105 hover:brightness-115',
isExpanded ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10 pointer-events-none',
])}
>
<ClueItem
clueKey="yinyuan-clue1"
imageSrc="chenyun/reflection/线索1"
isViewed={clueStates["yinyuan-clue1"] || false}
isViewed={clueStates['yinyuan-clue1'] || false}
onClick={() => {
const clue = YINYUAN_CLUE_DATA["yinyuan-clue1"];
const clue = YINYUAN_CLUE_DATA['yinyuan-clue1']
if (clue) {
onClueClick(clue, "yinyuan-clue1");
onClueClick(clue, 'yinyuan-clue1')
}
}}
/>
@@ -57,21 +51,19 @@ export const YinyuanClues = ({
{/* 银元之战:线索2 */}
<div
className={cn([
"absolute left-265 bottom-8 transition-all duration-300 delay-150",
"hover:scale-105 hover:brightness-115",
isExpanded
? "opacity-100 translate-y-0"
: "opacity-0 translate-y-10 pointer-events-none",
'absolute left-265 bottom-8 transition-all duration-300 delay-150',
'hover:scale-105 hover:brightness-115',
isExpanded ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10 pointer-events-none',
])}
>
<ClueItem
clueKey="yinyuan-clue2"
imageSrc="chenyun/reflection/线索2"
isViewed={clueStates["yinyuan-clue2"] || false}
isViewed={clueStates['yinyuan-clue2'] || false}
onClick={() => {
const clue = YINYUAN_CLUE_DATA["yinyuan-clue2"];
const clue = YINYUAN_CLUE_DATA['yinyuan-clue2']
if (clue) {
onClueClick(clue, "yinyuan-clue2");
onClueClick(clue, 'yinyuan-clue2')
}
}}
/>
@@ -81,34 +73,32 @@ export const YinyuanClues = ({
<div className="absolute right-50.5 -top-41">
<div className="relative">
{/* 响铃图标 */}
{!clueStates["yinyuan-phone"] && isExpanded && (
{!clueStates['yinyuan-phone'] && isExpanded && (
<Image
className="absolute left-[45%] -translate-x-1/2 -top-32 animate-bounce"
src={getStaticImage("chenyun/reflection/电话响")}
src={getStaticImage('chenyun/reflection/电话响')}
/>
)}
{/* 电话 */}
<div
className={cn([
isExpanded ? "cursor-pointer" : "pointer-events-none",
])}
className={cn([isExpanded ? 'cursor-pointer' : 'pointer-events-none'])}
onClick={() => {
if (!isExpanded) return;
const clue = YINYUAN_CLUE_DATA["yinyuan-phone"];
if (!isExpanded) return
const clue = YINYUAN_CLUE_DATA['yinyuan-phone']
if (clue) {
onClueClick(clue, "yinyuan-phone");
onClueClick(clue, 'yinyuan-phone')
}
}}
>
<Image src={getStaticImage("chenyun/reflection/电话")} button />
<Image src={getStaticImage('chenyun/reflection/电话')} button />
</div>
{/* 已接听标记 */}
{clueStates["yinyuan-phone"] && isExpanded && (
{clueStates['yinyuan-phone'] && isExpanded && (
<div className="absolute left-[40%] -translate-x-1/2 bottom-0">
<span
className={cn([
"text-[#ae6400] text-3xl font-bold",
"[text-shadow:_-4px_-4px_0_#ffffff,_4px_-4px_0_#ffffff,_-4px_4px_0_#ffffff,_4px_4px_0_#ffffff,_-5px_0_0_#ffffff,_5px_0_0_#ffffff,_0_-5px_0_#ffffff,_0_5px_0_#ffffff]",
'text-[#ae6400] text-3xl font-bold',
'[text-shadow:_-4px_-4px_0_#ffffff,_4px_-4px_0_#ffffff,_-4px_4px_0_#ffffff,_4px_4px_0_#ffffff,_-5px_0_0_#ffffff,_5px_0_0_#ffffff,_0_-5px_0_#ffffff,_0_5px_0_#ffffff]',
])}
>
已接听
@@ -118,5 +108,5 @@ export const YinyuanClues = ({
</div>
</div>
</>
);
};
)
}
@@ -2,33 +2,33 @@
* 银元之战文件组件
* 包含文件展示、走势图、前往解决按钮
*/
import { Image } from "@/components";
import { cn, getStaticImage } from "@/lib/utils";
import type { FileType } from "../shared/types";
import { Image } from '@/components'
import { cn, getStaticImage } from '@/lib/utils'
import type { FileType } from '../shared/types'
export interface YinyuanFileProps {
/** 当前展开的文件 */
expandedFile: FileType | null;
expandedFile: FileType | null
/** 是否已解决 */
isSolved: boolean;
isSolved: boolean
/** 是否显示走势图图标 */
showTrendChartIcon: boolean;
showTrendChartIcon: boolean
/** 是否所有线索都已查看 */
isAllViewed: boolean;
isAllViewed: boolean
/** 是否显示题目1 */
showQuiz1: boolean;
showQuiz1: boolean
/** 是否显示旁白2 */
showNarration2: boolean;
showNarration2: boolean
/** 是否显示题目2 */
showQuiz2: boolean;
showQuiz2: boolean
/** 是否显示成功提示框 */
showSuccessAlert: boolean;
showSuccessAlert: boolean
/** 文件点击回调 */
onFileClick: () => void;
onFileClick: () => void
/** 走势图点击回调 */
onTrendChartClick: () => void;
onTrendChartClick: () => void
/** 前往解决按钮点击回调 */
onSolveClick: () => void;
onSolveClick: () => void
}
/**
@@ -52,11 +52,11 @@ export const YinyuanFile = ({
<div
id="yinyuan-file"
className={cn([
"relative left-60 cursor-pointer transition-all duration-500",
expandedFile === null || expandedFile === "yinyuan"
? "opacity-100 scale-100"
: "opacity-0 scale-75 pointer-events-none",
expandedFile !== "yinyuan" && "hover:scale-105 hover:brightness-115",
'relative left-60 cursor-pointer transition-all duration-500',
expandedFile === null || expandedFile === 'yinyuan'
? 'opacity-100 scale-100'
: 'opacity-0 scale-75 pointer-events-none',
expandedFile !== 'yinyuan' && 'hover:scale-105 hover:brightness-115',
])}
onClick={onFileClick}
>
@@ -64,18 +64,18 @@ export const YinyuanFile = ({
className="transition-all duration-300"
src={
expandedFile
? getStaticImage("chenyun/reflection/文件1打开")
: getStaticImage("chenyun/reflection/文件1")
? getStaticImage('chenyun/reflection/文件1打开')
: getStaticImage('chenyun/reflection/文件1')
}
/>
<span
className={cn([
"absolute left-0 bottom-1/2 z-10",
"w-full bg-black/60 px-4 py-2 rounded-2xl text-center",
"text-white text-3xl font-bold tracking-widest",
'absolute left-0 bottom-1/2 z-10',
'w-full bg-black/60 px-4 py-2 rounded-2xl text-center',
'text-white text-3xl font-bold tracking-widest',
])}
>
{isSolved ? "01银元之战(已解决)" : "01银元之战(未解决)"}
{isSolved ? '01银元之战(已解决)' : '01银元之战(未解决)'}
</span>
{/* 走势图 - 银元之战解决后显示,点击后隐藏 */}
@@ -83,11 +83,11 @@ export const YinyuanFile = ({
<div
className="absolute -top-40 left-1/2 -translate-x-1/2 cursor-pointer transition-all duration-300 hover:scale-105 z-2"
onClick={(e) => {
e.stopPropagation();
onTrendChartClick();
e.stopPropagation()
onTrendChartClick()
}}
>
<Image src={getStaticImage("chenyun/reflection/走势图")} />
<Image src={getStaticImage('chenyun/reflection/走势图')} />
</div>
)}
@@ -101,17 +101,17 @@ export const YinyuanFile = ({
<div
className="absolute top-0 w-full h-full"
onClick={(e) => {
e.stopPropagation();
onSolveClick();
e.stopPropagation()
onSolveClick()
}}
>
<Image
className="translate-x-26 -translate-y-2"
src={getStaticImage("chenyun/reflection/点击前往解决")}
src={getStaticImage('chenyun/reflection/点击前往解决')}
button
/>
</div>
)}
</div>
);
};
)
}
@@ -2,28 +2,28 @@
* 银元之战引导提示组件
* 包含三个引导提示:前往解决按钮、走势图、走势图大图
*/
import { StudyGuideModal } from "@/components";
import { ExhibitOverlay } from "@/components";
import { StudyGuideModal } from '@/components'
import { ExhibitOverlay } from '@/components'
export interface YinyuanGuidesProps {
/** 是否显示引导提示1(前往解决按钮) */
showGuide1: boolean;
showGuide1: boolean
/** 是否显示引导提示2(走势图) */
showGuide2: boolean;
showGuide2: boolean
/** 是否显示引导提示3(走势图大图) */
showGuide3: boolean;
showGuide3: boolean
/** 是否显示走势图大图 */
showTrendChartDetail: boolean;
showTrendChartDetail: boolean
/** 引导提示1关闭回调 */
onGuide1Close: () => void;
onGuide1Close: () => void
/** 引导提示2关闭回调 */
onGuide2Close: () => void;
onGuide2Close: () => void
/** 引导提示3关闭回调 */
onGuide3Close: () => void;
onGuide3Close: () => void
/** 走势图大图关闭回调 */
onTrendChartDetailClose: () => void;
onTrendChartDetailClose: () => void
/** 走势图点击回调 */
onTrendChartClick: () => void;
onTrendChartClick: () => void
}
/**
@@ -82,5 +82,5 @@ export const YinyuanGuides = ({
onClose={onTrendChartDetailClose}
/>
</>
);
};
)
}
@@ -2,29 +2,29 @@
* 银元之战题目组件
* 包含多选题1、多选题2、旁白2
*/
import { Narration, MultipleChoiceQuizPanel } from "@/components";
import SuccessAlert from "@/components/layout/alert/success-alert";
import { getPublicPath } from "@/lib/utils";
import { Narration, MultipleChoiceQuizPanel } from '@/components'
import SuccessAlert from '@/components/layout/alert/success-alert'
import { getPublicPath } from '@/lib/utils'
export interface YinyuanQuizzesProps {
/** 是否显示多选题1 */
showQuiz1: boolean;
showQuiz1: boolean
/** 是否显示旁白2 */
showNarration2: boolean;
showNarration2: boolean
/** 旁白2文本 */
narration2Text: string;
narration2Text: string
/** 是否显示多选题2 */
showQuiz2: boolean;
showQuiz2: boolean
/** 是否显示成功提示框 */
showSuccessAlert: boolean;
showSuccessAlert: boolean
/** 多选题1提交回调 */
onQuiz1Submit: (values: string[], isCorrect: boolean) => void;
onQuiz1Submit: (values: string[], isCorrect: boolean) => void
/** 旁白2关闭回调 */
onNarration2Close: () => void;
onNarration2Close: () => void
/** 多选题2提交回调 */
onQuiz2Submit: (values: string[], isCorrect: boolean) => void;
onQuiz2Submit: (values: string[], isCorrect: boolean) => void
/** 成功提示框继续回调 */
onSuccessAlertContinue: () => void;
onSuccessAlertContinue: () => void
}
/**
@@ -49,11 +49,11 @@ export const YinyuanQuizzes = ({
visible={showQuiz1}
title="【多选】面对银元投机狂潮,你认为首要突破口是? "
options={[
{ value: "A", label: "A. 政治攻势(警告、约谈)" },
{ value: "B", label: "B. 经济手段(抛售银元,以银元打银元)" },
{ value: "C", label: "C. 舆论动员(宣传人民币信用,发动群众)" },
{ value: 'A', label: 'A. 政治攻势(警告、约谈)' },
{ value: 'B', label: 'B. 经济手段(抛售银元,以银元打银元)' },
{ value: 'C', label: 'C. 舆论动员(宣传人民币信用,发动群众)' },
]}
correctAnswer={["A", "B", "C"]}
correctAnswer={['A', 'B', 'C']}
errorMessage="单一措施效果有限,请尝试综合施策。"
minSelections={1}
maxSelections={3}
@@ -61,7 +61,7 @@ export const YinyuanQuizzes = ({
submitText="提交"
onSubmit={onQuiz1Submit}
onError={(error) => {
console.log("错误信息:", error);
console.log('错误信息:', error)
}}
/>
@@ -71,7 +71,7 @@ export const YinyuanQuizzes = ({
visible={showNarration2}
onClose={onNarration2Close}
enableAnimation={false}
audioSrc={getPublicPath("audio/chenyun/mp3_chenyun_31.mp3")}
audioSrc={getPublicPath('audio/chenyun/mp3_chenyun_31.mp3')}
/>
{/* 多选题2(图3)- 关闭旁白后显示 */}
@@ -79,11 +79,11 @@ export const YinyuanQuizzes = ({
visible={showQuiz2}
title="【多选】面对投机商的猖狂反扑,下一步应采取哪些决定性措施?"
options={[
{ value: "A", label: "A. 加大银元抛售量,耗尽投机资本" },
{ value: "B", label: "B. 查封投机核心场所,逮捕首要分子" },
{ value: "C", label: "C. 颁布法令,严禁银元计价流通" },
{ value: 'A', label: 'A. 加大银元抛售量,耗尽投机资本' },
{ value: 'B', label: 'B. 查封投机核心场所,逮捕首要分子' },
{ value: 'C', label: 'C. 颁布法令,严禁银元计价流通' },
]}
correctAnswer={["A", "B", "C"]}
correctAnswer={['A', 'B', 'C']}
errorMessage="单一措施效果有限,请尝试综合施策。"
minSelections={1}
maxSelections={3}
@@ -91,7 +91,7 @@ export const YinyuanQuizzes = ({
submitText="提交"
onSubmit={onQuiz2Submit}
onError={(error) => {
console.log("错误信息:", error);
console.log('错误信息:', error)
}}
/>
@@ -103,5 +103,5 @@ export const YinyuanQuizzes = ({
onContinue={onSuccessAlertContinue}
/>
</>
);
};
)
}
@@ -2,8 +2,8 @@
* 银元之战状态管理 Hook
* 管理银元之战相关的所有状态
*/
import { useState } from "react";
import { useChenyunStore } from "@/store/chenyunStore";
import { useState } from 'react'
import { useChenyunStore } from '@/store/chenyunStore'
/**
* 银元之战状态管理 Hook
@@ -11,41 +11,41 @@ import { useChenyunStore } from "@/store/chenyunStore";
*/
export const useYinyuanState = () => {
// 直接从 store 获取持久化的解决状态,不需要本地状态
const { isYinyuanSolved, setYinyuanSolved } = useChenyunStore();
const { isYinyuanSolved, setYinyuanSolved } = useChenyunStore()
// 更新解决状态时,直接更新 store
const handleSetIsYinyuanSolved = (solved: boolean) => {
setYinyuanSolved(solved);
};
setYinyuanSolved(solved)
}
// 多选题1相关状态
const [showQuiz1, setShowQuiz1] = useState(false);
const [showQuiz1, setShowQuiz1] = useState(false)
// 旁白文字状态(图2)
const [showNarration2, setShowNarration2] = useState(false);
const [narration2Text, setNarration2Text] = useState("");
const [showNarration2, setShowNarration2] = useState(false)
const [narration2Text, setNarration2Text] = useState('')
// 多选题2相关状态
const [showQuiz2, setShowQuiz2] = useState(false);
const [showQuiz2, setShowQuiz2] = useState(false)
// 成功提示框状态
const [showSuccessAlert, setShowSuccessAlert] = useState(false);
const [showSuccessAlert, setShowSuccessAlert] = useState(false)
// 走势图图标显示状态(控制文件上的走势图图标是否显示)
const [showTrendChartIcon, setShowTrendChartIcon] = useState(true);
const [showTrendChartIcon, setShowTrendChartIcon] = useState(true)
// 走势图大图显示状态
const [showTrendChartDetail, setShowTrendChartDetail] = useState(false);
const [showTrendChartDetail, setShowTrendChartDetail] = useState(false)
// 三个引导提示框状态
const [showGuide1, setShowGuide1] = useState(false); // 前往解决按钮出现后的提示
const [showGuide2, setShowGuide2] = useState(false); // 走势图出现后的提示
const [showGuide3, setShowGuide3] = useState(false); // 走势图大图打开后的提示
const [showGuide1, setShowGuide1] = useState(false) // 前往解决按钮出现后的提示
const [showGuide2, setShowGuide2] = useState(false) // 走势图出现后的提示
const [showGuide3, setShowGuide3] = useState(false) // 走势图大图打开后的提示
// 记录是否已经显示过这些提示(避免重复显示)
const [hasShownGuide1, setHasShownGuide1] = useState(false);
const [hasShownGuide2, setHasShownGuide2] = useState(false);
const [hasShownGuide3, setHasShownGuide3] = useState(false);
const [hasShownGuide1, setHasShownGuide1] = useState(false)
const [hasShownGuide2, setHasShownGuide2] = useState(false)
const [hasShownGuide3, setHasShownGuide3] = useState(false)
return {
// 题目相关状态
@@ -87,5 +87,5 @@ export const useYinyuanState = () => {
setHasShownGuide2,
hasShownGuide3,
setHasShownGuide3,
};
};
}
}