You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

328 lines
12 KiB

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据分析 - 湖南大学选课系统分析</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
background-color: #f8f9fa;
}
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px 0;
margin-bottom: 30px;
}
.card {
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
.card-header {
background-color: #667eea;
color: white;
border-radius: 10px 10px 0 0;
}
.btn-primary {
background-color: #667eea;
border-color: #667eea;
}
.btn-primary:hover {
background-color: #5a6fd8;
border-color: #5a6fd8;
}
</style>
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/">湖南大学选课系统分析</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="/">首页</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/courses">课程列表</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/analysis">数据分析</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- 英雄区 -->
<div class="hero">
<div class="container">
<h1 class="display-4">数据分析</h1>
<p class="lead">深入分析选课系统数据,获取有价值的洞察</p>
</div>
</div>
<!-- 分析图表 -->
<div class="container mb-5">
<!-- 课程类型分布 -->
<div class="card">
<div class="card-header">
<h3>课程类型分布</h3>
</div>
<div class="card-body">
<div id="courseTypeChart" style="width: 100%; height: 400px;"></div>
</div>
</div>
<!-- 院系分布 -->
<div class="card">
<div class="card-header">
<h3>院系课程分布</h3>
</div>
<div class="card-body">
<div id="departmentChart" style="width: 100%; height: 400px;"></div>
</div>
</div>
<!-- 学分分布 -->
<div class="card">
<div class="card-header">
<h3>学分分布</h3>
</div>
<div class="card-body">
<div id="creditChart" style="width: 100%; height: 400px;"></div>
</div>
</div>
<!-- 课程使用率 -->
<div class="card">
<div class="card-header">
<h3>课程容量使用率</h3>
</div>
<div class="card-body">
<div id="usageRateChart" style="width: 100%; height: 400px;"></div>
</div>
</div>
<!-- 院系统计 -->
<div class="card">
<div class="card-header">
<h3>院系统计详情</h3>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>院系</th>
<th>课程数</th>
<th>总学分</th>
<th>总容量</th>
<th>总已选</th>
<th>使用率</th>
</tr>
</thead>
<tbody>
<tr th:each="dept : ${departmentStats}">
<td th:text="${dept.key}"></td>
<td th:text="${dept.value.courseCount}"></td>
<td th:text="${dept.value.totalCredits}"></td>
<td th:text="${dept.value.totalCapacity}"></td>
<td th:text="${dept.value.totalEnrolled}"></td>
<td th:text="${#numbers.formatDecimal(dept.value.usageRate, 0, 1)}%"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 页脚 -->
<footer class="bg-dark text-white py-4">
<div class="container text-center">
<p>&copy; 2024 湖南大学选课系统分析平台</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 初始化课程类型分布图表
fetch('/api/course-type-distribution')
.then(response => response.json())
.then(data => {
const types = Object.keys(data);
const counts = Object.values(data);
const chart = echarts.init(document.getElementById('courseTypeChart'));
chart.setOption({
title: {
text: '课程类型分布',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [{
name: '课程类型',
type: 'pie',
radius: '60%',
data: types.map((type, index) => ({
name: type,
value: counts[index]
})),
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
});
});
// 初始化院系分布图表
fetch('/api/department-distribution')
.then(response => response.json())
.then(data => {
const departments = Object.keys(data);
const counts = Object.values(data);
const chart = echarts.init(document.getElementById('departmentChart'));
chart.setOption({
title: {
text: '院系课程分布',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [{
name: '院系',
type: 'pie',
radius: '60%',
data: departments.map((dept, index) => ({
name: dept,
value: counts[index]
})),
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
});
});
// 初始化学分分布图表
fetch('/api/credit-distribution')
.then(response => response.json())
.then(data => {
const credits = Object.keys(data).map(Number).sort((a, b) => a - b);
const counts = credits.map(credit => data[credit]);
const chart = echarts.init(document.getElementById('creditChart'));
chart.setOption({
title: {
text: '学分分布',
left: 'center'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
data: credits.map(c => c + '学分'),
name: '学分'
},
yAxis: {
type: 'value',
name: '课程数'
},
series: [{
data: counts,
type: 'bar',
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: '#667eea'},
{offset: 1, color: '#764ba2'}
])
}
}]
});
});
// 初始化课程使用率图表
fetch('/api/top-courses')
.then(response => response.json())
.then(data => {
const courseNames = data.map(item => item.course_name);
const enrolledCounts = data.map(item => item.enrolled);
const chart = echarts.init(document.getElementById('usageRateChart'));
chart.setOption({
title: {
text: '热门课程使用率',
left: 'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
type: 'category',
data: courseNames,
axisLabel: {
rotate: 45
}
},
yAxis: {
type: 'value',
name: '已选人数'
},
series: [{
data: enrolledCounts,
type: 'bar',
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: '#667eea'},
{offset: 1, color: '#764ba2'}
])
}
}]
});
});
// 响应式调整
window.addEventListener('resize', function() {
const charts = ['courseTypeChart', 'departmentChart', 'creditChart', 'usageRateChart'];
charts.forEach(id => {
const chart = echarts.getInstanceByDom(document.getElementById(id));
if (chart) {
chart.resize();
}
});
});
</script>
</body>
</html>