Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
215 lines
10 KiB
HTML
215 lines
10 KiB
HTML
{# 第一部分:总体概览的所有图表 #}
|
||
<script>
|
||
// ===== 1. 得分对比横向条形图 =====
|
||
const scoreCompare = {{ score_compare_data | tojson }};
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('score-compare-chart'));
|
||
const cats = scoreCompare.categories.map(tDim);
|
||
const option = {
|
||
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
|
||
legend: { data: [scoreCompare.school_name, I18N.ec_district_avg, I18N.ec_same_type_avg], bottom: 5, textStyle: { fontSize: 12 } },
|
||
grid: { left: '3%', right: '8%', bottom: '18%', top: '5%', containLabel: true },
|
||
xAxis: { type: 'value', min: 30, max: 80 },
|
||
yAxis: { type: 'category', data: cats, axisLabel: { fontSize: 12 } },
|
||
series: [
|
||
{ name: scoreCompare.school_name, type: 'bar', data: scoreCompare.school_values,
|
||
itemStyle: { color: COLORS.primary }, barWidth: '22%',
|
||
label: { show: true, position: 'right', fontSize: 11 } },
|
||
{ name: I18N.ec_district_avg, type: 'bar', data: scoreCompare.district_avg,
|
||
itemStyle: { color: COLORS.gray }, barWidth: '22%' },
|
||
{ name: I18N.ec_same_type_avg, type: 'bar', data: scoreCompare.same_type_avg,
|
||
itemStyle: { color: COLORS.warning }, barWidth: '22%' },
|
||
],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
|
||
// ===== 2. 七维度雷达图 =====
|
||
const radarData = {{ radar_data | tojson }};
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('radar-chart'));
|
||
const option = {
|
||
tooltip: {},
|
||
legend: { data: radarData.legend, bottom: 10 },
|
||
radar: {
|
||
indicator: radarData.dimensions.map(d => ({ name: tDim(d), max: 80 })),
|
||
shape: 'polygon', splitNumber: 4,
|
||
axisName: { color: '#333', fontSize: 12 }, radius: '65%',
|
||
},
|
||
series: [{
|
||
type: 'radar',
|
||
data: radarData.series.map((s, i) => ({
|
||
value: s.values, name: s.name,
|
||
areaStyle: { opacity: i === 0 ? 0.3 : 0.1 },
|
||
lineStyle: { width: i === 0 ? 3 : 1 },
|
||
})),
|
||
}],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
|
||
// ===== 3. 聚类类型分布饼图 =====
|
||
const clusterDist = {{ cluster_type_dist_data | tojson }};
|
||
if (clusterDist.total) {
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('cluster-type-dist-chart'));
|
||
const labelFormatter = LANG === 'en' ? '{b}\n{c} ({d}%)' : '{b}\n{c}所 ({d}%)';
|
||
const belongsTo = (clusterDist.school_cluster === '较好' || clusterDist.school_cluster === 'High-Performing')
|
||
? I18N.ec_cluster_good_short
|
||
: I18N.ec_cluster_weak_short;
|
||
const centerText = clusterDist.school_name + '\n' + I18N.ec_belongs_to + ' ' + belongsTo;
|
||
const option = {
|
||
tooltip: { trigger: 'item' },
|
||
legend: { bottom: 5, textStyle: { fontSize: 11 } },
|
||
series: [{
|
||
type: 'pie', radius: ['35%', '60%'], center: ['50%', '45%'],
|
||
avoidLabelOverlap: true,
|
||
itemStyle: { borderRadius: 8, borderColor: '#fff', borderWidth: 2 },
|
||
label: { show: true, formatter: labelFormatter, fontSize: 12 },
|
||
emphasis: { label: { show: true, fontSize: 14, fontWeight: 'bold' } },
|
||
data: [
|
||
{ value: clusterDist.good_count, name: I18N.ec_cluster_good, itemStyle: { color: COLORS.primary } },
|
||
{ value: clusterDist.weak_count, name: I18N.ec_cluster_weak, itemStyle: { color: COLORS.warning } },
|
||
]
|
||
}],
|
||
graphic: [{
|
||
type: 'text', left: 'center', top: '40%',
|
||
style: {
|
||
text: centerText,
|
||
textAlign: 'center', fill: COLORS.primary, fontSize: 12, fontWeight: 'bold',
|
||
}
|
||
}],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
}
|
||
|
||
// ===== 4. 两类学校折线对比图 =====
|
||
const clusterLine = {{ cluster_line_compare_data | tojson }};
|
||
if (clusterLine.dimensions) {
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('cluster-line-chart'));
|
||
const goodLegend = I18N.ec_cluster_good_full.replace('{n}', clusterLine.good_count);
|
||
const weakLegend = I18N.ec_cluster_weak_full.replace('{n}', clusterLine.weak_count);
|
||
const option = {
|
||
tooltip: { trigger: 'axis' },
|
||
legend: { data: [goodLegend, weakLegend], bottom: 5, textStyle: { fontSize: 11 } },
|
||
grid: { left: '3%', right: '4%', bottom: '18%', top: '8%', containLabel: true },
|
||
xAxis: {
|
||
type: 'category', data: clusterLine.dimensions.map(shortDim),
|
||
axisLabel: { fontSize: 11, rotate: 15 }, boundaryGap: false,
|
||
},
|
||
yAxis: { type: 'value', min: 40, max: 60 },
|
||
series: [
|
||
{
|
||
name: goodLegend,
|
||
type: 'line', data: clusterLine.good_values,
|
||
lineStyle: { width: 3, color: COLORS.primary }, itemStyle: { color: COLORS.primary },
|
||
symbol: 'circle', symbolSize: 8,
|
||
label: { show: true, position: 'top', fontSize: 10, color: COLORS.primary, formatter: p => p.value.toFixed(2) },
|
||
},
|
||
{
|
||
name: weakLegend,
|
||
type: 'line', data: clusterLine.weak_values,
|
||
lineStyle: { width: 3, color: COLORS.warning }, itemStyle: { color: COLORS.warning },
|
||
symbol: 'circle', symbolSize: 8,
|
||
label: { show: true, position: 'bottom', fontSize: 10, color: COLORS.warning, formatter: p => p.value.toFixed(2) },
|
||
},
|
||
],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
}
|
||
|
||
// ===== 5. 聚类类型对比雷达图 =====
|
||
const clusterRadar = {{ cluster_radar_data | tojson }};
|
||
if (clusterRadar.dimensions) {
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('cluster-radar-chart'));
|
||
const colorMap = [COLORS.cluster_good, COLORS.cluster_weak, COLORS.danger];
|
||
const option = {
|
||
tooltip: {},
|
||
legend: {
|
||
data: clusterRadar.legend, bottom: 5, textStyle: { fontSize: 11 },
|
||
formatter: function(name) {
|
||
if (name === '课程实施较好类' || name === I18N.ec_cluster_good) return I18N.ec_cluster_good_full.replace('{n}', clusterRadar.good_count);
|
||
if (name === '课程实施待提升类' || name === I18N.ec_cluster_weak) return I18N.ec_cluster_weak_full.replace('{n}', clusterRadar.weak_count);
|
||
return name;
|
||
}
|
||
},
|
||
radar: {
|
||
indicator: clusterRadar.dimensions.map(d => ({ name: tDim(d), max: 80 })),
|
||
shape: 'polygon', splitNumber: 4,
|
||
axisName: { color: '#333', fontSize: 11 }, radius: '60%',
|
||
},
|
||
series: [{
|
||
type: 'radar',
|
||
data: clusterRadar.series.map((s, i) => ({
|
||
value: s.values, name: s.name,
|
||
areaStyle: { opacity: i === 2 ? 0.05 : 0.15 },
|
||
lineStyle: { width: i === 2 ? 3 : 2, type: i === 2 ? 'solid' : 'dashed', color: colorMap[i] },
|
||
itemStyle: { color: colorMap[i] },
|
||
symbol: i === 2 ? 'diamond' : 'circle', symbolSize: i === 2 ? 8 : 4,
|
||
})),
|
||
}],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
}
|
||
|
||
// ===== 6. 区内学校排名条形图 =====
|
||
const rankingData = {{ school_ranking_data | tojson }};
|
||
if (rankingData.schools) {
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('school-ranking-chart'));
|
||
const barColors = rankingData.schools.map(s => s === rankingData.current_school ? COLORS.primary : COLORS.gray);
|
||
const option = {
|
||
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
|
||
grid: { left: '3%', right: '12%', bottom: '5%', top: '5%', containLabel: true },
|
||
xAxis: { type: 'value', min: 35, max: 65 },
|
||
yAxis: { type: 'category', data: rankingData.schools.slice().reverse(),
|
||
axisLabel: { fontSize: 12, fontWeight: function(v) { return v === rankingData.current_school ? 'bold' : 'normal'; } } },
|
||
series: [{
|
||
type: 'bar', barWidth: '50%',
|
||
data: rankingData.total_scores.slice().reverse().map((v, i) => ({
|
||
value: v, itemStyle: { color: barColors.slice().reverse()[i] },
|
||
})),
|
||
label: { show: true, position: 'right', fontSize: 12, fontWeight: 'bold', formatter: p => p.value.toFixed(1) },
|
||
}],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
}
|
||
|
||
// ===== 7. 维度间相关性热力图 =====
|
||
const corrData = {{ correlation_data | tojson }};
|
||
if (corrData.dimensions) {
|
||
(function() {
|
||
const chart = echarts.init(document.getElementById('correlation-chart'));
|
||
const localizedDims = corrData.dimensions.map(tDim);
|
||
const names = (corrData.short_names && LANG === 'zh') ? corrData.short_names : localizedDims;
|
||
const option = {
|
||
tooltip: { position: 'top', formatter: p => localizedDims[p.value[0]] + ' × ' + localizedDims[p.value[1]] + '<br/>' + I18N.ec_correlation + ': ' + p.value[2] },
|
||
grid: { left: '15%', right: '12%', bottom: '18%', top: '3%' },
|
||
xAxis: { type: 'category', data: names, axisLabel: { rotate: 30, fontSize: 11 }, splitArea: { show: true } },
|
||
yAxis: { type: 'category', data: names, axisLabel: { fontSize: 11 }, splitArea: { show: true } },
|
||
visualMap: { min: -1, max: 1, calculable: true, orient: 'vertical', right: 0, top: 'center',
|
||
inRange: { color: ['#fee2e2', '#fef3c7', '#f3f4f6', '#dbeafe', '#2563eb'] }, textStyle: { fontSize: 11 } },
|
||
series: [{
|
||
type: 'heatmap', data: corrData.data,
|
||
label: { show: true, fontSize: 11, formatter: p => p.value[2].toFixed(2) },
|
||
itemStyle: { borderWidth: 2, borderColor: '#fff' },
|
||
}],
|
||
};
|
||
chart.setOption(option);
|
||
window.addEventListener('resize', () => chart.resize());
|
||
})();
|
||
}
|
||
</script>
|