更新依赖项及历史人物相关内容资源
- 更新 package.json 和 package-lock.json 中的依赖项 - 新增/更新陈云、黄炎培、鲁迅、孙中山的音频文件 - 新增场景和组件的图片资源 - 清理未使用的音频和图片文件 - 优化多个组件和页面的实现逻辑
This commit is contained in:
1 parent
b1d55b9464
commit
e0fa47d21a
629 files changed
+24390
-2991
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { SingleChoice } from '@/components'
|
||||
import SuccessAlert from '@/components/layout/alert/success-alert'
|
||||
import type { SingleChoiceQuizPanelProps } from './types'
|
||||
|
||||
/**
|
||||
@@ -38,20 +39,38 @@ const SingleChoiceQuizPanel = ({
|
||||
onWrongSelect,
|
||||
onError,
|
||||
disabled = false,
|
||||
showSuccessAlert = false,
|
||||
successAlertProps,
|
||||
onSuccessContinue,
|
||||
}: SingleChoiceQuizPanelProps) => {
|
||||
const [selectedValue, setSelectedValue] = useState<string>('')
|
||||
const [error, setError] = useState<string>('')
|
||||
const [successAlertVisible, setSuccessAlertVisible] = useState<boolean>(false)
|
||||
|
||||
// 当窗口关闭时,重置内部状态
|
||||
useEffect(() => {
|
||||
if (!visible) {
|
||||
setSelectedValue('')
|
||||
setError('')
|
||||
setSuccessAlertVisible(false)
|
||||
}
|
||||
}, [visible])
|
||||
|
||||
// 当成功弹窗显示时,隐藏题目面板,避免双层遮罩叠加
|
||||
const shouldRenderQuizPanel = visible && !successAlertVisible
|
||||
|
||||
if (!visible) return null
|
||||
|
||||
// 约定:显式开启,或传入 title/content 任一文案,即启用答对成功弹窗
|
||||
const hasSuccessAlertCopy =
|
||||
Boolean(successAlertProps?.title) || Boolean(successAlertProps?.content)
|
||||
const shouldShowSuccessAlert = showSuccessAlert || hasSuccessAlertCopy
|
||||
|
||||
const handleSuccessContinue = () => {
|
||||
setSuccessAlertVisible(false)
|
||||
onSuccessContinue?.()
|
||||
}
|
||||
|
||||
// 处理选项点击
|
||||
const handleOptionClick = (value: string) => {
|
||||
if (disabled) return
|
||||
@@ -69,6 +88,10 @@ const SingleChoiceQuizPanel = ({
|
||||
setSelectedValue('')
|
||||
setError('')
|
||||
onSubmit?.(value, true)
|
||||
|
||||
if (shouldShowSuccessAlert) {
|
||||
setSuccessAlertVisible(true)
|
||||
}
|
||||
} else {
|
||||
// 答题失败:清空状态,执行 onError,允许重新选择
|
||||
setSelectedValue('')
|
||||
@@ -86,45 +109,61 @@ const SingleChoiceQuizPanel = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-black/40" style={{ zIndex }}>
|
||||
<div className="relative w-[1728px] h-[972px] flex flex-col items-center justify-center">
|
||||
{/* 题干卡片 */}
|
||||
<div className="w-[1700px] rounded-[32px] bg-black px-20 py-8 shadow-[0_20px_60px_rgba(240,190,117,0.8)] border-4 border-[#d4c5a9]">
|
||||
<div className="text-[34px] leading-relaxed text-white">{title}</div>
|
||||
<>
|
||||
{shouldRenderQuizPanel && (
|
||||
<div
|
||||
className="fixed inset-0 flex items-center justify-center bg-black/40"
|
||||
style={{ zIndex }}
|
||||
>
|
||||
<div className="relative w-[1728px] h-[972px] flex flex-col items-center justify-center">
|
||||
{/* 题干卡片 */}
|
||||
<div className="w-[1700px] rounded-[32px] bg-black px-20 py-8 shadow-[0_20px_60px_rgba(240,190,117,0.8)] border-4 border-[#d4c5a9]">
|
||||
<div className="text-[34px] leading-relaxed text-white">{title}</div>
|
||||
|
||||
{/* 答案反馈 */}
|
||||
{error && <div className="mt-5 text-center text-[26px] text-[#fcbe53]">{error}</div>}
|
||||
</div>
|
||||
{/* 答案反馈 */}
|
||||
{error && <div className="mt-5 text-center text-[26px] text-[#fcbe53]">{error}</div>}
|
||||
</div>
|
||||
|
||||
{/* 选项区域 */}
|
||||
<div className="mt-16">
|
||||
<SingleChoice
|
||||
options={options}
|
||||
value={selectedValue}
|
||||
disabled={disabled}
|
||||
renderOption={(option, isSelected) => (
|
||||
<div
|
||||
key={option.value}
|
||||
className="mb-6 cursor-pointer"
|
||||
onClick={() => handleOptionClick(option.value)}
|
||||
>
|
||||
<div
|
||||
className={`w-[1500px] flex items-center p-4 text-[28px] leading-relaxed rounded-tr-[50px] rounded-bl-4xl transition-all duration-150 ${
|
||||
disabled ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer'
|
||||
} ${
|
||||
isSelected
|
||||
? 'bg-[#d4a574] text-[#5c3e2e]'
|
||||
: 'bg-[#d7b888] text-[#5c3e2e] hover:bg-gradient-to-r from-[#ddf3e1] to-[#fbdd97]'
|
||||
}`}
|
||||
>
|
||||
{option.label}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
{/* 选项区域 */}
|
||||
<div className="mt-16">
|
||||
<SingleChoice
|
||||
options={options}
|
||||
value={selectedValue}
|
||||
disabled={disabled}
|
||||
renderOption={(option, isSelected) => (
|
||||
<div
|
||||
key={option.value}
|
||||
className="mb-6 cursor-pointer"
|
||||
onClick={() => handleOptionClick(option.value)}
|
||||
>
|
||||
<div
|
||||
className={`w-[1500px] flex items-center p-4 text-[28px] leading-relaxed rounded-tr-[50px] rounded-bl-4xl transition-all duration-150 ${
|
||||
disabled ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer'
|
||||
} ${
|
||||
isSelected
|
||||
? 'bg-[#d4a574] text-[#5c3e2e]'
|
||||
: 'bg-[#d7b888] text-[#5c3e2e] hover:bg-linear-to-r from-[#ddf3e1] to-[#fbdd97]'
|
||||
}`}
|
||||
>
|
||||
{option.label}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldShowSuccessAlert && (
|
||||
<SuccessAlert
|
||||
{...successAlertProps}
|
||||
visible={successAlertVisible}
|
||||
onContinue={handleSuccessContinue}
|
||||
onClose={handleSuccessContinue}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user