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:
1 parent
5d00adc1a5
commit
76c67b492e
216 files changed
+12454
-13976
No files matched your search
@@ -7,49 +7,49 @@ import {
|
||||
MatchQuizPanel,
|
||||
Video,
|
||||
type VideoRef,
|
||||
} from "@/components";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { getBackgroundImage, getStaticImage, getPublicPath } from "@/lib/utils";
|
||||
import { useRef, useState } from "react";
|
||||
import Cursor from "@/components/cursor";
|
||||
import { useCursorController } from "@/hooks/useCursorController";
|
||||
import SuccessAlert from "@/components/layout/alert/success-alert";
|
||||
import ScaledPortal from "@/components/layout/ScaledPortal";
|
||||
} from '@/components'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { getBackgroundImage, getStaticImage, getPublicPath } from '@/lib/utils'
|
||||
import { useRef, useState } from 'react'
|
||||
import Cursor from '@/components/cursor'
|
||||
import { useCursorController } from '@/hooks/useCursorController'
|
||||
import SuccessAlert from '@/components/layout/alert/success-alert'
|
||||
import ScaledPortal from '@/components/layout/ScaledPortal'
|
||||
|
||||
// starName 固定为 zhangleping
|
||||
const starName = "zhangleping";
|
||||
const starName = 'zhangleping'
|
||||
|
||||
// 展品 ID 与资源路径映射
|
||||
const exhibitSrcMap: Record<1 | 2 | 3, string> = {
|
||||
1: "zhangleping/place2/张乐平场景2展品1",
|
||||
2: "zhangleping/place2/张乐平场景2展品2",
|
||||
3: "zhangleping/place2/张乐平场景2展品3",
|
||||
};
|
||||
1: 'zhangleping/place2/张乐平场景2展品1',
|
||||
2: 'zhangleping/place2/张乐平场景2展品2',
|
||||
3: 'zhangleping/place2/张乐平场景2展品3',
|
||||
}
|
||||
|
||||
// 阶段二:抗战画家(3 个光标)
|
||||
const ZhanglepingPlace2 = () => {
|
||||
const navigate = useNavigate();
|
||||
const navigate = useNavigate()
|
||||
const { moduleName } = useParams<{
|
||||
moduleName: string;
|
||||
}>();
|
||||
moduleName: string
|
||||
}>()
|
||||
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | 3 | null>(null);
|
||||
const [visited, setVisited] = useState<Set<1 | 2 | 3>>(() => new Set());
|
||||
const [activeExhibitId, setActiveExhibitId] = useState<1 | 2 | 3 | null>(null)
|
||||
const [visited, setVisited] = useState<Set<1 | 2 | 3>>(() => new Set())
|
||||
|
||||
const [guideVisible2, setGuideVisible2] = useState(false);
|
||||
const [guideStep2, setGuideStep2] = useState(0);
|
||||
const [guideVisible2, setGuideVisible2] = useState(false)
|
||||
const [guideStep2, setGuideStep2] = useState(0)
|
||||
|
||||
const [guideVisible3, setGuideVisible3] = useState(false);
|
||||
const [guideStep3, setGuideStep3] = useState(0);
|
||||
const [guideVisible3, setGuideVisible3] = useState(false)
|
||||
const [guideStep3, setGuideStep3] = useState(0)
|
||||
|
||||
// 展品3对话结束后的连线题
|
||||
const [quizVisible3, setQuizVisible3] = useState(false);
|
||||
const [quizPassed3, setQuizPassed3] = useState(false);
|
||||
const [successAlert3Visible, setSuccessAlert3Visible] = useState(false);
|
||||
const [quizVisible3, setQuizVisible3] = useState(false)
|
||||
const [quizPassed3, setQuizPassed3] = useState(false)
|
||||
const [successAlert3Visible, setSuccessAlert3Visible] = useState(false)
|
||||
|
||||
// 展品1:关闭后播放的视频
|
||||
const [showVideo1, setShowVideo1] = useState(false);
|
||||
const video1Ref = useRef<VideoRef>(null);
|
||||
const [showVideo1, setShowVideo1] = useState(false)
|
||||
const video1Ref = useRef<VideoRef>(null)
|
||||
|
||||
// Cursor 顺序控制:先学习展品3,再依次解锁展品2、展品1
|
||||
const { isEnabled } = useCursorController({
|
||||
@@ -59,31 +59,31 @@ const ZhanglepingPlace2 = () => {
|
||||
1: [2],
|
||||
},
|
||||
visited,
|
||||
});
|
||||
})
|
||||
|
||||
if (!moduleName) return null;
|
||||
if (!moduleName) return null
|
||||
|
||||
const total = 3;
|
||||
const progressCount = visited.size;
|
||||
const completed = progressCount >= total;
|
||||
const total = 3
|
||||
const progressCount = visited.size
|
||||
const completed = progressCount >= total
|
||||
const subtitle = completed
|
||||
? "搜索该阶段相关资料(已完成)"
|
||||
: `搜索该阶段相关资料(${progressCount}/${total})`;
|
||||
? '搜索该阶段相关资料(已完成)'
|
||||
: `搜索该阶段相关资料(${progressCount}/${total})`
|
||||
|
||||
const handleOpenExhibit = (id: 1 | 2 | 3) => {
|
||||
setActiveExhibitId(id);
|
||||
setActiveExhibitId(id)
|
||||
if (id === 1) {
|
||||
// 展品1仅展示大图,无引导对话
|
||||
} else if (id === 2) {
|
||||
setGuideVisible2(true);
|
||||
setGuideStep2(0);
|
||||
setGuideVisible2(true)
|
||||
setGuideStep2(0)
|
||||
} else {
|
||||
setGuideVisible3(true);
|
||||
setGuideStep3(0);
|
||||
setGuideVisible3(true)
|
||||
setGuideStep3(0)
|
||||
// 重新进入展品3时重置题目完成状态
|
||||
setQuizPassed3(false);
|
||||
setQuizPassed3(false)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -101,11 +101,11 @@ const ZhanglepingPlace2 = () => {
|
||||
|
||||
<Image
|
||||
className="absolute right-5 top-5"
|
||||
src={getStaticImage("components/离开")}
|
||||
src={getStaticImage('components/离开')}
|
||||
button
|
||||
onClick={() => {
|
||||
if (moduleName && starName) {
|
||||
navigate(`/${moduleName}/${starName}/home`);
|
||||
navigate(`/${moduleName}/${starName}/home`)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -139,10 +139,10 @@ const ZhanglepingPlace2 = () => {
|
||||
{completed && (
|
||||
<Image
|
||||
className="absolute bottom-0 right-0"
|
||||
src={getStaticImage("components/place/继续前进")}
|
||||
src={getStaticImage('components/place/继续前进')}
|
||||
button
|
||||
onClick={() => {
|
||||
navigate(`/${moduleName}/${starName}/place3`);
|
||||
navigate(`/${moduleName}/${starName}/place3`)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -173,10 +173,10 @@ const ZhanglepingPlace2 = () => {
|
||||
<GuideSteps
|
||||
visible={guideVisible3}
|
||||
onVisibleChange={(visible) => {
|
||||
setGuideVisible3(visible);
|
||||
setGuideVisible3(visible)
|
||||
// 对话结束后,弹出连线题(如未通过)
|
||||
if (!visible && !quizPassed3) {
|
||||
setQuizVisible3(true);
|
||||
setQuizVisible3(true)
|
||||
}
|
||||
}}
|
||||
currentStep={guideStep3}
|
||||
@@ -198,34 +198,34 @@ const ZhanglepingPlace2 = () => {
|
||||
|
||||
<ExhibitOverlay
|
||||
visible={activeExhibitId !== null}
|
||||
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ""}
|
||||
src={activeExhibitId ? exhibitSrcMap[activeExhibitId] : ''}
|
||||
onClose={() => {
|
||||
if (activeExhibitId !== null) {
|
||||
// 展品1:关闭后播放一段视频,视频结束再标记已访问
|
||||
if (activeExhibitId === 1) {
|
||||
setActiveExhibitId(null);
|
||||
setShowVideo1(true);
|
||||
return;
|
||||
setActiveExhibitId(null)
|
||||
setShowVideo1(true)
|
||||
return
|
||||
}
|
||||
|
||||
// 展品3:需在完成连线题后才标记为已访问
|
||||
if (activeExhibitId === 3) {
|
||||
if (quizPassed3) {
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(3);
|
||||
return next;
|
||||
});
|
||||
const next = new Set(prev)
|
||||
next.add(3)
|
||||
return next
|
||||
})
|
||||
}
|
||||
} else {
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(activeExhibitId);
|
||||
return next;
|
||||
});
|
||||
const next = new Set(prev)
|
||||
next.add(activeExhibitId)
|
||||
return next
|
||||
})
|
||||
}
|
||||
}
|
||||
setActiveExhibitId(null);
|
||||
setActiveExhibitId(null)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -233,21 +233,21 @@ const ZhanglepingPlace2 = () => {
|
||||
{showVideo1 && (
|
||||
<Video
|
||||
ref={video1Ref}
|
||||
src={getPublicPath("video/sunzhongshan/sunzhongshan_03.mp4")}
|
||||
src={getPublicPath('video/sunzhongshan/sunzhongshan_03.mp4')}
|
||||
className="fixed inset-0 z-20000"
|
||||
autoPlay
|
||||
playsInline
|
||||
showSkipButton
|
||||
onEnded={() => {
|
||||
setShowVideo1(false);
|
||||
setShowVideo1(false)
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(1);
|
||||
return next;
|
||||
});
|
||||
const next = new Set(prev)
|
||||
next.add(1)
|
||||
return next
|
||||
})
|
||||
}}
|
||||
onSkip={() => {
|
||||
setShowVideo1(false);
|
||||
setShowVideo1(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -259,51 +259,50 @@ const ZhanglepingPlace2 = () => {
|
||||
visible={quizVisible3}
|
||||
title="【连线】张乐平先生的画笔在不同历史时期发挥着不同作用,请你把对应的历史时期与当时先生画笔发挥的主要作用匹配起来吧!"
|
||||
leftItems={[
|
||||
{ id: "period1", label: "抗日战争" },
|
||||
{ id: "period2", label: "解放战争" },
|
||||
{ id: "period3", label: "新中国成立后" },
|
||||
{ id: 'period1', label: '抗日战争' },
|
||||
{ id: 'period2', label: '解放战争' },
|
||||
{ id: 'period3', label: '新中国成立后' },
|
||||
]}
|
||||
rightItems={[
|
||||
{ id: "role2", label: "镜子" },
|
||||
{ id: "role3", label: "园丁" },
|
||||
{ id: "role1", label: "刀枪" },
|
||||
{ id: 'role2', label: '镜子' },
|
||||
{ id: 'role3', label: '园丁' },
|
||||
{ id: 'role1', label: '刀枪' },
|
||||
]}
|
||||
correctMatches={[
|
||||
{ leftId: "period1", rightId: "role1" },
|
||||
{ leftId: "period2", rightId: "role2" },
|
||||
{ leftId: "period3", rightId: "role3" },
|
||||
{ leftId: 'period1', rightId: 'role1' },
|
||||
{ leftId: 'period2', rightId: 'role2' },
|
||||
{ leftId: 'period3', rightId: 'role3' },
|
||||
]}
|
||||
errorMessage={(matches) => {
|
||||
const getMatchByLeft = (leftId: string) =>
|
||||
matches.find((m) => m.leftId === leftId);
|
||||
const getMatchByLeft = (leftId: string) => matches.find((m) => m.leftId === leftId)
|
||||
|
||||
const match1 = getMatchByLeft("period1");
|
||||
if (match1 && match1.rightId !== "role1") {
|
||||
return "抗日战争时期,张乐平先生的画笔主要是揭露日寇暴行,似“刀枪”。请你再想想吧!";
|
||||
const match1 = getMatchByLeft('period1')
|
||||
if (match1 && match1.rightId !== 'role1') {
|
||||
return '抗日战争时期,张乐平先生的画笔主要是揭露日寇暴行,似“刀枪”。请你再想想吧!'
|
||||
}
|
||||
|
||||
const match2 = getMatchByLeft("period2");
|
||||
if (match2 && match2.rightId !== "role2") {
|
||||
return "解放战争时期,张乐平先生的画笔主要是映照社会现实,似“镜子”。请你再想想吧!";
|
||||
const match2 = getMatchByLeft('period2')
|
||||
if (match2 && match2.rightId !== 'role2') {
|
||||
return '解放战争时期,张乐平先生的画笔主要是映照社会现实,似“镜子”。请你再想想吧!'
|
||||
}
|
||||
|
||||
const match3 = getMatchByLeft("period3");
|
||||
if (match3 && match3.rightId !== "role3") {
|
||||
return "新中国成立后,张乐平先生的画笔主要为万千儿童种下真善美的种子,似“园丁”。请你再想想吧!";
|
||||
const match3 = getMatchByLeft('period3')
|
||||
if (match3 && match3.rightId !== 'role3') {
|
||||
return '新中国成立后,张乐平先生的画笔主要为万千儿童种下真善美的种子,似“园丁”。请你再想想吧!'
|
||||
}
|
||||
return "连线不太对,请你再仔细想一想吧!";
|
||||
return '连线不太对,请你再仔细想一想吧!'
|
||||
}}
|
||||
onSubmit={(_matches, isCorrect) => {
|
||||
if (isCorrect) {
|
||||
setQuizVisible3(false);
|
||||
setQuizPassed3(true);
|
||||
setSuccessAlert3Visible(true);
|
||||
setQuizVisible3(false)
|
||||
setQuizPassed3(true)
|
||||
setSuccessAlert3Visible(true)
|
||||
// 答题成功后标记展品3为已访问
|
||||
setVisited((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.add(3);
|
||||
return next;
|
||||
});
|
||||
const next = new Set(prev)
|
||||
next.add(3)
|
||||
return next
|
||||
})
|
||||
}
|
||||
}}
|
||||
zIndex={10000}
|
||||
@@ -312,15 +311,13 @@ const ZhanglepingPlace2 = () => {
|
||||
<SuccessAlert
|
||||
visible={successAlert3Visible}
|
||||
onContinue={() => {
|
||||
setSuccessAlert3Visible(false);
|
||||
setSuccessAlert3Visible(false)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</ScaledPortal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ZhanglepingPlace2;
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export default ZhanglepingPlace2
|
||||
Reference in new issue
Block a user