- 前后端分离架构 (Nuxt 3 + Element Plus) - SQLite 数据库 (better-sqlite3) - 比赛项目管理 (田赛/径赛/团体赛) - 队伍管理 (5 个组别) - 成绩录入与积分统计 - 记分板展示 (排名/奖牌榜) - 移动端响应式适配 - 侧边栏布局 + 抽屉菜单 - 自动生成初始化数据接口
214 lines
5.2 KiB
Vue
214 lines
5.2 KiB
Vue
<template>
|
||
<div class="home-container">
|
||
<el-card class="welcome-card">
|
||
<h1>欢迎使用运动会记分板系统</h1>
|
||
<p>本系统用于管理运动会的比赛项目、队伍和成绩</p>
|
||
</el-card>
|
||
|
||
<el-row :gutter="20" class="stats-row">
|
||
<el-col :xs="12" :sm="12" :md="6" :lg="6">
|
||
<el-card class="stat-card">
|
||
<div class="stat-content">
|
||
<el-icon class="stat-icon" color="#409eff"><Trophy /></el-icon>
|
||
<div>
|
||
<div class="stat-value">{{ stats.events }}</div>
|
||
<div class="stat-label">比赛项目</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :xs="12" :sm="12" :md="6" :lg="6">
|
||
<el-card class="stat-card">
|
||
<div class="stat-content">
|
||
<el-icon class="stat-icon" color="#67c23a"><UserFilled /></el-icon>
|
||
<div>
|
||
<div class="stat-value">{{ stats.teams }}</div>
|
||
<div class="stat-label">参赛队伍</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :xs="12" :sm="12" :md="6" :lg="6">
|
||
<el-card class="stat-card">
|
||
<div class="stat-content">
|
||
<el-icon class="stat-icon" color="#e6a23c"><Edit /></el-icon>
|
||
<div>
|
||
<div class="stat-value">{{ stats.results }}</div>
|
||
<div class="stat-label">成绩记录</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :xs="12" :sm="12" :md="6" :lg="6">
|
||
<el-card class="stat-card">
|
||
<div class="stat-content">
|
||
<el-icon class="stat-icon" color="#f56c6c"><DataLine /></el-icon>
|
||
<div>
|
||
<div class="stat-value">{{ stats.categories }}</div>
|
||
<div class="stat-label">比赛类别</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20">
|
||
<el-col :xs="24" :sm="24" :md="12" :lg="12">
|
||
<el-card>
|
||
<template #header>
|
||
<span>快速操作</span>
|
||
</template>
|
||
<div class="quick-actions">
|
||
<el-row :gutter="10">
|
||
<el-col :span="12">
|
||
<el-button type="primary" class="action-btn" @click="navigateTo('/events')">管理比赛项目</el-button>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-button type="success" class="action-btn" @click="navigateTo('/teams')">管理队伍</el-button>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-button type="warning" class="action-btn" @click="navigateTo('/results')">录入成绩</el-button>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-button type="info" class="action-btn" @click="navigateTo('/scoreboard')">查看记分板</el-button>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :xs="24" :sm="24" :md="12" :lg="12">
|
||
<el-card>
|
||
<template #header>
|
||
<span>系统说明</span>
|
||
</template>
|
||
<ul class="system-info">
|
||
<li>田赛:跳高、跳远、掷铅球</li>
|
||
<li>径赛:100m、200m、400m、4×100m、4×400m、20×50m</li>
|
||
<li>团体赛:旱地龙舟、跳长绳、折返跑</li>
|
||
<li>组别:教师组、航空班组、体育班组、文化班甲组、文化班乙组</li>
|
||
</ul>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { Trophy, UserFilled, Edit, DataLine } from '@element-plus/icons-vue'
|
||
|
||
const stats = ref({
|
||
events: 0,
|
||
teams: 0,
|
||
results: 0,
|
||
categories: 3
|
||
})
|
||
|
||
onMounted(async () => {
|
||
try {
|
||
const [eventsRes, teamsRes, resultsRes] = await Promise.all([
|
||
$fetch('/api/events'),
|
||
$fetch('/api/teams'),
|
||
$fetch('/api/results')
|
||
])
|
||
|
||
stats.value.events = eventsRes.data?.length || 0
|
||
stats.value.teams = teamsRes.data?.length || 0
|
||
stats.value.results = resultsRes.data?.length || 0
|
||
} catch (error) {
|
||
console.error('Failed to load stats:', error)
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.home-container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.welcome-card {
|
||
margin-bottom: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.welcome-card h1 {
|
||
color: #303133;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.welcome-card p {
|
||
color: #909399;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.stats-row {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.stat-card {
|
||
text-align: center;
|
||
}
|
||
|
||
.stat-content {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.stat-icon {
|
||
font-size: 40px;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 32px;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 14px;
|
||
color: #909399;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.quick-actions {
|
||
display: block;
|
||
}
|
||
|
||
.quick-actions .action-btn {
|
||
width: 100%;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.system-info {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
.system-info li {
|
||
padding: 8px 0;
|
||
border-bottom: 1px solid #ebeef5;
|
||
color: #606266;
|
||
}
|
||
|
||
.system-info li:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
@media (max-width: 900px) {
|
||
.stat-value {
|
||
font-size: 24px;
|
||
}
|
||
|
||
.stat-icon {
|
||
font-size: 28px;
|
||
}
|
||
|
||
.stats-row :deep(.el-col) {
|
||
margin-bottom: 12px;
|
||
}
|
||
}
|
||
</style>
|