Files
ojnext/public/flowchart-data.html
yuetsh 1cb96a1073
Some checks failed
Deploy / deploy (push) Has been cancelled
add flowchart dead data info
2025-12-13 17:48:31 +08:00

329 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python流程图作业 - 学情分析看板</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts-wordcloud@2.1.0/dist/echarts-wordcloud.min.js"></script>
<style>
:root {
--bg-color: #f0f2f5;
--card-bg: #ffffff;
--primary: #1890ff;
--text-main: #333;
--text-secondary: #666;
}
body {
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
background-color: var(--bg-color);
margin: 0;
padding: 20px;
}
.header {
text-align: center;
margin-bottom: 20px;
}
.header h1 { color: var(--text-main); margin: 0; }
.header p { color: var(--text-secondary); margin-top: 5px; }
/* 顶部概览卡片 */
.overview-container {
display: flex;
justify-content: space-between;
gap: 20px;
margin-bottom: 20px;
}
.card {
background: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
flex: 1;
transition: transform 0.3s;
}
.card:hover { transform: translateY(-5px); }
.stat-title { font-size: 14px; color: var(--text-secondary); }
.stat-value { font-size: 28px; font-weight: bold; color: var(--text-main); margin-top: 10px; }
.stat-sub { font-size: 12px; color: #52c41a; margin-top: 5px; }
/* 图表布局 */
.charts-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 20px;
}
.chart-box {
background: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
height: 400px;
}
.chart-title {
font-size: 16px;
font-weight: bold;
border-left: 4px solid var(--primary);
padding-left: 10px;
margin-bottom: 15px;
}
/* 学生列表 */
.student-list {
background: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 12px; border-bottom: 1px solid #eee; }
th { background-color: #fafafa; color: var(--text-secondary); }
.tag {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
}
.tag-S { background: #fff7e6; color: #fa8c16; }
.tag-A { background: #e6f7ff; color: #1890ff; }
.tag-B { background: #f6ffed; color: #52c41a; }
.tag-C { background: #fff1f0; color: #f5222d; }
</style>
</head>
<body>
<div class="overview-container">
<div class="card">
<div class="stat-title">班级平均分</div>
<div class="stat-value" id="avgScore">0</div>
<div class="stat-sub">↑ 比上周For循环 +2.5分</div>
</div>
<div class="card">
<div class="stat-title">S+A 级别(卓越+优秀)人数</div>
<div class="stat-value" id="countA">0</div>
<div class="stat-sub">占比 35.7%</div>
</div>
<div class="card">
<div class="stat-title">未掌握核心难点</div>
<div class="stat-value" style="color: #f5222d; font-size: 24px;">循环条件</div>
<div class="stat-sub">需重点讲解 a<100 边界</div>
</div>
</div>
<div class="charts-grid">
<div class="chart-box">
<div class="chart-title">作业评级分布</div>
<div id="pieChart" style="width: 100%; height: 340px;"></div>
</div>
<div class="chart-box">
<div class="chart-title">薄弱知识点词云 (AI分析)</div>
<div id="wordCloud" style="width: 100%; height: 340px;"></div>
</div>
</div>
<div class="charts-grid">
<div class="chart-box" style="grid-column: span 2;">
<div class="chart-title">全班分数段统计</div>
<div id="barChart" style="width: 100%; height: 340px;"></div>
</div>
</div>
<script>
// --- 1. 模拟数据生成 (40位同学) ---
const totalStudents = 40;
const students = [];
const familyNames = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨";
// 精确分配等级人数S 10% (4人), A 15% (6人), B 50% (20人), C 15% (6人), D 10% (4人)
const gradeDistribution = {
S: 4, // 10% = 4人
A: 6, // 15% = 6人
B: 20, // 50% = 20人
C: 6, // 15% = 6人
D: 4 // 10% = 4人
};
let gradeCounts = { S: 0, A: 0, B: 0, C: 0, D: 0 };
let totalScore = 0;
// 创建等级数组,确保精确分配
let levelQueue = [];
for (let level in gradeDistribution) {
for (let i = 0; i < gradeDistribution[level]; i++) {
levelQueue.push(level);
}
}
// 打乱顺序
for (let i = levelQueue.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[levelQueue[i], levelQueue[j]] = [levelQueue[j], levelQueue[i]];
}
for (let i = 1; i <= totalStudents; i++) {
let score;
let level = levelQueue[i - 1];
// 根据等级生成对应分数范围
if (level === 'S') {
// S级95-100
score = Math.floor(Math.random() * (100 - 95 + 1) + 95);
} else if (level === 'A') {
// A级85-94
score = Math.floor(Math.random() * (95 - 85) + 85);
} else if (level === 'B') {
// B级70-84
score = Math.floor(Math.random() * (85 - 70) + 70);
} else if (level === 'C') {
// C级60-69
score = Math.floor(Math.random() * (70 - 60) + 60);
} else {
// D级50-59
score = Math.floor(Math.random() * (60 - 50) + 50);
}
gradeCounts[level]++;
totalScore += score;
let comment = "";
if (level === 'S') comment = "完美!逻辑清晰,变量初始化正确,闭环完美,代码规范。";
else if (level === 'A') comment = "逻辑清晰,变量初始化正确,闭环完美。";
else if (level === 'B') comment = "整体逻辑正确,但部分连线方向有误。";
else if (level === 'C') comment = "循环条件判断错误,导致死循环或无法进入。";
else comment = "基础概念理解不足,需要重新学习。";
students.push({
id: 2025000 + i,
name: familyNames[i % familyNames.length] + "同学",
score: score,
level: level,
comment: comment
});
}
// --- 2. 填充顶部数据 ---
document.getElementById('avgScore').innerText = (totalScore / totalStudents).toFixed(1);
const excellentCount = gradeCounts.S + gradeCounts.A; // S级和A级合计
document.getElementById('countA').innerText = excellentCount;
// 更新占比显示
const excellentPercent = ((excellentCount / totalStudents) * 100).toFixed(1);
const countACard = document.getElementById('countA').parentElement;
countACard.querySelector('.stat-sub').innerText = `占比 ${excellentPercent}%`;
// --- 3. 初始化图表 ---
// A. 饼图 - 等级分布
const pieChart = echarts.init(document.getElementById('pieChart'));
pieChart.setOption({
tooltip: { trigger: 'item' },
legend: { top: '5%', left: 'center' },
color: ['#fa8c16', '#1890ff', '#52c41a', '#faad14', '#f5222d'],
series: [{
name: '评级占比',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 },
label: { show: false, position: 'center' },
emphasis: { label: { show: true, fontSize: 20, fontWeight: 'bold' } },
data: [
{ value: gradeCounts.S, name: 'S级 (卓越)' },
{ value: gradeCounts.A, name: 'A级 (优秀)' },
{ value: gradeCounts.B, name: 'B级 (良好)' },
{ value: gradeCounts.C, name: 'C级 (待改进)' }
]
}]
});
// B. 词云图 - 知识点掌握情况
// 这里重点突出“循环条件”
const wordChart = echarts.init(document.getElementById('wordCloud'));
wordChart.setOption({
tooltip: {},
series: [{
type: 'wordCloud',
gridSize: 2,
sizeRange: [12, 60], // 字体大小范围
rotationRange: [-45, 45],
shape: 'circle',
width: '100%',
height: '100%',
textStyle: {
fontFamily: 'sans-serif',
fontWeight: 'bold',
color: function () {
return 'rgb(' + [
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') + ')';
}
},
data: [
{ name: '循环条件', value: 150, textStyle: { color: 'red' } }, // 核心痛点
{ name: '变量初始化', value: 80 },
{ name: 'i=i+1', value: 70 },
{ name: 'a<100', value: 65 },
{ name: '死循环', value: 60 },
{ name: '连线方向', value: 50 },
{ name: '退出逻辑', value: 45 },
{ name: 'While语法', value: 40 },
{ name: 'Print缩进', value: 35 },
{ name: 'Yes/No分支', value: 30 },
{ name: '流程结束符', value: 25 },
{ name: '变量定义', value: 20 }
]
}]
});
// C. 柱状图 - 分数段
const barChart = echarts.init(document.getElementById('barChart'));
// 简单的分段统计
let ranges = { '90-100': 0, '80-89': 0, '70-79': 0, '60-69': 0, '<60': 0 };
students.forEach(s => {
if (s.score >= 90) ranges['90-100']++;
else if (s.score >= 80) ranges['80-89']++;
else if (s.score >= 70) ranges['70-79']++;
else if (s.score >= 60) ranges['60-69']++;
else ranges['<60']++;
});
barChart.setOption({
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: { type: 'category', data: Object.keys(ranges) },
yAxis: { type: 'value' },
series: [{
name: '人数',
type: 'bar',
barWidth: '50%',
data: Object.values(ranges),
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
}
}]
});
// 窗口缩放适配
window.addEventListener('resize', function() {
pieChart.resize();
wordChart.resize();
barChart.resize();
});
</script>
</body>
</html>