|
|
<!DOCTYPE html>
|
|
|
<html lang="zh-CN">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>积分排名 - 课堂点名系统</title>
|
|
|
<!-- 引入静态CSS(确保路径正确) -->
|
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
|
</head>
|
|
|
<body>
|
|
|
<div class="container">
|
|
|
<!-- 页面头部 -->
|
|
|
<header>
|
|
|
<h1>学生积分排名管理</h1>
|
|
|
<a href="/" class="back-btn">← 返回首页</a>
|
|
|
</header>
|
|
|
|
|
|
<!-- 班级选择和导出按钮 -->
|
|
|
<div class="class-controls">
|
|
|
<div class="class-selector">
|
|
|
<label for="className">选择班级:</label>
|
|
|
<select id="className" onchange="loadClassData()">
|
|
|
<option value="软工K班" selected>软工K班</option>
|
|
|
<option value="计科A班">计科A班</option>
|
|
|
<option value="大数据B班">大数据B班</option>
|
|
|
<!-- 可根据实际班级添加选项 -->
|
|
|
</select>
|
|
|
</div>
|
|
|
<a href="/api/scores/export_detailed?class_name=软工K班" id="exportBtn" class="export-btn">
|
|
|
导出积分详单(Excel)
|
|
|
</a>
|
|
|
</div>
|
|
|
|
|
|
<!-- 积分可视化图表区域 -->
|
|
|
<div class="score-chart">
|
|
|
<h3>积分TOP5学生及点名次数统计</h3>
|
|
|
<div class="chart-container">
|
|
|
{% if chart_base64 %}
|
|
|
<!-- 显示后端生成的图表(Base64格式) -->
|
|
|
<img src="data:image/png;base64,{{ chart_base64 }}" alt="积分与点名次数图表" class="chart-img">
|
|
|
{% else %}
|
|
|
<p class="no-data">暂无数据,无法生成图表(请先导入学生并点名)</p>
|
|
|
{% endif %}
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 积分排名表格 -->
|
|
|
<div class="score-table">
|
|
|
<h3>班级积分详情</h3>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>排名</th>
|
|
|
<th>学号</th>
|
|
|
<th>姓名</th>
|
|
|
<th>专业</th>
|
|
|
<th>随机点名次数</th>
|
|
|
<th>总积分</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="scoreTableBody">
|
|
|
<!-- 数据将通过JS动态加载 -->
|
|
|
<tr><td colspan="6" class="loading">加载中...</td></tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
// 页面加载时自动加载当前班级数据
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
loadClassData();
|
|
|
});
|
|
|
|
|
|
// 加载指定班级的积分数据
|
|
|
function loadClassData() {
|
|
|
// 获取选中的班级名称
|
|
|
const className = document.getElementById('className').value;
|
|
|
const tableBody = document.getElementById('scoreTableBody');
|
|
|
const exportBtn = document.getElementById('exportBtn');
|
|
|
|
|
|
// 更新导出按钮的链接(关联当前班级)
|
|
|
exportBtn.href = `/api/scores/export_detailed?class_name=${encodeURIComponent(className)}`;
|
|
|
|
|
|
// 清空表格并显示加载状态
|
|
|
tableBody.innerHTML = '<tr><td colspan="6" class="loading">加载中...</td></tr>';
|
|
|
|
|
|
// 调用后端API获取积分排名数据
|
|
|
fetch(`/api/scores/ranking?class_name=${encodeURIComponent(className)}`)
|
|
|
.then(response => {
|
|
|
if (!response.ok) {
|
|
|
throw new Error('数据加载失败');
|
|
|
}
|
|
|
return response.json();
|
|
|
})
|
|
|
.then(data => {
|
|
|
if (data.success && data.data.length > 0) {
|
|
|
// 渲染表格数据
|
|
|
renderScoreTable(data.data, tableBody);
|
|
|
} else {
|
|
|
// 无数据时显示提示
|
|
|
tableBody.innerHTML = '<tr><td colspan="6" class="no-data">暂无该班级学生数据(请先导入学生名单)</td></tr>';
|
|
|
}
|
|
|
})
|
|
|
.catch(error => {
|
|
|
// 错误处理
|
|
|
tableBody.innerHTML = '<tr><td colspan="6" class="error">加载失败:' + error.message + '</td></tr>';
|
|
|
console.error('积分数据加载错误:', error);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 渲染积分表格
|
|
|
function renderScoreTable(students, tableBody) {
|
|
|
let html = '';
|
|
|
students.forEach((student, index) => {
|
|
|
html += `
|
|
|
<tr>
|
|
|
<td class="rank">${index + 1}</td>
|
|
|
<td>${student.student_id}</td>
|
|
|
<td>${student.name}</td>
|
|
|
<td>${student.major}</td>
|
|
|
<td>${student.call_count}</td>
|
|
|
<td class="total-score ${student.total_score >= 0 ? 'positive' : 'negative'}">
|
|
|
${student.total_score.toFixed(1)}
|
|
|
</td>
|
|
|
</tr>
|
|
|
`;
|
|
|
});
|
|
|
tableBody.innerHTML = html;
|
|
|
}
|
|
|
</script>
|
|
|
</body>
|
|
|
</html> |