优化 Dashboard 布局:实现炫酷徽章、水平滚动AI建议和玻璃拟态效果

This commit is contained in:
gao
2025-11-05 21:29:33 +08:00
parent 8991f63f52
commit f72c3f17d2
+361 -64
View File
@@ -36,29 +36,8 @@
</div>
</header>
<!-- 学习概览主卡片 -->
<div class="main-overview-card">
<div class="overview-header">
<div class="level-progress-main">
<div class="level-badge">
<span class="level-text">Lv.{{ userLevel }} 学习达人</span>
<div class="level-fire">🔥</div>
</div>
<div class="progress-info">
<div class="progress-bar-main">
<div class="progress-fill-animated" :style="{ width: userProgress.rankPercent + '%' }"></div>
</div>
<span class="progress-text">排名超越 {{ userProgress.rankPercent }}% 同龄用户</span>
</div>
</div>
<div class="overview-actions">
<button @click="showDetailedStats" class="action-btn primary">
📊 详细分析
</button>
</div>
</div>
<!-- 核心统计数据 -->
<!-- 学习概览卡(轻量化) -->
<div class="overview-card">
<div class="core-stats">
<div class="stat-item">
<div class="stat-icon">⏱️</div>
@@ -88,20 +67,18 @@
</div>
</div>
<!-- 学习小目标 Widget -->
<div class="learning-goals">
<!-- 今日学习目标进度 -->
<div class="goal-progress-container">
<div class="goal-header">
<span class="goal-icon">🌟</span>
<span class="goal-title">今日学习目标</span>
<span class="goal-title">今日目标</span>
</div>
<div class="goal-content">
<p class="goal-text">{{ getTodayGoal() }}</p>
<div class="goal-progress">
<div class="goal-bar">
<div class="goal-fill" :style="{ width: getGoalProgress() + '%' }"></div>
</div>
<span class="goal-percentage">{{ getGoalProgress() }}%</span>
<p class="goal-text">{{ getTodayGoal() }}</p>
<div class="goal-progress">
<div class="goal-bar">
<div class="goal-fill" :style="{ width: getGoalProgress() + '%' }"></div>
</div>
<span class="goal-percentage">{{ getGoalProgress() }}%</span>
</div>
</div>
</div>
@@ -190,22 +167,29 @@
<span v-else>⏳</span>
</button>
</div>
<div class="suggestions-grid">
<div v-for="suggestion in aiSuggestions" :key="suggestion.id" class="suggestion-card" @click="applySuggestion(suggestion)">
<div class="suggestion-icon">{{ suggestion.icon }}</div>
<div class="suggestion-content">
<h4 class="suggestion-title">{{ suggestion.title }}</h4>
<p class="suggestion-description">{{ suggestion.description }}</p>
<div class="suggestion-meta">
<span class="meta-item">{{ suggestion.duration }}</span>
<span class="meta-item">{{ suggestion.difficulty }}</span>
<!-- 水平滚动的AI建议卡片 -->
<div class="suggestions-carousel">
<div class="suggestions-track">
<div v-for="suggestion in aiSuggestions" :key="suggestion.id" class="suggestion-card" @click="applySuggestion(suggestion)">
<div class="suggestion-icon">{{ suggestion.icon }}</div>
<div class="suggestion-content">
<h4 class="suggestion-title">{{ suggestion.title }}</h4>
<p class="suggestion-description">{{ suggestion.description }}</p>
<div class="suggestion-meta">
<span class="meta-item">{{ suggestion.duration }}</span>
<span class="meta-item">{{ suggestion.difficulty }}</span>
</div>
</div>
<div class="suggestion-action">
<span class="action-arrow">→</span>
</div>
</div>
<div class="suggestion-action">
<span class="action-arrow">→</span>
</div>
</div>
</div>
<!-- 悬浮AI按钮 -->
<button class="ai-more-btn" @click="showDetailedStats">
<span>🤖</span>
</button>
</div>
</div>
@@ -738,7 +722,97 @@ window.addEventListener('resize', () => {
font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
}
/* 背景层 - 深浅分层护眼配色 */
/* 布局比例调整 */
.dashboard-container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
position: relative;
z-index: 1;
}
/* 响应式优化 */
@media (max-width: 1024px) {
.data-cards-grid {
grid-template-columns: 1fr;
}
.data-card.large {
grid-column: span 1;
}
.suggestions-track {
padding-left: 10px;
padding-right: 60px; /* 为AI按钮留出空间 */
}
}
@media (max-width: 768px) {
.dashboard-container {
padding: 16px;
}
.top-header {
flex-direction: column;
gap: 16px;
padding: 20px;
}
.core-stats {
flex-direction: column;
gap: 12px;
}
.stat-divider {
width: 100%;
height: 1px;
}
.overview-header {
flex-direction: column;
gap: 16px;
align-items: flex-start;
}
.ai-assistant-fab {
width: 50px;
height: 50px;
bottom: 20px;
right: 20px;
}
.ai-fab-icon {
font-size: 20px;
}
.suggestions-track {
padding-left: 10px;
padding-right: 60px;
}
}
@media (max-width: 480px) {
.section-header {
flex-direction: column;
gap: 12px;
align-items: flex-start;
}
.overview-card {
padding: 16px;
}
.data-card {
padding: 16px;
}
.suggestion-card {
min-width: 280px;
padding: 16px;
}
}
/* 背景层 - 优化渐变 */
.bg-gradient {
position: fixed;
top: 0;
@@ -746,15 +820,24 @@ window.addEventListener('resize', () => {
width: 100%;
height: 100%;
background: linear-gradient(135deg,
#1e293b 0%,
#334155 25%,
#475569 50%,
#334155 75%,
#1e293b 100%
#0f172a 0%,
#1e293b 25%,
#334155 50%,
#1e293b 75%,
#0f172a 100%
);
z-index: -2;
}
/* 玻璃拟态通用样式 */
.glass-effect {
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 16px;
}
.floating-orbs {
position: fixed;
width: 100%;
@@ -861,9 +944,10 @@ window.addEventListener('resize', () => {
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
background: rgba(30, 41, 59, 0.8);
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
-webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 20px;
padding: 24px 32px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
@@ -992,6 +1076,39 @@ window.addEventListener('resize', () => {
60% { transform: translateY(-5px); }
}
.level-badge {
background: linear-gradient(135deg, #00e0ff, #45ff9d);
color: #0f172a;
font-weight: 600;
padding: 6px 14px;
border-radius: 20px;
box-shadow: 0 0 12px rgba(0, 255, 204, 0.6);
display: inline-flex;
align-items: center;
gap: 6px;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 8px rgba(0,255,204,0.5); }
50% { box-shadow: 0 0 16px rgba(0,255,204,0.9); }
}
.badge-glow {
background: linear-gradient(135deg, #00e0ff, #45ff9d);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 700;
}
/* 卡片玻璃拟态效果 */
.data-card {
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.progress-info {
display: flex;
align-items: center;
@@ -1166,9 +1283,9 @@ window.addEventListener('resize', () => {
min-width: 40px;
}
/* 数据卡片区 */
/* 数据卡片区 - 提升视觉核心地位 */
.data-cards-section {
margin-bottom: 32px;
margin: 24px 0 32px;
}
.section-header {
@@ -1183,12 +1300,15 @@ window.addEventListener('resize', () => {
font-size: 24px;
font-weight: 700;
color: #ECEFF4;
display: flex;
align-items: center;
gap: 10px;
}
.filter-select {
background: rgba(30, 41, 59, 0.8);
background: rgba(255, 255, 255, 0.08);
color: #ECEFF4;
border: 1px solid rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.12);
padding: 8px 16px;
border-radius: 8px;
font-size: 14px;
@@ -1201,9 +1321,10 @@ window.addEventListener('resize', () => {
}
.data-card {
background: rgba(30, 41, 59, 0.6);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 20px;
padding: 24px;
transition: all 0.3s ease;
@@ -1211,7 +1332,7 @@ window.addEventListener('resize', () => {
}
.data-card:hover {
background: rgba(30, 41, 59, 0.8);
background: rgba(255, 255, 255, 0.12);
transform: translateY(-4px);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.3);
}
@@ -1220,6 +1341,137 @@ window.addEventListener('resize', () => {
grid-column: span 2;
}
/* 优化后的学习概览卡片 */
.overview-card {
background: rgba(30, 41, 59, 0.6);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 24px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.2);
}
.core-stats {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20px;
margin-bottom: 24px;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 16px;
background: rgba(255, 255, 255, 0.05);
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.08);
transition: all 0.3s ease;
}
.stat-item:hover {
background: rgba(255, 255, 255, 0.08);
transform: translateY(-2px);
}
.stat-icon {
font-size: 28px;
margin-bottom: 8px;
}
.stat-content {
text-align: center;
}
.stat-number {
font-size: 28px;
font-weight: 700;
color: #58C5A5;
text-shadow: 0 0 15px rgba(88, 197, 165, 0.4);
margin-bottom: 4px;
}
.stat-unit {
font-size: 14px;
color: #8892A0;
font-weight: 500;
margin-bottom: 4px;
}
.stat-label {
font-size: 14px;
color: #ECEFF4;
font-weight: 500;
}
.stat-divider {
width: 1px;
height: 60px;
background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.1), transparent);
}
.goal-progress-container {
background: rgba(168, 230, 207, 0.1);
border: 1px solid rgba(168, 230, 207, 0.2);
border-radius: 16px;
padding: 16px;
}
.goal-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.goal-icon {
font-size: 18px;
}
.goal-title {
font-size: 16px;
font-weight: 600;
color: #A8E6CF;
}
.goal-text {
color: #ECEFF4;
font-size: 14px;
margin-bottom: 12px;
line-height: 1.4;
}
.goal-progress {
display: flex;
align-items: center;
gap: 12px;
}
.goal-bar {
flex: 1;
height: 6px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
overflow: hidden;
}
.goal-fill {
height: 100%;
background: linear-gradient(90deg, #58C5A5, #48B885);
border-radius: 3px;
transition: width 1s ease;
}
.goal-percentage {
color: #58C5A5;
font-weight: 600;
min-width: 36px;
font-size: 14px;
}
.card-header {
display: flex;
justify-content: space-between;
@@ -1437,10 +1689,29 @@ window.addEventListener('resize', () => {
cursor: not-allowed;
}
.suggestions-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
.suggestions-carousel {
position: relative;
overflow: hidden;
padding: 10px 0 30px;
}
.suggestions-track {
display: flex;
gap: 20px;
overflow-x: auto;
scroll-snap-type: x mandatory;
padding-bottom: 10px;
scrollbar-width: thin;
scrollbar-color: rgba(88, 197, 165, 0.5) transparent;
}
.suggestions-track::-webkit-scrollbar {
height: 6px;
}
.suggestions-track::-webkit-scrollbar-thumb {
background: rgba(88, 197, 165, 0.5);
border-radius: 3px;
}
.suggestion-card {
@@ -1449,10 +1720,12 @@ window.addEventListener('resize', () => {
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 20px;
min-width: 320px;
display: flex;
gap: 16px;
cursor: pointer;
transition: all 0.3s ease;
scroll-snap-align: start;
}
.suggestion-card:hover {
@@ -1462,6 +1735,30 @@ window.addEventListener('resize', () => {
border-color: rgba(88, 197, 165, 0.3);
}
.ai-more-btn {
position: absolute;
right: 20px;
bottom: 10px;
width: 48px;
height: 48px;
border-radius: 50%;
background: linear-gradient(135deg, #58C5A5, #48B885);
border: none;
color: white;
font-size: 20px;
cursor: pointer;
box-shadow: 0 4px 16px rgba(88, 197, 165, 0.4);
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.ai-more-btn:hover {
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(88, 197, 165, 0.6);
}
.suggestion-icon {
font-size: 24px;
width: 48px;