feat: 更新线索提示功能和图像资源,提升用户体验

- 在 ClueBookModal 组件中添加线索提示图像功能,增强互动性。
- 更新多个场景中的引导对话文本,确保信息准确性和一致性。
- 替换和更新多个图像资源,提升视觉内容的准确性。
- 调整完成提示弹窗文本,优化用户体验。
This commit is contained in:
zhongyidian committed 2026-01-18 12:29:04 +08:00
1 parent ac7bb420fd
commit 9184c41cc7
14 files changed
+103 -19

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 863 KiB

After

Width:  |  Height:  |  Size: 808 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+49 -2
View File
@@ -10,6 +10,7 @@ export interface ClueBookModalProps {
onClose: () => void;
getClueImage: (clueId: string) => string;
getClueDetailImage: (clueId: string) => string;
getClueHintImage?: (clueId: string) => string | null;
}
/**
@@ -21,8 +22,10 @@ export const ClueBookModal = ({
onClose,
getClueImage,
getClueDetailImage,
getClueHintImage,
}: ClueBookModalProps) => {
const [selectedClueId, setSelectedClueId] = useState<string | null>(null);
const [showClueHint, setShowClueHint] = useState(false);
// 默认选中第一个已收集的线索
useEffect(() => {
@@ -34,6 +37,18 @@ export const ClueBookModal = ({
}
}, [visible, clues, selectedClueId]);
// 当切换线索时,关闭线索提示
useEffect(() => {
setShowClueHint(false);
}, [selectedClueId]);
// 检查当前线索是否有提示
const hasClueHint = (clueId: string): boolean => {
if (!getClueHintImage) return false;
const hintImage = getClueHintImage(clueId);
return hintImage !== null && hintImage !== undefined;
};
if (!visible) return null;
const selectedClue = clues.find((c) => c.id === selectedClueId);
@@ -108,13 +123,45 @@ export const ClueBookModal = ({
{/* 右侧:线索详情或对话 */}
<div className="flex-1 px-10 flex items-center justify-center pt-58">
{selectedClue && selectedClue.collected ? (
<div className="w-full h-full flex flex-col items-center justify-center">
<div className="w-full h-full flex flex-col items-center justify-center relative">
{/* 显示线索详情图片 */}
<div className="relative w-full h-full text-center">
<div className="relative h-full text-center">
<Image
src={getClueDetailImage(selectedClue.id)}
className="h-full"
/>
{/* 线索提示描述(覆盖在详情图片上) */}
{showClueHint &&
hasClueHint(selectedClue.id) &&
getClueHintImage && (
<div className="absolute inset-0 z-20 flex items-center justify-center">
<div className="relative h-full">
<Image
src={getClueHintImage(selectedClue.id)!}
className="h-full"
/>
{/* 关闭按钮 */}
<Image
className="absolute top-0 right-0 z-30"
src={getStaticImage(`sunzhongshan/reflection/关闭`)}
button
onClick={() => setShowClueHint(false)}
/>
</div>
</div>
)}
{/* 线索提示按钮(右下角) */}
{hasClueHint(selectedClue.id) && (
<div className="absolute bottom-10 right-0 z-10">
<Image
src={getStaticImage(
`sunzhongshan/reflection/内置线索提示按钮`
)}
button
onClick={() => setShowClueHint(true)}
/>
</div>
)}
</div>
</div>
) : (
+7 -4
View File
@@ -237,6 +237,9 @@ const SunzhongshanReflectionScene1 = () => {
setShowCompleteGuide(false);
// 保存场景1完成状态
localStorage.setItem(`${starName}-reflection-scene1-completed`, "true");
if (moduleName && starName) {
navigate(`/${moduleName}/${starName}/reflection2`);
}
};
// 获取线索图片
@@ -446,7 +449,7 @@ const SunzhongshanReflectionScene1 = () => {
{/* 题目1:今天的日期是? */}
<SingleChoiceQuizPanel
visible={showQuiz1}
title="今天的日期是?"
title="【单选】今天的日期是?"
options={[
{ value: "A", label: "A.1919年5月5日" },
{ value: "B", label: "B.1921年5月5日" },
@@ -460,7 +463,7 @@ const SunzhongshanReflectionScene1 = () => {
{/* 题目2:今天的日记写什么呢? */}
<SingleChoiceQuizPanel
visible={showQuiz2}
title="今天的日记写什么呢?"
title="【单选】今天的日记写什么呢?"
options={[
{
value: "A",
@@ -482,7 +485,7 @@ const SunzhongshanReflectionScene1 = () => {
{/* 题目3:作为五四运动的见证者、参与者,你觉得中国革命有望通过怎样的方式实现? */}
<SingleChoiceQuizPanel
visible={showQuiz3}
title="作为五四运动的见证者、参与者,你觉得中国革命有望通过怎样的方式实现?"
title="【单选】作为五四运动的见证者、参与者,你觉得中国革命有望通过怎样的方式实现?"
options={[
{
value: "A",
@@ -502,7 +505,7 @@ const SunzhongshanReflectionScene1 = () => {
{/* 完成提示弹窗 */}
<EndingOverlay
visible={showCompleteGuide}
text={`"恭喜你完成场景一的探索!{\n}粤军总司令陈炯明与孙中山政见无法统一。1922年6月16日,陈炯明部将叶举率4000余人包围总统府,炮击孙中山住所粤秀楼。这一叛变行动使得北伐事业再次陷于停顿,第二次护法运动失败……{\n}请你走进场景二,继续探索吧!"`}
text={`恭喜你完成场景一的探索!\n粤军总司令陈炯明与孙中山政见无法统一。1922年6月16日,陈炯明部将叶举率4000余人包围总统府,炮击孙中山住所粤秀楼。这一叛变行动使得北伐事业再次陷于停顿,第二次护法运动失败……\n请你走进场景二,继续探索吧!`}
onContinue={handleCompleteGuideClose}
/>
</div>
+22 -7
View File
@@ -247,6 +247,9 @@ const SunzhongshanReflectionScene2 = () => {
setShowCompleteGuide(false);
// 保存场景2完成状态
localStorage.setItem(`${starName}-reflection-scene2-completed`, "true");
if (moduleName && starName) {
navigate(`/${moduleName}/${starName}/reflection3`);
}
};
// 获取线索图片
@@ -259,12 +262,22 @@ const SunzhongshanReflectionScene2 = () => {
const getClueDetailImage = (clueId: string) => {
const clueNumber = clueId.split("clue")[1];
// 线索3没有详情图片,返回线索图片
if (clueNumber === "3") {
return getStaticImage(`${sceneId}/线索${clueNumber}`);
}
// if (clueNumber === "4") {
// return getStaticImage(`${sceneId}/线索${clueNumber}`);
// }
return getStaticImage(`${sceneId}/线索${clueNumber}-详情`);
};
// 获取线索提示图片
const getClueHintImage = (clueId: string): string | null => {
const clueNumber = clueId.split("clue")[1];
// 场景2中线索1、2、3、4有提示
if (clueNumber && ["1", "2", "3", "4"].includes(clueNumber)) {
return getStaticImage(`${sceneId}/线索${clueNumber}-详情的详情`);
}
return null;
};
// 初始化线索(如果还没有)
useEffect(() => {
clueConfigs.forEach((clue) => {
@@ -405,6 +418,7 @@ const SunzhongshanReflectionScene2 = () => {
onClose={handleClueBookClose}
getClueImage={getClueImage}
getClueDetailImage={getClueDetailImage}
getClueHintImage={getClueHintImage}
/>
{/* 成功提示弹窗 */}
@@ -460,7 +474,7 @@ const SunzhongshanReflectionScene2 = () => {
{/* 题目1:当下无产阶级工人运动面对的敌人主要有哪些? */}
<SingleChoiceQuizPanel
visible={showQuiz1}
title="当下无产阶级工人运动面对的敌人主要有哪些?"
title="【单选】当下无产阶级工人运动面对的敌人主要有哪些?"
options={[
{ value: "A", label: "A: 地主和旧官僚" },
{ value: "B", label: "B: 军阀势力和帝国主义列强" },
@@ -474,7 +488,7 @@ const SunzhongshanReflectionScene2 = () => {
{/* 题目2:今天的日记写什么呢? */}
<SingleChoiceQuizPanel
visible={showQuiz2}
title="今天的日记写什么呢?"
title="【单选】今天的日记写什么呢?"
options={[
{
value: "A",
@@ -496,7 +510,7 @@ const SunzhongshanReflectionScene2 = () => {
{/* 题目3:当下无产阶级工人运动面临困境,你觉得谁可以成为工人们的朋友? */}
<SingleChoiceQuizPanel
visible={showQuiz3}
title="当下无产阶级工人运动面临困境,你觉得谁可以成为工人们的朋友?"
title="【单选】当下无产阶级工人运动面临困境,你觉得谁可以成为工人们的朋友?"
options={[
{
value: "A",
@@ -516,7 +530,8 @@ const SunzhongshanReflectionScene2 = () => {
{/* 完成提示弹窗 */}
<EndingOverlay
visible={showCompleteGuide}
text={`"恭喜你完成场景二的探索!{\n}1922年夏到1924年初,李大钊来到上海,在宣传革命思想的同时与孙中山进行了数次会面,为改组国民党和促成第一次国共合作作出了巨大贡献。{\n}1924年1月,中国国民党第一次全国代表大会在广州召开,孙中山重新解释了三民主义,事实上确立了联俄、联共、扶助农工三大政策。李大钊、毛泽东等10名共产党员当选为中国国民党第一届中央执行委员会委员或候补委员。国民党一大的召开标志着第一次国共合作的正式形成。{\n}请你走进场景三,继续探索吧!"`}
text={`恭喜你完成场景二的探索!\n1922年夏到1924年初,李大钊来到上海,在宣传革命思想的同时与孙中山进行了数次会面,为改组国民党和促成第一次国共合作作出了巨大贡献。\n1924年1月,中国国民党第一次全国代表大会在广州召开,孙中山重新解释了三民主义,事实上确立了联俄、联共、扶助农工三大政策。李大钊、毛泽东等10名共产党员当选为中国国民党第一届中央执行委员会委员或候补委员。国民党一大的召开标志着第一次国共合作的正式形成。\n请你走进场景三,继续探索吧!`}
animationSpeed={200}
onContinue={handleCompleteGuideClose}
/>
</div>
+25 -6
View File
@@ -148,7 +148,11 @@ const SunzhongshanReflectionScene3 = () => {
const handleBackpackClick = () => {
// 如果不在主场景,提示需要先获取线索1
if (!isMainScene) {
setErrorAlertContent(showCursor ? "该线索已收集" : "请先获取线索1");
setErrorAlertContent(
showCursor
? "请点击光标进入下一个场景,再点击背包吧!"
: "请先获取线索1"
);
setShowErrorAlert(true);
return;
}
@@ -255,6 +259,9 @@ const SunzhongshanReflectionScene3 = () => {
setShowCompleteGuide(false);
// 保存场景3完成状态
localStorage.setItem(`${starName}-reflection-scene3-completed`, "true");
if (moduleName && starName) {
navigate(`/${moduleName}/${starName}/home`);
}
};
// 处理 Cursor 点击 - 切换到主场景
@@ -275,6 +282,16 @@ const SunzhongshanReflectionScene3 = () => {
return getStaticImage(`${sceneId}/线索${clueNumber}-详情`);
};
// 获取线索提示图片
const getClueHintImage = (clueId: string): string | null => {
const clueNumber = clueId.split("clue")[1];
// 场景3中只有线索3有提示
if (clueNumber === "3") {
return getStaticImage(`${sceneId}/线索${clueNumber}-详情的详情`);
}
return null;
};
// 初始化线索(如果还没有)
useEffect(() => {
clueConfigs.forEach((clue) => {
@@ -447,6 +464,7 @@ const SunzhongshanReflectionScene3 = () => {
onClose={handleClueBookClose}
getClueImage={getClueImage}
getClueDetailImage={getClueDetailImage}
getClueHintImage={getClueHintImage}
/>
{/* 成功提示弹窗 */}
@@ -510,7 +528,7 @@ const SunzhongshanReflectionScene3 = () => {
{/* 题目1:冯玉祥发动"北京政变"后邀请孙中山北上共商国是,各界对此事的看法如何? */}
<SingleChoiceQuizPanel
visible={showQuiz1}
title='冯玉祥发动"北京政变"后邀请孙中山北上共商国是,各界对此事的看法如何?'
title='【单选】冯玉祥发动"北京政变"后邀请孙中山北上共商国是,各界对此事的看法如何?'
options={[
{ value: "A", label: "A.意见高度一致,认为和平统一已经十拿九稳" },
{ value: "B", label: "B.期待、信任为主,亦有担忧和谨慎的探讨" },
@@ -524,7 +542,7 @@ const SunzhongshanReflectionScene3 = () => {
{/* 题目2:毅然北上赴会的孙中山先生,为争取国家和平统一作出了哪些努力? */}
<SingleChoiceQuizPanel
visible={showQuiz2}
title="毅然北上赴会的孙中山先生,为争取国家和平统一作出了哪些努力?"
title="【单选】毅然北上赴会的孙中山先生,为争取国家和平统一作出了哪些努力?"
options={[
{
value: "A",
@@ -545,7 +563,7 @@ const SunzhongshanReflectionScene3 = () => {
{/* 题目3:今天的日记写什么呢? */}
<SingleChoiceQuizPanel
visible={showQuiz3}
title="今天的日记写什么呢?"
title="【单选】今天的日记写什么呢?"
options={[
{
value: "A",
@@ -558,7 +576,7 @@ const SunzhongshanReflectionScene3 = () => {
'B.孙中山先生抵沪,来自百年后的我站在欢迎的人群中,终于亲眼见到了这位伟大的革命先行者。1924年的秋天,冯玉祥北京政变为国家的和平统一带来一线契机。回望历史,我们知道,这在中国近代的民族民主革命路途上,不过是一个插曲。但对于孙中山先生而言,抱病北上,不遗余力地宣传反帝反封建主张,几乎成为他为国家前途命运而作的最后争取。他在迷途中坚守,在变局中担当,穷极一生从未停下脚步。伟大复兴的新征程上,我们早已摆脱了屈辱与苦难,向着国家富强的光明前景、人民幸福的美好未来进发。先生"振兴中华"的呐喊犹在耳畔,"天下为公"的初心始终滚烫。今天我们所能做的,便是铭记这份坚守与担当,做跨越百年的追梦路上最坚定的继承者与前行者。',
},
]}
correctAnswer="A"
correctAnswer={undefined}
errorMessage=""
onSubmit={handleQuiz3Submit}
zIndex={10001}
@@ -567,7 +585,8 @@ const SunzhongshanReflectionScene3 = () => {
{/* 完成提示弹窗 */}
<EndingOverlay
visible={showCompleteGuide}
text={`"辛亥革命拉开了中国完全意义上的近代民族民主革命的序幕。北洋军阀首领袁世凯窃取革命成果后,各地军阀势力对内割据混战,对外出卖国家利益,在政治上谋求专制和独裁,俨然成为民族独立、民主政治、民生幸福之路上的头号绊脚石。{\n}为了改变这一时期的困局,孙中山尝试过高举护法旗帜,两度领导护法运动;与新生的中国共产党展开合作,与无产阶级工农群众共建起统一战线;为了团结一切可以团结的力量,调动一切可以调动的因素,在生命最后的日子里抱病北上,一路不遗余力地向社会各界宣传反帝反封建主张。他经历了太多挫折,却始终以'行'求'知'。"`}
text={`辛亥革命拉开了中国完全意义上的近代民族民主革命的序幕。北洋军阀首领袁世凯窃取革命成果后,各地军阀势力对内割据混战,对外出卖国家利益,在政治上谋求专制和独裁,俨然成为民族独立、民主政治、民生幸福之路上的头号绊脚石。\n为了改变这一时期的困局,孙中山尝试过高举护法旗帜,两度领导护法运动;与新生的中国共产党展开合作,与无产阶级工农群众共建起统一战线;为了团结一切可以团结的力量,调动一切可以调动的因素,在生命最后的日子里抱病北上,一路不遗余力地向社会各界宣传反帝反封建主张。他经历了太多挫折,却始终以'行'求'知'。`}
animationSpeed={200}
onContinue={handleCompleteGuideClose}
/>
</div>