优化答题界面布局和视觉设计
主要更改: - 头部布局优化:将返回按钮、标题、统计信息整合到一行,使用毛玻璃卡片样式 - 统计信息重构:将正确/错误次数移到头部右侧,采用紧凑的标签+数值设计 - 进度条优化:使用卡片包裹,添加毛玻璃效果,简化显示内容,只保留进度条 - 响应式优化:移动端自动调整为多行布局,平板和PC端保持横向一行显示 - 视觉统一:所有组件使用一致的毛玻璃风格和 macOS 设计语言 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
c0a280132c
commit
3c97985af0
@ -1,8 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Progress, Space, Typography } from 'antd'
|
import { Progress, Card } from 'antd'
|
||||||
import { CheckOutlined, CloseOutlined } from '@ant-design/icons'
|
|
||||||
|
|
||||||
const { Text } = Typography
|
|
||||||
|
|
||||||
interface QuestionProgressProps {
|
interface QuestionProgressProps {
|
||||||
currentIndex: number
|
currentIndex: number
|
||||||
@ -14,33 +11,40 @@ interface QuestionProgressProps {
|
|||||||
const QuestionProgress: React.FC<QuestionProgressProps> = ({
|
const QuestionProgress: React.FC<QuestionProgressProps> = ({
|
||||||
currentIndex,
|
currentIndex,
|
||||||
totalQuestions,
|
totalQuestions,
|
||||||
correctCount,
|
|
||||||
wrongCount,
|
|
||||||
}) => {
|
}) => {
|
||||||
if (totalQuestions === 0) return null
|
if (totalQuestions === 0) return null
|
||||||
|
|
||||||
|
const percent = Math.round(((currentIndex + 1) / totalQuestions) * 100)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ marginBottom: 20 }}>
|
<Card
|
||||||
|
style={{
|
||||||
|
marginBottom: 20,
|
||||||
|
borderRadius: 16,
|
||||||
|
background: 'rgba(255, 255, 255, 0.9)',
|
||||||
|
backdropFilter: 'blur(30px) saturate(180%)',
|
||||||
|
WebkitBackdropFilter: 'blur(30px) saturate(180%)',
|
||||||
|
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.05), 0 1px 4px rgba(0, 0, 0, 0.03), 0 0 0 1px rgba(0, 0, 0, 0.03)',
|
||||||
|
border: '0.5px solid rgba(0, 0, 0, 0.04)',
|
||||||
|
}}
|
||||||
|
bodyStyle={{ padding: '16px 20px' }}
|
||||||
|
>
|
||||||
<Progress
|
<Progress
|
||||||
percent={Math.round(((currentIndex + 1) / totalQuestions) * 100)}
|
percent={percent}
|
||||||
status="active"
|
status="active"
|
||||||
strokeColor={{
|
strokeColor={{
|
||||||
'0%': '#108ee9',
|
'0%': '#007aff',
|
||||||
'100%': '#87d068',
|
'100%': '#52c41a',
|
||||||
}}
|
}}
|
||||||
|
trailColor="rgba(0, 0, 0, 0.06)"
|
||||||
|
strokeWidth={12}
|
||||||
format={() => `${currentIndex + 1} / ${totalQuestions}`}
|
format={() => `${currentIndex + 1} / ${totalQuestions}`}
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div style={{ marginTop: 8, textAlign: 'center' }}>
|
</Card>
|
||||||
<Space size="large">
|
|
||||||
<Text>
|
|
||||||
<CheckOutlined style={{ color: '#52c41a' }} /> 正确:{correctCount}
|
|
||||||
</Text>
|
|
||||||
<Text>
|
|
||||||
<CloseOutlined style={{ color: '#ff4d4f' }} /> 错误:{wrongCount}
|
|
||||||
</Text>
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,12 +14,63 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
backdrop-filter: blur(30px) saturate(180%);
|
||||||
|
-webkit-backdrop-filter: blur(30px) saturate(180%);
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow:
|
||||||
|
0 2px 12px rgba(0, 0, 0, 0.05),
|
||||||
|
0 1px 4px rgba(0, 0, 0, 0.03),
|
||||||
|
0 0 0 1px rgba(0, 0, 0, 0.03);
|
||||||
|
border: 0.5px solid rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
.backButton {
|
||||||
|
color: #007aff;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 4px 12px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #0051d5;
|
||||||
|
background: rgba(0, 122, 255, 0.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: #1d1d1f !important;
|
color: #1d1d1f !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
font-size: 18px !important;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statsGroup {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statItem {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statLabel {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #86868b;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statValue {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,12 +126,41 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
flex-direction: column;
|
flex-wrap: wrap;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
align-items: flex-start;
|
padding: 12px 16px;
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
|
.backButton {
|
||||||
|
order: 1;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 20px !important;
|
order: 2;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statsGroup {
|
||||||
|
order: 3;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statItem {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statLabel {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statValue {
|
||||||
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,13 +181,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 响应式设计 - 平板
|
||||||
|
@media (min-width: 769px) and (max-width: 1024px) {
|
||||||
|
.container {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
.title {
|
||||||
|
font-size: 20px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 响应式设计 - PC端
|
// 响应式设计 - PC端
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 1025px) {
|
||||||
.container {
|
.container {
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
margin-bottom: 32px;
|
margin-bottom: 24px;
|
||||||
|
padding: 18px 24px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 22px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statValue {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -253,12 +253,27 @@ const QuestionPage: React.FC = () => {
|
|||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
{/* 头部 */}
|
{/* 头部 */}
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<Button icon={<ArrowLeftOutlined />} onClick={() => navigate("/")}>
|
<Button
|
||||||
返回首页
|
icon={<ArrowLeftOutlined />}
|
||||||
|
onClick={() => navigate("/")}
|
||||||
|
className={styles.backButton}
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
返回
|
||||||
</Button>
|
</Button>
|
||||||
<Title level={3} className={styles.title}>
|
<Title level={3} className={styles.title}>
|
||||||
AnKao 刷题
|
AnKao 刷题
|
||||||
</Title>
|
</Title>
|
||||||
|
<div className={styles.statsGroup}>
|
||||||
|
<div className={styles.statItem}>
|
||||||
|
<span className={styles.statLabel}>正确</span>
|
||||||
|
<span className={styles.statValue} style={{ color: '#52c41a' }}>{correctCount}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.statItem}>
|
||||||
|
<span className={styles.statLabel}>错误</span>
|
||||||
|
<span className={styles.statValue} style={{ color: '#ff4d4f' }}>{wrongCount}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 进度条 */}
|
{/* 进度条 */}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user