| | |
| | | <template> |
| | | <div class="dashboard"> |
| | | <!-- 数据统计卡片 --> |
| | | <el-row :gutter="20" class="stats-row"> |
| | | <el-col :span="6"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon"> |
| | | <el-icon color="#409eff"><Trophy /></el-icon> |
| | | <div class="icon-container blue"> |
| | | <el-icon><Trophy /></el-icon> |
| | | </div> |
| | | <div class="stat-content"> |
| | | <div class="stat-number">{{ stats.activeActivities }}</div> |
| | | <div class="stat-label">当前进行比赛</div> |
| | | </div> |
| | | <div class="stat-number">{{ stats.activeActivities }}</div> |
| | | <div class="stat-title">当前比赛</div> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon"> |
| | | <el-icon color="#67c23a"><UserFilled /></el-icon> |
| | | <div class="icon-container green"> |
| | | <el-icon><UserFilled /></el-icon> |
| | | </div> |
| | | <div class="stat-content"> |
| | | <div class="stat-number">{{ stats.totalPlayers }}</div> |
| | | <div class="stat-label">参赛总人数</div> |
| | | </div> |
| | | <div class="stat-number">{{ stats.totalPlayers }}</div> |
| | | <div class="stat-title">参赛总人数</div> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon"> |
| | | <el-icon color="#e6a23c"><Clock /></el-icon> |
| | | <div class="icon-container yellow"> |
| | | <el-icon><Clock /></el-icon> |
| | | </div> |
| | | <div class="stat-content"> |
| | | <div class="stat-number">{{ stats.pendingReviews }}</div> |
| | | <div class="stat-label">报名待审核</div> |
| | | </div> |
| | | <div class="stat-number">{{ stats.pendingReviews }}</div> |
| | | <div class="stat-title">报名待审核</div> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon"> |
| | | <el-icon color="#f56c6c"><User /></el-icon> |
| | | <div class="icon-container red"> |
| | | <el-icon><User /></el-icon> |
| | | </div> |
| | | <div class="stat-content"> |
| | | <div class="stat-number">{{ stats.totalJudges }}</div> |
| | | <div class="stat-label">评委总数</div> |
| | | </div> |
| | | <div class="stat-number">{{ stats.totalJudges }}</div> |
| | | <div class="stat-title">评委总数</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 最近活动 --> |
| | | <div class="page-card"> |
| | | <h3 class="card-title">最近比赛</h3> |
| | | <el-table :data="recentActivities" style="width: 100%"> |
| | | <el-table-column prop="name" label="比赛名称" /> |
| | | <div class="table-card"> |
| | | <div class="table-header"> |
| | | <h3 class="table-title">最近比赛</h3> |
| | | <el-button type="primary" @click="$router.push('/activity')">查看全部</el-button> |
| | | </div> |
| | | <el-table :data="recentActivities" class="recent-table"> |
| | | <el-table-column prop="name" label="比赛名称" width="180" /> |
| | | <el-table-column prop="playerCount" label="报名人数" width="120" /> |
| | | <el-table-column prop="startTime" label="比赛时间" width="180" /> |
| | | <el-table-column prop="startTime" label="开始时间" width="180" /> |
| | | <el-table-column prop="endTime" label="结束时间" width="180" /> |
| | | <el-table-column prop="status" label="状态" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag> |
| | | <span :class="getStatusClass(row.status)">{{ row.status }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="150"> |
| | | <template #default="{ row }"> |
| | | <el-button type="primary" size="small" @click="viewActivity(row)">查看</el-button> |
| | | <el-button type="success" size="small" @click="manageActivity(row)">管理</el-button> |
| | | <el-table-column label="操作"> |
| | | <template #default="scope"> |
| | | <a class="action-link" @click="viewActivity(scope.row)">查看</a> |
| | | <a class="action-link" @click="manageActivity(scope.row)">管理</a> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | name: activity.name, |
| | | playerCount: activity.playerCount || 0, |
| | | startTime: activity.matchTime || activity.createTime, |
| | | endTime: activity.endTime || '待定', |
| | | status: activity.stateName || '未知' |
| | | })) |
| | | } catch (error) { |
| | |
| | | loadRecentActivities() |
| | | }) |
| | | |
| | | // 获取状态标签类型 |
| | | const getStatusType = (status: string) => { |
| | | const typeMap: Record<string, string> = { |
| | | '进行中': 'success', |
| | | '报名中': 'warning', |
| | | '待开始': 'info', |
| | | '已结束': 'info' |
| | | } |
| | | return typeMap[status] || 'info' |
| | | } |
| | | |
| | | // 查看比赛 |
| | | const viewActivity = (activity: any) => { |
| | | router.push(`/activity/${activity.id}`) |
| | |
| | | const manageActivity = (activity: any) => { |
| | | router.push('/activity') |
| | | } |
| | | |
| | | // 获取状态样式类 |
| | | const getStatusClass = (status: string) => { |
| | | const statusMap: Record<string, string> = { |
| | | '已发布': 'status-published', |
| | | '进行中': 'status-published', |
| | | '未发布': 'status-unpublished', |
| | | '报名中': 'status-unpublished', |
| | | '关闭': 'status-closed', |
| | | '已结束': 'status-closed', |
| | | '待开始': 'status-unpublished' |
| | | } |
| | | return statusMap[status] || 'status-unpublished' |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | <style scoped> |
| | | /* 页面整体样式 */ |
| | | .dashboard { |
| | | .stats-row { |
| | | margin-bottom: 20px; |
| | | padding: 24px; |
| | | background-color: #FFFFFF; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | /* 统计卡片行 */ |
| | | .stats-row { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | /* 统计卡片样式 */ |
| | | .stat-card { |
| | | background: #FFFFFF; |
| | | border-radius: 12px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); |
| | | border: none; |
| | | padding: 24px; |
| | | height: 120px; |
| | | position: relative; |
| | | overflow: hidden; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .stat-card:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); |
| | | } |
| | | |
| | | /* 图标容器 */ |
| | | .icon-container { |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | position: absolute; |
| | | top: 24px; |
| | | left: 24px; |
| | | } |
| | | |
| | | .icon-container.blue { |
| | | background-color: #E0E7FF; |
| | | color: #6366F1; |
| | | } |
| | | |
| | | .icon-container.green { |
| | | background-color: #D1FAE5; |
| | | color: #10B981; |
| | | } |
| | | |
| | | .icon-container.yellow { |
| | | background-color: #FEF3C7; |
| | | color: #F59E0B; |
| | | } |
| | | |
| | | .icon-container.red { |
| | | background-color: #FECACA; |
| | | color: #EF4444; |
| | | } |
| | | |
| | | /* 统计数字 */ |
| | | .stat-number { |
| | | font-size: 32px; |
| | | font-weight: 700; |
| | | color: #1F2937; |
| | | position: absolute; |
| | | top: 24px; |
| | | right: 24px; |
| | | line-height: 1; |
| | | } |
| | | |
| | | /* 统计标题 */ |
| | | .stat-title { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #6B7280; |
| | | position: absolute; |
| | | bottom: 24px; |
| | | left: 24px; |
| | | } |
| | | |
| | | /* 表格卡片 */ |
| | | .table-card { |
| | | background: #FFFFFF; |
| | | border-radius: 12px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); |
| | | border: none; |
| | | padding: 24px; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | /* 表格头部 */ |
| | | .table-header { |
| | | margin-bottom: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .table-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #1F2937; |
| | | margin: 0; |
| | | } |
| | | |
| | | /* 表格样式 */ |
| | | .recent-table { |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.el-table__header) { |
| | | background-color: #F9FAFB; |
| | | } |
| | | |
| | | :deep(.el-table__header th) { |
| | | background-color: #F9FAFB !important; |
| | | color: #374151; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | height: 48px; |
| | | border-bottom: 1px solid #E5E7EB; |
| | | } |
| | | |
| | | :deep(.el-table__row) { |
| | | height: 56px; |
| | | } |
| | | |
| | | :deep(.el-table__row:nth-child(even)) { |
| | | background-color: #F9FAFB; |
| | | } |
| | | |
| | | :deep(.el-table__row:nth-child(odd)) { |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | :deep(.el-table td) { |
| | | color: #1F2937; |
| | | font-size: 14px; |
| | | font-weight: 400; |
| | | border-bottom: 1px solid #F3F4F6; |
| | | } |
| | | |
| | | /* 状态标签样式 */ |
| | | .status-published { |
| | | color: #67C23A; |
| | | background-color: #F0F9FF; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .status-unpublished { |
| | | color: #E6A23C; |
| | | background-color: #FDF6EC; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .status-closed { |
| | | color: #F56C6C; |
| | | background-color: #FEF0F0; |
| | | padding: 4px 8px; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | /* 操作链接样式 */ |
| | | .action-link { |
| | | color: #409EFF; |
| | | cursor: pointer; |
| | | font-size: 14px; |
| | | margin: 0 8px; |
| | | text-decoration: none; |
| | | } |
| | | |
| | | .action-link:hover { |
| | | color: #66B1FF; |
| | | text-decoration: underline; |
| | | } |
| | | |
| | | .action-link:first-child { |
| | | margin-left: 0; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .dashboard { |
| | | padding: 16px; |
| | | } |
| | | |
| | | .stat-card { |
| | | background: white; |
| | | border-radius: 8px; |
| | | padding: 20px; |
| | | display: flex; |
| | | align-items: center; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | |
| | | .stat-icon { |
| | | font-size: 40px; |
| | | margin-right: 16px; |
| | | } |
| | | |
| | | .stat-content { |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .card-title { |
| | | margin-bottom: 20px; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .quick-btn { |
| | | width: 100%; |
| | | height: 60px; |
| | | font-size: 14px; |
| | | |
| | | .el-icon { |
| | | margin-right: 8px; |
| | | } |
| | | margin-bottom: 16px; |
| | | } |
| | | } |
| | | </style> |