Files
report-admin/templates/era2/components/charts_overview.js.html
T
lofyerandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> 71db82393a Initial commit
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-07-13 15:38:41 +08:00

215 lines
10 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.
{# 第一部分:总体概览的所有图表 #}
<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>