feat: 更新场景和组件,优化用户体验

- 更新多个场景中的引导对话,提升学习互动性。
- 修改组件以清理不必要的学习引导弹窗,简化用户流程。
- 调整文本内容,确保信息准确性和一致性。
- 添加背景音乐控制,增强沉浸式体验。
This commit is contained in:
zhongyidian committed 2026-01-13 18:48:10 +08:00
1 parent d226283e15
commit 71f607f6a3
46 files changed
+423 -372

No files matched your search

+23 -2
View File
@@ -372,6 +372,28 @@ const ExhibitOverlay = ({
// 指针抬起
const handlePointerUp = useCallback(
(e: React.PointerEvent<HTMLDivElement>) => {
const dragStart = dragStartRef.current;
// 检测是否是点击(移动距离很小)
if (dragStart && dragStart.pointerId === e.pointerId && onClick) {
// 计算从按下到抬起的移动距离
const dx = e.clientX - dragStart.startX;
const dy = e.clientY - dragStart.startY;
const distance = Math.hypot(dx, dy);
// 如果移动距离小于 5px,认为是点击而不是拖拽
if (distance < 5) {
// 检查 transform 是否改变,如果改变了说明是拖拽
const transformChanged =
Math.abs(transformRef.current.x - dragStart.startTransform.x) >
0.1 ||
Math.abs(transformRef.current.y - dragStart.startTransform.y) > 0.1;
if (!transformChanged) {
onClick();
}
}
}
// 释放指针捕获
if (containerRef.current) {
try {
@@ -405,7 +427,7 @@ const ExhibitOverlay = ({
setIsDragging(pointers.current.size > 0);
},
[]
[onClick]
);
// 双击重置
@@ -541,7 +563,6 @@ const ExhibitOverlay = ({
WebkitPerspective: "1000",
perspective: "1000",
}}
onClick={onClick}
>
<Image
src={exhibitSrc}
+2 -2
View File
@@ -21,11 +21,11 @@ const ClueContent = ({ clue }: ClueContentProps) => {
{clue.title}
</h2>
{typeof clue.content === "string" ? (
<div className="text-3xl leading-16 text-[#896a27] whitespace-pre-line text-center">
<div className="text-3xl leading-16 text-[#896a27] whitespace-pre-line">
{clue.content}
</div>
) : (
<div className="text-3xl leading-16 text-[#896a27] text-center">
<div className="text-3xl leading-16 text-[#896a27]">
{clue.content}
</div>
)}
+1 -1
View File
@@ -24,7 +24,7 @@ const DragQuizPanel = ({
>
<div className="relative w-[1728px] h-[972px] flex flex-col items-center pt-12 pb-14">
{/* 题干卡片 */}
<div className="w-[1600px] rounded-[32px] bg-black/90 px-20 py-12 shadow-[0_20px_60px_rgba(240,190,117,0.8)] border-4 border-[#d4c5a9]">
<div className="w-[1700px] rounded-[32px] bg-black/90 px-20 py-12 shadow-[0_20px_60px_rgba(240,190,117,0.8)] border-4 border-[#d4c5a9]">
<div className="text-[32px] leading-relaxed text-white">
{title && <div className="mb-4">{title}</div>}
<div>
+18 -2
View File
@@ -30,7 +30,7 @@ const LetterToChenyun = ({
我是____专业的学生。今天,我怀着崇敬又激动的心情,参观了位于上海市青浦区练塘镇的陈云纪念馆,学习了您“不唯上、不唯书、只唯____”的做事准则,还有“综合平衡”“人民至上”的经济思想。我深刻体会到,这些精神不仅是建设年代的智慧结晶,更是新时代指引我们前行的思想灯塔。
作为新时代大学生,我会在专业学习中____,像您当年练珠算、搞调查那样精益求精;未来无论从事什么工作,都要把服务群众____放在首位;面对困难时不退缩,像您当年稳定物价、推进实业那样,用____本领(结合所学专业)为国家发展贡献自己的力量!
作为新时代学生,我会在专业学习中____,像您当年练珠算、搞调查那样精益求精;未来无论从事什么工作,都要把服务群众、____放在首位;面对困难时不退缩,像您当年稳定物价、推进实业那样,用____本领(结合所学专业)为国家发展贡献自己的力量!
站在新时代的起点,我一定以____为志向,勤学苦练,传承精神,让您的务实担当在青春里扎根,让奋斗在建设祖国的实践中绽放光彩!`;
@@ -90,10 +90,26 @@ const LetterToChenyun = ({
<div className="text-[#4e402e] text-[26px] leading-relaxed">
{(() => {
let placeholderIndex = 0;
let foundNiHao = false;
return letterContent.split("\n").map((line, lineIndex) => {
// 检测是否已经找到"您好"行
if (line.includes("您好")) {
foundNiHao = true;
}
// "您好"行之后的非空行需要首行缩进
const needsIndent =
foundNiHao &&
line.trim() !== "" &&
!line.includes("您好");
const segments = line.split("____");
return (
<div key={lineIndex} className="mb-6">
<div
key={lineIndex}
className="mb-6"
style={needsIndent ? { textIndent: "2em" } : {}}
>
{segments.map((part, partIndex) => {
const isLast = partIndex === segments.length - 1;
if (isLast) {
+17 -1
View File
@@ -93,10 +93,26 @@ const LetterToHuangyanpei = ({
<div className="text-[#4e402e] text-[26px] leading-relaxed">
{(() => {
let placeholderIndex = 0;
let foundNiHao = false;
return letterContent.split("\n").map((line, lineIndex) => {
// 检测是否已经找到"您好"行
if (line.includes("您好")) {
foundNiHao = true;
}
// "您好"行之后的非空行需要首行缩进
const needsIndent =
foundNiHao &&
line.trim() !== "" &&
!line.includes("您好");
const segments = line.split("____");
return (
<div key={lineIndex} className="mb-0">
<div
key={lineIndex}
className="mb-0"
style={needsIndent ? { textIndent: "2em" } : {}}
>
{segments.map((part, partIndex) => {
const isLast = partIndex === segments.length - 1;
if (isLast) {
+17 -1
View File
@@ -91,10 +91,26 @@ const LetterToLuxun = ({
<div className="text-[#4e402e] text-[26px] leading-relaxed">
{(() => {
let placeholderIndex = 0;
let foundNiHao = false;
return letterContent.split("\n").map((line, lineIndex) => {
// 检测是否已经找到"您好"行
if (line.includes("您好")) {
foundNiHao = true;
}
// "您好"行之后的非空行需要首行缩进
const needsIndent =
foundNiHao &&
line.trim() !== "" &&
!line.includes("您好");
const segments = line.split("____");
return (
<div key={lineIndex} className="mb-2">
<div
key={lineIndex}
className="mb-2"
style={needsIndent ? { textIndent: "2em" } : {}}
>
{segments.map((part, partIndex) => {
const isLast = partIndex === segments.length - 1;
if (isLast) {
+17 -1
View File
@@ -91,10 +91,26 @@ const LetterToSunzhongshan = ({
<div className="text-[#4e402e] text-[26px] leading-relaxed">
{(() => {
let placeholderIndex = 0;
let foundNiHao = false;
return letterContent.split("\n").map((line, lineIndex) => {
// 检测是否已经找到"您好"行
if (line.includes("您好")) {
foundNiHao = true;
}
// "您好"行之后的非空行需要首行缩进
const needsIndent =
foundNiHao &&
line.trim() !== "" &&
!line.includes("您好");
const segments = line.split("____");
return (
<div key={lineIndex} className="mb-2">
<div
key={lineIndex}
className="mb-2"
style={needsIndent ? { textIndent: "2em" } : {}}
>
{segments.map((part, partIndex) => {
const isLast = partIndex === segments.length - 1;
if (isLast) {