feat: add problem name distribution and problem×class matrix to statistics

This commit is contained in:
hmo
2026-04-27 19:37:25 +08:00
parent dcc0457848
commit 3e9d899178
2 changed files with 100 additions and 1 deletions
+78 -1
View File
@@ -81,6 +81,31 @@
</div>
</div>
<!-- 问题分布 -->
<div class="row mb-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title"><i class="bi bi-bar-chart"></i> 各类问题分布</h5>
<canvas id="problemNameChart"></canvas>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title"><i class="bi bi-grid-3x3-gap"></i> 问题×班级矩阵</h5>
<div class="table-responsive" style="max-height: 300px; overflow-y: auto;">
<table class="table table-sm table-bordered text-center small" id="problemClassMatrix">
<thead id="problemClassMatrixHead"></thead>
<tbody id="problemClassMatrixBody"></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- 班级统计 -->
<div class="row">
<div class="col-md-6">
@@ -105,7 +130,7 @@
{% block extra_js %}
<script>
let severityChart, levelChart, classStudentChart, classProblemChart;
let severityChart, levelChart, classStudentChart, classProblemChart, problemNameChart;
async function loadStatistics() {
try {
@@ -191,6 +216,58 @@ async function loadStatistics() {
html += `<td><strong>${grandTotal}</strong></td></tr>`;
matrixBody.innerHTML = html;
// 问题名称分布图
const problemNames = Object.keys(data.problem_name_distribution || {});
const problemCounts = Object.values(data.problem_name_distribution || {});
const pnCtx = document.getElementById('problemNameChart').getContext('2d');
if (problemNameChart) problemNameChart.destroy();
problemNameChart = new Chart(pnCtx, {
type: 'bar',
data: {
labels: problemNames,
datasets: [{
label: '出现次数',
data: problemCounts,
backgroundColor: '#0d6efd',
}]
},
options: {
indexAxis: 'y',
responsive: true,
plugins: {
legend: { display: false }
},
scales: {
x: { beginAtZero: true }
}
}
});
// 问题×班级矩阵表
const classes = data.classes || [];
const pcmHead = document.getElementById('problemClassMatrixHead');
let headHtml = '<tr><th>问题</th>';
for (const c of classes) {
headHtml += `<th>${c.name}</th>`;
}
headHtml += '<th>合计</th></tr>';
pcmHead.innerHTML = headHtml;
const pcmBody = document.getElementById('problemClassMatrixBody');
let bodyHtml = '';
const pcmData = data.problem_class_matrix || [];
for (const row of pcmData) {
let rowTotal = 0;
bodyHtml += `<tr><td>${row.problem_name}</td>`;
for (const c of classes) {
const count = row[`class_${c.id}`] || 0;
bodyHtml += `<td>${count}</td>`;
rowTotal += count;
}
bodyHtml += `<td><strong>${rowTotal}</strong></td></tr>`;
}
pcmBody.innerHTML = bodyHtml;
// 班级学员条形图
const csCtx = document.getElementById('classStudentChart').getContext('2d');
if (classStudentChart) classStudentChart.destroy();