ZhangQiPro/src/views/BigScreenPortrait.vue
sladro 3c19173c24 feat: 优化BigScreenPortrait大屏页面显示和功能完善
🔧 显示问题修复:
- 修复参与学生人数显示布局问题,优化number-gauge-combined容器
- 调整迷你仪表盘尺寸从60px到45px,适配紧凑布局
- 优化数字显示样式,使用clamp()确保响应式适配
- 完善ECharts仪表盘配置,简化为迷你版本显示

🎯 功能按钮完善:
- 实现"生成报告"和"历史记录"按钮完整功能
- 集成权限验证系统,需要教师权限才能访问
- 添加智能权限提示,未登录时引导用户登录
- 保持按钮原有美观样式,权限不足时仅显示小锁图标

🎨 界面文本优化:
- 清理Login.vue中的"演示"字样,改为"登录"
- 移除版权信息中的"演示版本"标识
- 优化组件中的演示相关文本,提升专业性

🚀 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-16 10:23:36 +08:00

2578 lines
57 KiB
Vue

<template>
<div class="big-screen-container">
<!-- 背景动画效果 -->
<div class="background-animation">
<div class="particle-network"></div>
</div>
<!-- 主标题区域 -->
<div class="header-section">
<h1 class="main-title">学生能力评价画像系统</h1>
<div class="subtitle">STUDENT CAPABILITY EVALUATION PORTRAIT</div>
<div class="current-time">{{ currentTime }}</div>
</div>
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 左侧区域 -->
<div class="left-section">
<!-- 成绩分布 -->
<div class="module-container grade-distribution">
<div class="module-header">
<el-icon><TrendCharts /></el-icon>
<span>成绩分布</span>
</div>
<div ref="gradeChart" class="chart-container"></div>
</div>
<!-- 能力矩阵三角形 -->
<div class="module-container ability-matrix">
<div class="module-header">
<el-icon><Grid /></el-icon>
<span>能力矩阵</span>
</div>
<div ref="abilityChart" class="chart-container"></div>
</div>
</div>
<!-- 中间区域 -->
<div class="center-section">
<!-- 核心指标展示区 -->
<div class="module-container core-metrics">
<div class="metrics-layout">
<!-- 左侧大区域 - 学生人数和仪表盘 -->
<div class="metric-main-area">
<div class="main-metric-header">
<el-icon><UserFilled /></el-icon>
<span>参与实习学生人数</span>
<div class="real-time-indicator">
<div class="pulse-dot"></div>
<span>实时</span>
</div>
</div>
<div class="main-metric-content ultra-compact">
<div class="metric-integrated-display">
<div class="number-gauge-combined">
<div class="number-display-section">
<div class="big-number">{{ studentCount }}</div>
<div class="number-unit"></div>
</div>
<div ref="gaugeChart" class="gauge-mini"></div>
</div>
<div class="stats-grid-compact">
<div class="stat-pill">
<span class="stat-icon">📈</span>
<div class="stat-data">
<span class="stat-value positive">+12%</span>
<span class="stat-label">较上月</span>
</div>
</div>
<div class="stat-pill">
<span class="stat-icon">👥</span>
<div class="stat-data">
<span class="stat-value">+18</span>
<span class="stat-label">新增</span>
</div>
</div>
<div class="stat-pill">
<span class="stat-icon">🎯</span>
<div class="stat-data">
<span class="stat-value">92%</span>
<span class="stat-label">活跃率</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧指标墙 - 自适应显示 -->
<div class="metrics-wall">
<div class="wall-grid adaptive">
<!-- 完成率卡片 -->
<div class="wall-card completion-rate compact">
<div class="wall-icon">
<el-icon><TrendCharts /></el-icon>
</div>
<div class="wall-content">
<div class="wall-number">87.5%</div>
<div class="wall-label">完成率</div>
<div class="wall-trend positive"> +5.2%</div>
</div>
<div class="wall-progress mini">
<div class="progress-ring">
<div class="progress-fill" style="--progress: 87.5%"></div>
</div>
</div>
</div>
<!-- 平均评分卡片 -->
<div class="wall-card average-score compact">
<div class="wall-icon">
<el-icon><StarFilled /></el-icon>
</div>
<div class="wall-content">
<div class="wall-number">82.3</div>
<div class="wall-label">评分</div>
<div class="wall-trend positive"> +2.1%</div>
</div>
<div class="wall-rating mini">
<div class="stars"></div>
</div>
</div>
<!-- 活跃课程数 -->
<div class="wall-card active-courses compact">
<div class="wall-icon">
<el-icon><Reading /></el-icon>
</div>
<div class="wall-content">
<div class="wall-number">24</div>
<div class="wall-label">课程</div>
<div class="wall-trend positive"> +8%</div>
</div>
</div>
<!-- 教师参与度 -->
<div class="wall-card teacher-participation compact">
<div class="wall-icon">
<el-icon><UserFilled /></el-icon>
</div>
<div class="wall-content">
<div class="wall-number">32</div>
<div class="wall-label">教师</div>
<div class="wall-trend positive"> +6%</div>
</div>
</div>
<!-- 企业合作数 -->
<div class="wall-card enterprise-cooperation compact">
<div class="wall-icon">
<el-icon><OfficeBuilding /></el-icon>
</div>
<div class="wall-content">
<div class="wall-number">18</div>
<div class="wall-label">企业</div>
<div class="wall-trend positive"> +12%</div>
</div>
</div>
<!-- 评价总数 -->
<div class="wall-card total-evaluations compact">
<div class="wall-icon">
<el-icon><DocumentChecked /></el-icon>
</div>
<div class="wall-content">
<div class="wall-number">1,247</div>
<div class="wall-label">评价</div>
<div class="wall-trend positive"> +15%</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 详细数据统计 -->
<div class="module-container detailed-stats">
<div class="module-header">
<el-icon><DataAnalysis /></el-icon>
<span>实习数据统计</span>
<div class="header-extra">
<span class="update-time">实时更新</span>
<div class="status-indicator"></div>
</div>
</div>
<div class="stats-overview">
<div class="overview-item">
<div class="overview-icon">
<el-icon><Reading /></el-icon>
</div>
<div class="overview-content">
<div class="overview-number">24</div>
<div class="overview-label">实习课程</div>
<div class="overview-trend">
<span class="trend-value">+5%</span>
<el-icon><Top /></el-icon>
</div>
</div>
</div>
<div class="overview-item">
<div class="overview-icon">
<el-icon><OfficeBuilding /></el-icon>
</div>
<div class="overview-content">
<div class="overview-number">8</div>
<div class="overview-label">专业覆盖</div>
<div class="overview-trend">
<span class="trend-value">+2</span>
<el-icon><Top /></el-icon>
</div>
</div>
</div>
<div class="overview-item">
<div class="overview-icon">
<el-icon><UserFilled /></el-icon>
</div>
<div class="overview-content">
<div class="overview-number">32</div>
<div class="overview-label">辅导老师</div>
<div class="overview-trend">
<span class="trend-value">+8%</span>
<el-icon><Top /></el-icon>
</div>
</div>
</div>
<div class="overview-item">
<div class="overview-icon">
<el-icon><School /></el-icon>
</div>
<div class="overview-content">
<div class="overview-number">18</div>
<div class="overview-label">合作企业</div>
<div class="overview-trend">
<span class="trend-value">+3</span>
<el-icon><Top /></el-icon>
</div>
</div>
</div>
</div>
<div class="stats-chart">
<div ref="trendChart" class="trend-container"></div>
</div>
</div>
</div>
<!-- 右侧区域 -->
<div class="right-section">
<!-- 学生名单 -->
<div class="module-container student-list">
<div class="module-header ultra-compact">
<el-icon><List /></el-icon>
<span>学生名单</span>
<div class="header-counter">{{ studentList.length }}</div>
</div>
<div class="student-table-enhanced">
<div class="table-header-enhanced">
<span>姓名</span>
<span>学号</span>
<span>状态</span>
<span>操作</span>
</div>
<div class="table-body-enhanced">
<div class="table-row-enhanced" v-for="student in studentList" :key="student.id">
<div class="student-info">
<div class="student-avatar">{{ student.name.charAt(0) }}</div>
<span class="student-name">{{ student.name }}</span>
</div>
<span class="student-id">{{ student.studentId }}</span>
<div class="student-status">
<span class="status-badge completed">已完成</span>
<span class="grade-indicator">{{ student.grade }}</span>
</div>
<div class="action-group">
<button class="action-btn primary" @click="viewReport(student.id)">
<el-icon><Document /></el-icon>
</button>
<button class="action-btn secondary">
<el-icon><View /></el-icon>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 多维度检测 -->
<div class="module-container multi-dimension">
<div class="module-header ultra-compact">
<el-icon><Monitor /></el-icon>
<span>智能分析</span>
<div class="analysis-status">
<div class="status-dot active"></div>
<span>就绪</span>
</div>
</div>
<div class="analysis-grid">
<div class="analysis-card" @click="analyzeDimension('image')">
<div class="card-icon image">
<el-icon><Picture /></el-icon>
</div>
<div class="card-content">
<span class="card-title">影像</span>
<span class="card-subtitle">AI视觉分析</span>
</div>
<div class="card-indicator">
<div class="progress-ring small">
<div class="progress-fill" style="--progress: 85%"></div>
</div>
</div>
</div>
<div class="analysis-card" @click="analyzeDimension('audio')">
<div class="card-icon audio">
<el-icon><Microphone /></el-icon>
</div>
<div class="card-content">
<span class="card-title">音频</span>
<span class="card-subtitle">语音识别</span>
</div>
<div class="card-indicator">
<div class="progress-ring small">
<div class="progress-fill" style="--progress: 72%"></div>
</div>
</div>
</div>
<div class="analysis-card" @click="analyzeDimension('text')">
<div class="card-icon text">
<el-icon><Edit /></el-icon>
</div>
<div class="card-content">
<span class="card-title">文本</span>
<span class="card-subtitle">NLP分析</span>
</div>
<div class="card-indicator">
<div class="progress-ring small">
<div class="progress-fill" style="--progress: 94%"></div>
</div>
</div>
</div>
</div>
<!-- 底部操作按钮 -->
<div class="action-buttons-enhanced">
<button
class="action-btn-large primary"
:class="{ 'requires-auth': !authStore.isLoggedIn || authStore.user?.role !== 'teacher' }"
@click="generateReport"
:title="!authStore.isLoggedIn ? '需要登录教师账号' : authStore.user?.role !== 'teacher' ? '需要教师权限' : '生成学生评价报告'"
>
<el-icon><DocumentAdd /></el-icon>
<span>生成报告</span>
</button>
<button
class="action-btn-large secondary"
:class="{ 'requires-auth': !authStore.isLoggedIn || authStore.user?.role !== 'teacher' }"
@click="viewHistory"
:title="!authStore.isLoggedIn ? '需要登录教师账号' : authStore.user?.role !== 'teacher' ? '需要教师权限' : '查看历史评价记录'"
>
<el-icon><Clock /></el-icon>
<span>历史记录</span>
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, onMounted, onUnmounted, reactive } from 'vue'
import * as echarts from 'echarts'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { useAuthStore } from '@/stores/auth'
import { mockStudents, mockPortraitData, generateChartData, generateStatsData, bigScreenData } from '@/utils/mockData'
export default {
name: 'BigScreenPortrait',
setup() {
const router = useRouter()
const authStore = useAuthStore()
const currentTime = ref('')
const studentCount = ref(156)
const studentList = ref([])
const practiceStats = ref([])
// 图表实例
const gradeChart = ref(null)
const abilityChart = ref(null)
const gaugeChart = ref(null)
const trendChart = ref(null)
let chartInstances = []
let timer = null
// 初始化数据
const initData = () => {
studentList.value = mockStudents.slice(0, 8)
practiceStats.value = bigScreenData.practiceStats
studentCount.value = bigScreenData.realTimeData.studentCount
// 检查登录状态
authStore.checkAuth()
}
// 权限检查和导航的通用方法
const checkPermissionAndNavigate = (targetPath, requiredRole = null) => {
if (!authStore.isLoggedIn) {
ElMessage.warning('请先登录以使用此功能')
router.push('/')
return false
}
if (requiredRole && authStore.user?.role !== requiredRole) {
ElMessage.warning('权限不足,需要教师账号才能访问此功能')
return false
}
router.push(targetPath)
return true
}
// 更新时间
const updateTime = () => {
const now = new Date()
currentTime.value = now.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
}
// 初始化成绩分布图表
const initGradeChart = () => {
const chart = echarts.init(gradeChart.value)
const data = bigScreenData.gradeDistribution
const option = {
backgroundColor: 'transparent',
grid: {
left: '10%',
right: '10%',
top: '15%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: data.map(item => item.grade),
axisLine: {
lineStyle: { color: '#3b82f6' }
},
axisLabel: {
color: '#e2e8f0',
fontSize: 12,
rotate: 45
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: { color: '#3b82f6' }
},
axisLabel: {
color: '#e2e8f0',
fontSize: 12
},
splitLine: {
lineStyle: { color: 'rgba(59, 130, 246, 0.2)' }
}
},
series: [{
data: data.map((item, index) => ({
value: item.count,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: item.color },
{ offset: 1, color: `${item.color}80` }
]),
borderRadius: [4, 4, 0, 0]
}
})),
type: 'bar',
barWidth: '50%',
label: {
show: true,
position: 'top',
color: '#e2e8f0',
fontSize: 14,
fontWeight: 'bold',
formatter: '{c}人'
},
animationDuration: 2000,
animationEasing: 'elasticOut'
}]
}
chart.setOption(option)
chartInstances.push(chart)
}
// 初始化能力矩阵图表
const initAbilityChart = () => {
const chart = echarts.init(abilityChart.value)
const abilityData = bigScreenData.abilityMatrix
const option = {
backgroundColor: 'transparent',
radar: {
indicator: abilityData.dimensions.map(dim => ({
name: dim,
max: 100
})),
center: ['50%', '50%'],
radius: '70%',
axisName: {
color: '#e2e8f0',
fontSize: 14,
fontWeight: 'bold',
backgroundColor: 'rgba(30, 58, 138, 0.8)',
borderRadius: 4,
padding: [4, 8]
},
splitLine: {
lineStyle: {
color: 'rgba(59, 130, 246, 0.3)',
width: 2
}
},
splitArea: {
areaStyle: {
color: [
'rgba(6, 182, 212, 0.1)',
'rgba(6, 182, 212, 0.2)',
'rgba(59, 130, 246, 0.1)',
'rgba(59, 130, 246, 0.2)'
]
}
},
axisLine: {
lineStyle: {
color: 'rgba(59, 130, 246, 0.5)',
width: 2
}
}
},
series: [{
type: 'radar',
data: abilityData.students.map((student, index) => ({
value: student.values,
name: student.name,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: `${student.color}80` },
{ offset: 1, color: `${student.color}20` }
])
},
lineStyle: {
color: student.color,
width: 3,
shadowBlur: 10,
shadowColor: student.color
},
symbol: 'circle',
symbolSize: 10,
itemStyle: {
color: student.color,
borderColor: '#fff',
borderWidth: 2,
shadowBlur: 10,
shadowColor: student.color
}
})),
animationDuration: 2000,
animationEasing: 'elasticOut'
}],
legend: {
data: abilityData.students.map(s => s.name),
textStyle: {
color: '#e2e8f0',
fontSize: 12
},
bottom: 10,
itemWidth: 20,
itemHeight: 10
}
}
chart.setOption(option)
chartInstances.push(chart)
}
// 初始化仪表盘图表(迷你版)
const initGaugeChart = () => {
const chart = echarts.init(gaugeChart.value)
const option = {
backgroundColor: 'transparent',
series: [{
type: 'gauge',
startAngle: 200,
endAngle: -20,
center: ['50%', '60%'],
radius: '85%',
min: 0,
max: 200,
splitNumber: 2,
itemStyle: {
color: '#06b6d4'
},
progress: {
show: true,
width: 8,
roundCap: true,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#06b6d4' },
{ offset: 1, color: '#3b82f6' }
])
}
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 8,
color: [[1, 'rgba(59, 130, 246, 0.15)']]
}
},
axisTick: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
detail: {
show: false
},
data: [{
value: studentCount.value,
name: ''
}],
animationDuration: 2000
}]
}
chart.setOption(option)
chartInstances.push(chart)
}
// 初始化趋势图表
const initTrendChart = () => {
const chart = echarts.init(trendChart.value)
const option = {
backgroundColor: 'transparent',
grid: {
left: '5%',
right: '5%',
top: '10%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月'],
axisLine: { show: false },
axisTick: { show: false },
axisLabel: {
color: '#94a3b8',
fontSize: 10
}
},
yAxis: {
type: 'value',
axisLine: { show: false },
axisTick: { show: false },
axisLabel: { show: false },
splitLine: { show: false }
},
series: [{
data: [120, 132, 145, 134, 156, 165],
type: 'line',
smooth: true,
lineStyle: {
color: '#06b6d4',
width: 3,
shadowBlur: 10,
shadowColor: '#06b6d4'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(6, 182, 212, 0.3)' },
{ offset: 1, color: 'rgba(6, 182, 212, 0.05)' }
])
},
symbol: 'circle',
symbolSize: 6,
itemStyle: {
color: '#06b6d4',
borderColor: '#fff',
borderWidth: 2
},
animationDuration: 2000
}]
}
chart.setOption(option)
chartInstances.push(chart)
}
// 查看报告
const viewReport = (studentId) => {
router.push(`/report/${studentId}`)
}
// 多维度分析
const analyzeDimension = (type) => {
ElMessage.success(`正在分析${type === 'image' ? '影像' : type === 'audio' ? '音频' : '文本'}数据...`)
}
// 生成报告 - 跳转到报告中心
const generateReport = () => {
checkPermissionAndNavigate('/home/reports', 'teacher')
}
// 查看历史记录 - 跳转到报告中心
const viewHistory = () => {
checkPermissionAndNavigate('/home/reports', 'teacher')
}
// 窗口大小调整处理
const handleResize = () => {
chartInstances.forEach(chart => {
chart.resize()
})
}
// 初始化
onMounted(() => {
initData()
updateTime()
timer = setInterval(updateTime, 1000)
setTimeout(() => {
initGradeChart()
initAbilityChart()
initGaugeChart()
initTrendChart()
}, 100)
window.addEventListener('resize', handleResize)
})
// 清理
onUnmounted(() => {
if (timer) clearInterval(timer)
window.removeEventListener('resize', handleResize)
chartInstances.forEach(chart => {
chart.dispose()
})
})
return {
currentTime,
studentCount,
studentList,
practiceStats,
gradeChart,
abilityChart,
gaugeChart,
trendChart,
authStore,
viewReport,
analyzeDimension,
generateReport,
viewHistory
}
}
}
</script>
<style scoped>
.big-screen-container {
width: 100vw;
height: 100vh;
background: linear-gradient(135deg, #0a1027 0%, #1e3a8a 50%, #1e40af 100%);
position: relative;
overflow: hidden;
font-family: 'Arial', sans-serif;
}
/* 背景动画效果 */
.background-animation {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.particle-network {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 20%, rgba(6, 182, 212, 0.1) 0%, transparent 50%),
radial-gradient(circle at 40% 40%, rgba(16, 185, 129, 0.05) 0%, transparent 50%);
animation: particleFloat 20s ease-in-out infinite;
}
@keyframes particleFloat {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-20px) rotate(180deg); }
}
/* 标题区域 */
.header-section {
position: relative;
z-index: 10;
text-align: center;
padding: 12px 0;
background: var(--primary-alpha-heavy);
backdrop-filter: var(--glass-blur);
border-bottom: 1px solid rgba(59, 130, 246, 0.3);
}
.main-title {
font-size: 36px;
font-weight: bold;
color: #e2e8f0;
margin: 0;
text-shadow: 0 0 15px rgba(59, 130, 246, 0.6);
background: linear-gradient(45deg, var(--secondary), var(--primary-light), var(--purple));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.subtitle {
font-size: 14px;
color: var(--gray-light);
margin: 6px 0;
letter-spacing: 0.5px;
}
.current-time {
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 12px;
color: #e2e8f0;
background: var(--primary-alpha-heavy);
padding: 4px 10px;
border-radius: var(--radius-xl);
border: 1px solid rgba(59, 130, 246, 0.25);
}
/* 主内容区域 - 优化间距和布局 */
.main-content {
display: grid;
grid-template-columns: 1fr 1.3fr 0.9fr;
gap: 10px;
padding: 10px;
height: calc(100vh - 100px);
position: relative;
z-index: 5;
}
/* 模块容器 - 减少内边距 */
.module-container {
background: rgba(30, 58, 138, 0.15);
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: var(--radius-md);
padding: 12px;
backdrop-filter: blur(10px);
box-shadow: var(--shadow-md);
position: relative;
overflow: hidden;
}
.module-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, transparent 50%);
pointer-events: none;
}
.module-container.compact {
padding: 10px;
border-radius: var(--radius-sm);
}
.module-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
color: #e2e8f0;
font-size: 16px;
font-weight: 600;
}
.module-header .el-icon {
font-size: 18px;
color: var(--secondary);
}
/* 图表容器 */
.chart-container {
width: 100%;
height: 250px;
position: relative;
z-index: 1;
}
.gauge-container {
width: 100%;
height: 200px;
position: relative;
z-index: 1;
}
.gauge-container.compact {
height: 120px;
}
/* 左侧区域 - 紧凑布局 */
.left-section {
display: flex;
flex-direction: column;
gap: 8px;
}
.grade-distribution {
flex: 1;
}
.ability-matrix {
flex: 1;
}
/* 中间区域 - 紧凑布局 */
.center-section {
display: flex;
flex-direction: column;
gap: 8px;
}
/* SOTA标准优化样式 */
/* 超紧凑布局 */
.main-metric-content.ultra-compact {
display: flex;
flex-direction: column;
gap: 8px;
height: 100%;
justify-content: space-between;
}
.metric-integrated-display {
display: flex;
flex-direction: column;
gap: 10px;
height: 100%;
}
.number-gauge-combined {
display: flex;
align-items: center;
gap: 12px;
background: var(--primary-alpha-medium);
border-radius: var(--radius-md);
padding: 10px 15px;
border: 1px solid rgba(59, 130, 246, 0.2);
min-height: 70px;
}
.number-display-section {
display: flex;
align-items: baseline;
gap: 6px;
flex: 1;
}
.gauge-mini {
width: 45px;
height: 45px;
position: relative;
flex-shrink: 0;
}
.stats-grid-compact {
display: grid;
grid-template-columns: 1fr;
gap: 4px;
flex: 1;
}
.stat-pill {
display: flex;
align-items: center;
gap: 8px;
background: var(--primary-alpha-heavy);
border: 1px solid rgba(59, 130, 246, 0.25);
border-radius: var(--radius-lg);
padding: 6px 10px;
transition: var(--transition);
}
.stat-pill:hover {
background: var(--primary-alpha-heavy);
border-color: rgba(59, 130, 246, 0.4);
transform: translateX(2px);
}
.stat-icon {
font-size: 12px;
opacity: 0.9;
}
.stat-data {
display: flex;
flex-direction: column;
gap: 1px;
}
.stat-data .stat-value {
font-size: 12px;
font-weight: 600;
color: #e2e8f0;
}
.stat-data .stat-label {
font-size: 9px;
color: #94a3b8;
opacity: 0.8;
}
/* 核心指标展示区 */
.core-metrics {
flex: 1;
}
.metrics-layout {
display: grid;
grid-template-columns: 1.4fr 1fr;
gap: 12px;
height: 100%;
}
.metric-main-area {
background: rgba(30, 58, 138, 0.2);
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: var(--radius-md);
padding: 15px;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
transition: var(--transition);
}
.metric-main-area::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, transparent 50%);
pointer-events: none;
}
.metric-main-area:hover {
transform: translateY(-2px);
box-shadow: 0 12px 40px rgba(59, 130, 246, 0.2);
}
.main-metric-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 12px;
position: relative;
z-index: 1;
}
.main-metric-header .el-icon {
font-size: 20px;
color: #06b6d4;
}
.main-metric-header span {
font-size: 16px;
color: #e2e8f0;
font-weight: 500;
}
.real-time-indicator {
display: flex;
align-items: center;
gap: 4px;
margin-left: auto;
font-size: 10px;
color: var(--success);
background: var(--success-alpha-medium);
padding: 3px 6px;
border-radius: var(--radius-lg);
border: 1px solid rgba(16, 185, 129, 0.25);
}
.pulse-dot {
width: 5px;
height: 5px;
background: var(--success);
border-radius: 50%;
animation: pulse 1.5s infinite;
}
.main-metric-content {
display: flex;
gap: 12px;
flex: 1;
align-items: center;
position: relative;
z-index: 1;
}
.main-metric-content.compact {
gap: 10px;
align-items: center;
}
.main-metric-content.compact .metric-number-section {
flex: 0 0 auto;
}
.main-metric-content.compact .metric-chart-section {
flex: 1;
min-width: 0;
}
.metric-number-section {
flex: 1;
display: flex;
flex-direction: column;
gap: 10px;
justify-content: center;
}
.number-display {
display: flex;
align-items: baseline;
gap: 8px;
}
.big-number {
font-size: clamp(28px, 2.8vw, 36px);
font-weight: 700;
color: #e2e8f0;
text-shadow: 0 0 15px rgba(6, 182, 212, 0.5);
line-height: 1;
letter-spacing: -0.5px;
}
.number-unit {
font-size: 16px;
color: #94a3b8;
font-weight: 500;
margin-top: 2px;
}
.number-stats {
display: flex;
flex-direction: column;
gap: 6px;
}
.stat-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
}
.stat-label {
color: #94a3b8;
}
.stat-value {
color: #e2e8f0;
font-weight: 500;
}
.stat-value.positive {
color: #10b981;
}
.metric-chart-section {
width: 200px;
height: 150px;
}
/* 指标墙 */
.metrics-wall {
display: flex;
flex-direction: column;
gap: 12px;
height: 100%;
}
.wall-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: minmax(50px, 1fr);
gap: 6px;
height: 100%;
}
.wall-grid.adaptive {
gap: 4px;
grid-template-rows: repeat(3, 1fr);
}
.wall-card {
background: rgba(30, 58, 138, 0.12);
border: 1px solid rgba(59, 130, 246, 0.18);
border-radius: var(--radius-sm);
padding: 8px;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
overflow: hidden;
transition: var(--transition);
}
.wall-card:hover {
background: rgba(30, 58, 138, 0.25);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
}
.wall-card.compact {
padding: 6px 8px;
border-radius: var(--radius-sm);
}
.wall-icon {
font-size: 14px;
color: var(--secondary);
margin-bottom: 4px;
opacity: 0.9;
}
.wall-card.compact .wall-icon {
font-size: 12px;
margin-bottom: 2px;
}
.wall-content {
flex: 1;
}
.wall-number {
font-size: 20px;
font-weight: 600;
color: #e2e8f0;
margin-bottom: 2px;
line-height: 1;
}
.wall-card.compact .wall-number {
font-size: 16px;
margin-bottom: 1px;
}
.wall-label {
font-size: 10px;
color: #94a3b8;
margin-bottom: 3px;
opacity: 0.9;
}
.wall-card.compact .wall-label {
font-size: 9px;
margin-bottom: 2px;
}
.wall-trend {
font-size: 11px;
font-weight: 500;
}
.wall-card.compact .wall-trend {
font-size: 9px;
}
.wall-trend.positive {
color: var(--success);
}
.wall-trend.negative {
color: var(--danger);
}
/* 特殊卡片样式 */
.wall-progress {
position: absolute;
top: 10px;
right: 10px;
}
.wall-progress.mini {
top: 6px;
right: 6px;
}
.progress-ring {
width: 32px;
height: 32px;
position: relative;
}
.wall-progress.mini .progress-ring {
width: 24px;
height: 24px;
}
.progress-ring::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
border: 2px solid rgba(59, 130, 246, 0.2);
border-radius: 50%;
}
.wall-progress.mini .progress-ring::before {
border-width: 1px;
}
.progress-ring::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 3px solid transparent;
border-top: 3px solid #06b6d4;
border-right: 3px solid #06b6d4;
border-radius: 50%;
transform: rotate(-45deg);
animation: rotateProgress 2s linear infinite;
}
.wall-progress.mini .progress-ring::after {
border-width: 2px;
}
@keyframes rotateProgress {
from { transform: rotate(-45deg); }
to { transform: rotate(315deg); }
}
.wall-rating {
display: flex;
align-items: center;
gap: 6px;
margin-top: 6px;
}
.wall-rating.mini {
margin-top: 3px;
}
.wall-rating.mini .stars {
font-size: 10px;
}
.stars {
color: #f59e0b;
font-size: 12px;
}
.rating-text {
font-size: 10px;
color: #94a3b8;
}
/* 多维度检测按钮优化 */
.dimension-buttons {
display: grid;
grid-template-columns: 1fr;
gap: 4px;
margin-bottom: 8px;
flex: 1;
min-height: 0;
}
/* 分析网格 */
.analysis-grid {
display: grid;
grid-template-columns: 1fr;
gap: 6px;
margin-bottom: 12px;
flex: 1;
}
.analysis-card {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
background: var(--primary-alpha-medium);
border: 1px solid rgba(59, 130, 246, 0.25);
border-radius: var(--radius-md);
cursor: pointer;
transition: var(--transition);
position: relative;
overflow: hidden;
}
.analysis-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, transparent 50%);
pointer-events: none;
}
.analysis-card:hover {
background: var(--primary-alpha-heavy);
border-color: rgba(59, 130, 246, 0.4);
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
.card-icon {
width: 28px;
height: 28px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
position: relative;
z-index: 1;
}
.card-icon.image {
background: linear-gradient(135deg, #f59e0b, #f97316);
color: white;
}
.card-icon.audio {
background: linear-gradient(135deg, #8b5cf6, #a855f7);
color: white;
}
.card-icon.text {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
}
.card-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 1px;
position: relative;
z-index: 1;
}
.card-title {
font-size: 12px;
font-weight: 600;
color: #e2e8f0;
}
.card-subtitle {
font-size: 9px;
color: var(--gray-light);
opacity: 0.8;
}
.card-indicator {
position: relative;
z-index: 1;
}
.progress-ring.small {
width: 20px;
height: 20px;
position: relative;
}
.progress-ring.small::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: 50%;
}
.progress-ring.small .progress-fill {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 2px solid transparent;
border-top: 2px solid var(--secondary);
border-right: 2px solid var(--secondary);
border-radius: 50%;
transform: rotate(-45deg);
opacity: 0.8;
}
/* 增强型操作按钮 */
.action-buttons-enhanced {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-top: auto;
}
.action-btn-large {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
padding: 8px 10px;
border: none;
border-radius: var(--radius-md);
font-size: 11px;
font-weight: 600;
cursor: pointer;
transition: var(--transition);
position: relative;
overflow: hidden;
}
.action-btn-large::before {
content: '';
position: absolute;
top: 0;
left: -100%;
right: 0;
bottom: 0;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.action-btn-large:hover::before {
left: 100%;
}
.action-btn-large.primary {
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: white;
}
.action-btn-large.primary:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
.action-btn-large.secondary {
background: linear-gradient(135deg, var(--gray), var(--gray-light));
color: white;
}
.action-btn-large.secondary:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-sm);
}
.action-btn-large .el-icon {
font-size: 12px;
}
.action-btn-large span {
position: relative;
z-index: 1;
}
/* 权限相关样式 - 只在权限不足时显示限制样式 */
.action-btn-large.requires-auth {
position: relative;
}
.action-btn-large.requires-auth::after {
content: '🔒';
position: absolute;
top: -5px;
right: -5px;
background: var(--warning);
color: white;
width: 16px;
height: 16px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
border: 2px solid var(--bg-primary);
z-index: 10;
}
.dimension-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 8px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.15) 0%, rgba(6, 182, 212, 0.15) 100%);
border: 1px solid rgba(59, 130, 246, 0.25);
border-radius: var(--radius-sm);
color: #e2e8f0;
cursor: pointer;
transition: var(--transition);
font-size: 11px;
min-height: 32px;
}
.dimension-btn:hover {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.3) 0%, rgba(6, 182, 212, 0.3) 100%);
border-color: rgba(59, 130, 246, 0.5);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.dimension-btn .el-icon {
font-size: 12px;
color: var(--secondary);
opacity: 0.9;
}
.wall-mini-chart {
margin-top: 6px;
}
.mini-bars {
display: flex;
align-items: end;
gap: 2px;
height: 20px;
}
.bar {
width: 4px;
background: linear-gradient(to top, #06b6d4, #3b82f6);
border-radius: 2px;
animation: barGrow 1s ease-out;
}
@keyframes barGrow {
from { height: 0; }
to { height: var(--height); }
}
.wall-avatar-list {
display: flex;
align-items: center;
gap: 4px;
margin-top: 6px;
}
.avatar-circle {
width: 16px;
height: 16px;
border-radius: 50%;
background: linear-gradient(135deg, #06b6d4, #3b82f6);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.avatar-more {
font-size: 10px;
color: #94a3b8;
background: rgba(147, 197, 253, 0.2);
padding: 2px 4px;
border-radius: 8px;
}
.wall-enterprise-icons {
display: flex;
gap: 4px;
margin-top: 6px;
}
.enterprise-icon {
font-size: 14px;
opacity: 0.8;
}
.wall-evaluation-status {
display: flex;
flex-direction: column;
gap: 2px;
margin-top: 6px;
}
.status-item {
font-size: 10px;
padding: 2px 4px;
border-radius: 4px;
}
.status-item.completed {
color: #10b981;
background: rgba(16, 185, 129, 0.2);
}
.status-item.pending {
color: #f59e0b;
background: rgba(245, 158, 11, 0.2);
}
/* 操作按钮优化 */
.action-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-top: 8px;
flex: 0 0 auto;
}
.action-buttons .el-button {
background: linear-gradient(135deg, var(--primary-light) 0%, var(--secondary) 100%);
border: none;
color: white;
font-weight: 500;
transition: var(--transition);
padding: 4px 8px;
font-size: 10px;
height: 28px;
border-radius: var(--radius-sm);
}
.action-buttons .el-button:hover {
transform: translateY(-1px);
box-shadow: var(--shadow-md);
opacity: 0.95;
}
.action-buttons .el-button.el-button--info {
background: linear-gradient(135deg, var(--gray) 0%, var(--gray-light) 100%);
}
/* 详细数据统计 */
.detailed-stats {
flex: 1;
display: flex;
flex-direction: column;
}
.header-extra {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
}
.update-time {
font-size: 11px;
color: var(--gray-light);
background: var(--primary-alpha-heavy);
padding: 3px 6px;
border-radius: var(--radius-lg);
}
.status-indicator {
width: 6px;
height: 6px;
background: var(--success);
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.stats-overview {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-bottom: 15px;
}
.overview-item {
display: flex;
align-items: center;
gap: 8px;
padding: 10px;
background: var(--primary-alpha-medium);
border-radius: var(--radius-sm);
border: 1px solid rgba(59, 130, 246, 0.18);
transition: var(--transition);
}
.overview-item:hover {
background: var(--primary-alpha-heavy);
transform: translateY(-1px);
box-shadow: var(--shadow-sm);
}
.overview-icon {
font-size: 20px;
color: var(--secondary);
background: var(--secondary-alpha-heavy);
padding: 6px;
border-radius: var(--radius-sm);
}
.overview-number {
font-size: 20px;
font-weight: 600;
color: #e2e8f0;
margin-bottom: 1px;
}
.overview-label {
font-size: 11px;
color: var(--gray-light);
margin-bottom: 2px;
}
.overview-trend {
display: flex;
align-items: center;
gap: 3px;
font-size: 11px;
color: var(--success);
}
.trend-value {
font-weight: bold;
}
.stats-chart {
height: 100px;
background: var(--primary-alpha-medium);
border-radius: var(--radius-sm);
border: 1px solid rgba(59, 130, 246, 0.15);
}
.trend-container {
width: 100%;
height: 100%;
}
/* 右侧区域 - 优化布局 */
.right-section {
display: flex;
flex-direction: column;
gap: 6px;
height: 100%;
}
.student-list {
flex: 1.3;
min-height: 0;
display: flex;
flex-direction: column;
max-height: 65%;
}
.multi-dimension {
flex: 0.7;
min-height: 180px;
display: flex;
flex-direction: column;
max-height: 35%;
}
/* 多维度检测按钮 */
.dimension-buttons {
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 20px;
}
.dimension-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 16px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(6, 182, 212, 0.2) 100%);
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: 8px;
color: #e2e8f0;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
}
.dimension-btn:hover {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.3) 0%, rgba(6, 182, 212, 0.3) 100%);
border-color: rgba(59, 130, 246, 0.5);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.dimension-btn .el-icon {
font-size: 16px;
color: #06b6d4;
}
/* 操作按钮 */
.action-buttons {
display: flex;
gap: 12px;
margin-top: 20px;
}
.action-buttons .el-button {
flex: 1;
background: linear-gradient(135deg, #3b82f6 0%, #06b6d4 100%);
border: none;
color: white;
font-weight: bold;
transition: all 0.3s ease;
}
.action-buttons .el-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.3);
}
.action-buttons .el-button.el-button--info {
background: linear-gradient(135deg, var(--gray) 0%, var(--gray-light) 100%);
}
/* 学生表格 - 紧凑设计 */
.student-table {
background: rgba(30, 58, 138, 0.08);
border-radius: var(--radius-sm);
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
border: 1px solid rgba(59, 130, 246, 0.15);
}
/* 增强型学生表格 */
.student-table-enhanced {
background: var(--primary-alpha-medium);
border-radius: var(--radius-md);
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
border: 1px solid rgba(59, 130, 246, 0.2);
}
.table-header-enhanced {
display: grid;
grid-template-columns: 1.5fr 1fr 1fr 0.8fr;
gap: 8px;
padding: 8px 12px;
background: var(--primary-alpha-heavy);
font-weight: 600;
color: #e2e8f0;
font-size: 11px;
flex: 0 0 auto;
border-bottom: 1px solid rgba(59, 130, 246, 0.3);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.table-body-enhanced {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
padding: 4px;
}
.table-row-enhanced {
display: grid;
grid-template-columns: 1.5fr 1fr 1fr 0.8fr;
gap: 8px;
padding: 8px 12px;
margin: 2px 0;
border-radius: var(--radius-sm);
color: #e2e8f0;
font-size: 11px;
align-items: center;
transition: var(--transition);
background: var(--primary-alpha-light);
border: 1px solid transparent;
}
.table-row-enhanced:hover {
background: var(--primary-alpha-medium);
border-color: rgba(59, 130, 246, 0.3);
transform: translateX(2px);
box-shadow: var(--shadow-sm);
}
.student-info {
display: flex;
align-items: center;
gap: 6px;
}
.student-avatar {
width: 20px;
height: 20px;
border-radius: 50%;
background: var(--secondary);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: 600;
}
.student-name {
font-weight: 500;
}
.student-id {
font-family: monospace;
opacity: 0.8;
}
.student-status {
display: flex;
flex-direction: column;
gap: 2px;
}
.status-badge {
padding: 2px 6px;
border-radius: var(--radius-lg);
font-size: 9px;
font-weight: 500;
text-align: center;
}
.status-badge.completed {
background: var(--success-alpha-medium);
color: var(--success);
border: 1px solid rgba(16, 185, 129, 0.2);
}
.grade-indicator {
font-size: 8px;
color: var(--gray-light);
text-align: center;
}
.action-group {
display: flex;
gap: 4px;
justify-content: center;
}
.action-btn {
width: 20px;
height: 20px;
border-radius: var(--radius-sm);
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
font-size: 10px;
}
.action-btn.primary {
background: var(--secondary-alpha-medium);
color: var(--secondary);
border: 1px solid rgba(6, 182, 212, 0.2);
}
.action-btn.primary:hover {
background: var(--secondary-alpha-heavy);
transform: scale(1.1);
}
.action-btn.secondary {
background: var(--gray-alpha-medium);
color: var(--gray-light);
border: 1px solid rgba(148, 163, 184, 0.2);
}
.action-btn.secondary:hover {
background: var(--gray-alpha-heavy);
transform: scale(1.1);
}
.table-header {
display: grid;
grid-template-columns: 0.8fr 1fr 0.6fr 0.8fr;
gap: 4px;
padding: 8px 10px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.25) 0%, rgba(6, 182, 212, 0.2) 100%);
font-weight: 600;
color: #e2e8f0;
font-size: 11px;
flex: 0 0 auto;
border-bottom: 1px solid rgba(59, 130, 246, 0.3);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.table-body {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
max-height: 100%;
padding: 4px;
}
.table-row {
display: grid;
grid-template-columns: 0.8fr 1fr 0.6fr 0.8fr;
gap: 4px;
padding: 8px 10px;
margin: 2px 4px;
border-radius: var(--radius-sm);
color: #e2e8f0;
font-size: 11px;
align-items: center;
transition: var(--transition);
background: rgba(30, 58, 138, 0.05);
border: 1px solid transparent;
}
.table-row:hover {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.15) 0%, rgba(6, 182, 212, 0.1) 100%);
border-color: rgba(59, 130, 246, 0.2);
transform: translateX(2px);
box-shadow: var(--shadow-sm);
}
.table-row:last-child {
border-bottom: none;
margin-bottom: 4px;
}
.report-link {
color: var(--secondary);
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 3px;
padding: 3px 6px;
border-radius: var(--radius-sm);
background: rgba(6, 182, 212, 0.1);
border: 1px solid rgba(6, 182, 212, 0.2);
transition: var(--transition);
font-size: 10px;
white-space: nowrap;
}
.report-link:hover {
color: var(--secondary-light);
background: rgba(6, 182, 212, 0.2);
border-color: rgba(6, 182, 212, 0.4);
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(6, 182, 212, 0.3);
}
/* 多维度检测按钮 */
.dimension-buttons {
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 20px;
}
.dimension-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 16px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(6, 182, 212, 0.2) 100%);
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: 8px;
color: #e2e8f0;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
}
.dimension-btn:hover {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.3) 0%, rgba(6, 182, 212, 0.3) 100%);
border-color: rgba(59, 130, 246, 0.5);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.dimension-btn .el-icon {
font-size: 16px;
color: #06b6d4;
}
/* 操作按钮 */
.action-buttons {
display: flex;
gap: 12px;
margin-top: 20px;
}
.action-buttons .el-button {
flex: 1;
background: linear-gradient(135deg, #3b82f6 0%, #06b6d4 100%);
border: none;
color: white;
font-weight: bold;
transition: all 0.3s ease;
}
.action-buttons .el-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.3);
}
.action-buttons .el-button.el-button--info {
background: linear-gradient(135deg, var(--gray) 0%, var(--gray-light) 100%);
}
/* 自适应组件优化 */
@media (max-width: 1600px) {
.chart-container {
height: 250px;
}
.gauge-container {
height: 180px;
}
.dimension-btn {
font-size: 12px;
padding: 8px 10px;
}
.action-buttons .el-button {
font-size: 11px;
height: 32px;
padding: 6px 10px;
}
}
/* 模块标题紧凑模式 */
.module-header.compact {
margin-bottom: 10px;
font-size: 14px;
font-weight: 600;
}
.module-header.compact .el-icon {
font-size: 16px;
}
.module-header.ultra-compact {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
font-size: 13px;
font-weight: 600;
}
.module-header.ultra-compact .el-icon {
font-size: 14px;
}
.header-counter {
background: var(--success-alpha-medium);
color: var(--success);
padding: 2px 6px;
border-radius: var(--radius-lg);
font-size: 10px;
font-weight: 500;
border: 1px solid rgba(16, 185, 129, 0.2);
}
.analysis-status {
display: flex;
align-items: center;
gap: 4px;
font-size: 10px;
color: var(--success);
}
.status-dot {
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--success);
}
.status-dot.active {
animation: pulse 1.5s infinite;
}
.table-body::-webkit-scrollbar,
.table-body-enhanced::-webkit-scrollbar {
width: 4px;
}
.table-body::-webkit-scrollbar-track,
.table-body-enhanced::-webkit-scrollbar-track {
background: var(--primary-alpha-light);
border-radius: 2px;
}
.table-body::-webkit-scrollbar-thumb,
.table-body-enhanced::-webkit-scrollbar-thumb {
background: var(--secondary-alpha-medium);
border-radius: 2px;
}
.table-body::-webkit-scrollbar-thumb:hover,
.table-body-enhanced::-webkit-scrollbar-thumb:hover {
background: var(--secondary-alpha-heavy);
}
/* 响应式设计 */
@media (max-width: 1920px) {
.main-content {
padding: 12px;
gap: 10px;
}
.module-container {
padding: 12px;
}
.main-title {
font-size: 32px;
}
.big-number {
font-size: 42px;
}
.wall-card.compact {
padding: 6px;
}
.wall-card.compact .wall-number {
font-size: 15px;
}
}
@media (max-width: 1600px) {
.main-content {
grid-template-columns: 1fr 1.2fr 0.8fr;
gap: 8px;
}
.big-number {
font-size: clamp(24px, 2.4vw, 32px);
}
.number-unit {
font-size: 14px;
}
.gauge-mini {
width: 40px;
height: 40px;
}
.number-gauge-combined {
padding: 8px 12px;
min-height: 60px;
}
.wall-card.compact .wall-number {
font-size: 14px;
}
.wall-card.compact .wall-label {
font-size: 9px;
}
.metrics-layout {
grid-template-columns: 1.3fr 1fr;
}
.main-metric-content.compact {
flex-direction: row;
gap: 8px;
}
.metric-chart-section {
width: 100%;
height: 100px;
}
.chart-container {
height: 220px;
}
}
@media (max-width: 1366px) {
.main-content {
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
}
.main-title {
font-size: 28px;
}
.subtitle {
font-size: 14px;
}
.big-number {
font-size: 42px;
}
.wall-grid.adaptive {
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
}
.stats-overview {
grid-template-columns: repeat(2, 1fr);
}
.metrics-layout {
grid-template-columns: 1fr;
}
.table-row {
font-size: 11px;
}
}
@media (max-width: 1024px) {
.main-content {
padding: 10px;
gap: 10px;
}
.module-container {
padding: 12px;
}
.wall-grid.adaptive {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.stats-overview {
grid-template-columns: 1fr;
}
.big-number {
font-size: clamp(20px, 2vw, 28px);
}
.number-unit {
font-size: 12px;
}
.gauge-mini {
width: 35px;
height: 35px;
}
.number-gauge-combined {
padding: 6px 10px;
min-height: 50px;
gap: 8px;
}
.main-metric-header {
flex-wrap: wrap;
}
.real-time-indicator {
margin-left: 0;
margin-top: 5px;
}
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
}
.header-section {
flex-direction: column;
gap: 10px;
text-align: center;
}
.current-time {
position: static;
transform: none;
}
.wall-grid.adaptive {
grid-template-columns: 1fr;
}
.metrics-layout {
grid-template-columns: 1fr;
}
.main-metric-content.compact {
flex-direction: column;
}
.stats-overview {
grid-template-columns: 1fr;
}
.module-header {
font-size: 16px;
}
.big-number {
font-size: 32px;
}
}
/* 加载动画 */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.module-container {
animation: fadeIn 0.8s ease-out;
}
.module-container:nth-child(1) { animation-delay: 0.1s; }
.module-container:nth-child(2) { animation-delay: 0.2s; }
.module-container:nth-child(3) { animation-delay: 0.3s; }
.module-container:nth-child(4) { animation-delay: 0.4s; }
.module-container:nth-child(5) { animation-delay: 0.5s; }
.module-container:nth-child(6) { animation-delay: 0.6s; }
</style>