934 lines
48 KiB
HTML
934 lines
48 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>云南省教育决策研究服务系统</title>
|
||
|
||
<!-- 外部资源引用 (全部使用CDN) -->
|
||
<!-- 1. Tailwind CSS -->
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
|
||
<!-- 2. Font Awesome 图标库 -->
|
||
<link rel="stylesheet" href="https://cdn.staticfile.net/font-awesome/4.7.0/css/font-awesome.min.css">
|
||
|
||
<!-- 3. jQuery -->
|
||
<script src="https://cdn.staticfile.net/jquery/3.6.4/jquery.min.js"></script>
|
||
|
||
<!-- 4. ECharts 库 -->
|
||
<script src="https://cdn.staticfile.net/echarts/5.4.3/echarts.min.js"></script>
|
||
|
||
<!-- 自定义样式 -->
|
||
<link rel="stylesheet" href="styles.css">
|
||
|
||
<!-- Tailwind 配置 -->
|
||
<script>
|
||
tailwind.config = {
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
primary: '#165DFF',
|
||
secondary: '#00C48C',
|
||
accent: '#722ED1',
|
||
dark: '#0F172A',
|
||
'dark-card': '#1E293B'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
</head>
|
||
<body class="bg-dark text-white min-h-screen flex flex-col">
|
||
<!-- 导航栏 -->
|
||
<header class="bg-dark-card border-b border-primary/20 px-6 py-4 sticky top-0 z-40">
|
||
<div class="container mx-auto flex justify-between items-center">
|
||
<div class="flex items-center space-x-3">
|
||
<i class="fa fa-bar-chart text-primary text-2xl"></i>
|
||
<h1 class="text-xl font-bold">云南省教育决策研究服务系统</h1>
|
||
</div>
|
||
<nav class="hidden md:flex space-x-6">
|
||
<a href="#" class="text-white hover:text-primary transition-colors">首页</a>
|
||
<a href="#" class="text-gray-400 hover:text-primary transition-colors">数据概览</a>
|
||
<a href="#" class="text-gray-400 hover:text-primary transition-colors">分析报告</a>
|
||
<a href="#" class="text-gray-400 hover:text-primary transition-colors">政策法规</a>
|
||
</nav>
|
||
<button class="md:hidden text-white text-xl">
|
||
<i class="fa fa-bars"></i>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- 主要内容区 -->
|
||
<main class="flex-grow container mx-auto p-6">
|
||
<!-- 数据概览卡片 -->
|
||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-6 hover:shadow-lg hover:shadow-primary/10 transition-all cursor-pointer" id="staffInfoBtn">
|
||
<div class="flex justify-between items-start mb-4">
|
||
<div>
|
||
<p class="text-gray-400 text-sm mb-1">教职工总数</p>
|
||
<h3 class="text-2xl font-bold">251,400</h3>
|
||
</div>
|
||
<div class="p-3 bg-primary/10 rounded-lg text-primary">
|
||
<i class="fa fa-users text-xl"></i>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center text-sm">
|
||
<span class="text-secondary flex items-center"><i class="fa fa-arrow-up mr-1"></i> 2.4%</span>
|
||
<span class="text-gray-400 ml-2">较上年增长</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-6 hover:shadow-lg hover:shadow-primary/10 transition-all cursor-pointer" id="schoolInfoBtn">
|
||
<div class="flex justify-between items-start mb-4">
|
||
<div>
|
||
<p class="text-gray-400 text-sm mb-1">学校总数</p>
|
||
<h3 class="text-2xl font-bold">13,804</h3>
|
||
</div>
|
||
<div class="p-3 bg-secondary/10 rounded-lg text-secondary">
|
||
<i class="fa fa-university text-xl"></i>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center text-sm">
|
||
<span class="text-secondary flex items-center"><i class="fa fa-arrow-up mr-1"></i> 1.2%</span>
|
||
<span class="text-gray-400 ml-2">较上年增长</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-6 hover:shadow-lg hover:shadow-primary/10 transition-all cursor-pointer" id="studentInfoBtn">
|
||
<div class="flex justify-between items-start mb-4">
|
||
<div>
|
||
<p class="text-gray-400 text-sm mb-1">在校生总数</p>
|
||
<h3 class="text-2xl font-bold">4,860,200</h3>
|
||
</div>
|
||
<div class="p-3 bg-accent/10 rounded-lg text-accent">
|
||
<i class="fa fa-graduation-cap text-xl"></i>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center text-sm">
|
||
<span class="text-red-400 flex items-center"><i class="fa fa-arrow-down mr-1"></i> 0.5%</span>
|
||
<span class="text-gray-400 ml-2">较上年下降</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-6 hover:shadow-lg hover:shadow-primary/10 transition-all cursor-pointer" id="graduateInfoBtn">
|
||
<div class="flex justify-between items-start mb-4">
|
||
<div>
|
||
<p class="text-gray-400 text-sm mb-1">毕业生总数</p>
|
||
<h3 class="text-2xl font-bold">1,256,800</h3>
|
||
</div>
|
||
<div class="p-3 bg-primary/10 rounded-lg text-primary">
|
||
<i class="fa fa-certificate text-xl"></i>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center text-sm">
|
||
<span class="text-secondary flex items-center"><i class="fa fa-arrow-up mr-1"></i> 1.8%</span>
|
||
<span class="text-gray-400 ml-2">较上年增长</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 图表区域 -->
|
||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-4 lg:col-span-2" style="height: 400px">
|
||
<div class="flex justify-between items-center mb-4 px-2">
|
||
<h3 class="font-semibold">人口变化总体趋势</h3>
|
||
<div class="flex space-x-2">
|
||
<button class="px-3 py-1 text-xs bg-primary/10 text-primary rounded-full">5年</button>
|
||
<button class="px-3 py-1 text-xs bg-gray-700 text-gray-300 rounded-full">10年</button>
|
||
<button class="px-3 py-1 text-xs bg-gray-700 text-gray-300 rounded-full">15年</button>
|
||
</div>
|
||
</div>
|
||
<div id="populationTrendChart" class="w-full h-[calc(100%-40px)]"></div>
|
||
</div>
|
||
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-4" style="height: 400px">
|
||
<div class="flex justify-between items-center mb-4 px-2">
|
||
<h3 class="font-semibold">云南省人口密度</h3>
|
||
<div class="flex space-x-2">
|
||
<button class="px-3 py-1 text-xs bg-primary/10 text-primary rounded-full">密度</button>
|
||
<button class="px-3 py-1 text-xs bg-gray-700 text-gray-300 rounded-full">分布</button>
|
||
</div>
|
||
</div>
|
||
<div id="populationMapChart" class="w-full h-[calc(100%-40px)]"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-4" style="height: 350px">
|
||
<div class="flex justify-between items-center mb-4 px-2">
|
||
<h3 class="font-semibold">义务教育阶段发展预测</h3>
|
||
<div class="flex space-x-2">
|
||
<button class="px-3 py-1 text-xs bg-primary/10 text-primary rounded-full">在校生</button>
|
||
<button class="px-3 py-1 text-xs bg-gray-700 text-gray-300 rounded-full">招生数</button>
|
||
</div>
|
||
</div>
|
||
<div id="educationForecastChart" class="w-full h-[calc(100%-40px)]"></div>
|
||
</div>
|
||
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 p-4" style="height: 350px">
|
||
<div class="flex justify-between items-center mb-4 px-2">
|
||
<h3 class="font-semibold">高中阶段教育发展预测</h3>
|
||
<div class="flex space-x-2">
|
||
<button class="px-3 py-1 text-xs bg-primary/10 text-primary rounded-full">在校生</button>
|
||
<button class="px-3 py-1 text-xs bg-gray-700 text-gray-300 rounded-full">招生数</button>
|
||
</div>
|
||
</div>
|
||
<div id="highSchoolChart" class="w-full h-[calc(100%-40px)]"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 手风琴区域 -->
|
||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 overflow-hidden backdrop-blur-sm bg-opacity-80 flex flex-col flex-grow">
|
||
<h3 class="bg-primary/10 px-5 py-3 font-semibold flex justify-between items-center cursor-pointer accordion-header">
|
||
<span>教育发展特征</span>
|
||
<i class="fa fa-chevron-down text-primary accordion-icon transition-transform duration-300 transform rotate-180"></i>
|
||
</h3>
|
||
<div class="accordion-content max-h-[500px] overflow-y-auto accordion-transition px-5 py-3 flex-grow">
|
||
<div class="py-3 border-b border-gray-700/50">
|
||
<p class="text-sm mb-1 text-gray-300">人口变化特征</p>
|
||
<p class="text-xs text-gray-400">总人口保持稳定,出生率持续下降,老龄化趋势明显</p>
|
||
</div>
|
||
<div class="py-3 border-b border-gray-700/50">
|
||
<p class="text-sm mb-1 text-gray-300">学生流动特征</p>
|
||
<p class="text-xs text-gray-400">农村学生向城镇转移趋势明显,优质教育资源竞争激烈</p>
|
||
</div>
|
||
<div class="py-3">
|
||
<p class="text-sm mb-1 text-gray-300">教育质量特征</p>
|
||
<p class="text-xs text-gray-400">整体教育质量稳步提升,但区域间发展不平衡</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-dark-card rounded-xl border border-primary/20 overflow-hidden backdrop-blur-sm bg-opacity-80 flex flex-col flex-grow">
|
||
<h3 class="bg-primary/10 px-5 py-3 font-semibold flex justify-between items-center cursor-pointer accordion-header">
|
||
<span>决策建议</span>
|
||
<i class="fa fa-chevron-down text-primary accordion-icon transition-transform duration-300 transform rotate-180"></i>
|
||
</h3>
|
||
<div class="accordion-content max-h-[500px] overflow-y-auto accordion-transition px-5 py-3 flex-grow">
|
||
<div class="py-3 border-b border-gray-700/50">
|
||
<p class="text-sm mb-1 text-gray-300">优化资源配置</p>
|
||
<p class="text-xs text-gray-400">根据人口变化趋势,调整学校布局和师资配置</p>
|
||
</div>
|
||
<div class="py-3 border-b border-gray-700/50">
|
||
<p class="text-sm mb-1 text-gray-300">促进教育公平</p>
|
||
<p class="text-xs text-gray-400">加大城市投入,缩小城乡差距</p>
|
||
</div>
|
||
<div class="py-3 border-b border-gray-700/50">
|
||
<p class="text-sm mb-1 text-gray-300">提升教育质量</p>
|
||
<p class="text-xs text-gray-400">加强教师队伍建设,推进教育教学改革</p>
|
||
</div>
|
||
<div class="py-3">
|
||
<p class="text-sm mb-1 text-gray-300">推动教育创新</p>
|
||
<p class="text-xs text-gray-400">利用信息技术促进教育现代化,提升教育治理水平</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- 页脚 -->
|
||
<footer class="bg-dark py-4 px-6 text-center text-gray-400 text-sm border-t border-primary/20">
|
||
<p>云南省教育决策研究服务系统 © 2025</p>
|
||
</footer>
|
||
|
||
<!-- 教职工信息弹出层 -->
|
||
<div id="staffInfoModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
|
||
<div class="bg-dark-card border border-primary/40 rounded-xl p-6 max-w-lg w-full mx-4 transform scale-95 transition-transform duration-300">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h3 class="text-xl font-bold text-white">教职工详细信息</h3>
|
||
<button class="close-modal text-gray-400 hover:text-white transition-colors">
|
||
<i class="fa fa-times text-xl"></i>
|
||
</button>
|
||
</div>
|
||
<div class="space-y-4" id="staffInfoContent">
|
||
<!-- 数据将通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 学校总数信息弹出层 -->
|
||
<div id="schoolInfoModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
|
||
<div class="bg-dark-card border border-primary/40 rounded-xl p-6 max-w-lg w-full mx-4 transform scale-95 transition-transform duration-300">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h3 class="text-xl font-bold text-white">学校分布详细信息</h3>
|
||
<button class="close-modal text-gray-400 hover:text-white transition-colors">
|
||
<i class="fa fa-times text-xl"></i>
|
||
</button>
|
||
</div>
|
||
<div class="space-y-4" id="schoolInfoContent">
|
||
<!-- 数据将通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 在校生总数信息弹出层 -->
|
||
<div id="studentInfoModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
|
||
<div class="bg-dark-card border border-primary/40 rounded-xl p-6 max-w-lg w-full mx-4 transform scale-95 transition-transform duration-300">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h3 class="text-xl font-bold text-white">在校生详细信息</h3>
|
||
<button class="close-modal text-gray-400 hover:text-white transition-colors">
|
||
<i class="fa fa-times text-xl"></i>
|
||
</button>
|
||
</div>
|
||
<div class="space-y-4" id="studentInfoContent">
|
||
<!-- 数据将通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 毕业生数信息弹出层 -->
|
||
<div id="graduateInfoModal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 opacity-0 pointer-events-none transition-opacity duration-300">
|
||
<div class="bg-dark-card border border-primary/40 rounded-xl p-6 max-w-lg w-full mx-4 transform scale-95 transition-transform duration-300">
|
||
<div class="flex justify-between items-center mb-4">
|
||
<h3 class="text-xl font-bold text-white">毕业生详细信息</h3>
|
||
<button class="close-modal text-gray-400 hover:text-white transition-colors">
|
||
<i class="fa fa-times text-xl"></i>
|
||
</button>
|
||
</div>
|
||
<div class="space-y-4" id="graduateInfoContent">
|
||
<!-- 数据将通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 初始化图表
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
// 1. 手风琴功能初始化
|
||
const accordionHeaders = document.querySelectorAll('.accordion-header');
|
||
accordionHeaders.forEach(header => {
|
||
const content = header.nextElementSibling;
|
||
const icon = header.querySelector('.accordion-icon');
|
||
// 确保手风琴默认展开
|
||
content.style.maxHeight = '500px';
|
||
content.style.padding = '12px 20px';
|
||
icon.classList.add('rotate-180');
|
||
|
||
header.addEventListener('click', () => {
|
||
if (content.style.maxHeight && content.style.maxHeight !== '0px') {
|
||
content.style.maxHeight = '0px';
|
||
content.style.height = '0';
|
||
content.style.padding = '0';
|
||
icon.classList.remove('rotate-180');
|
||
} else {
|
||
content.style.maxHeight = '500px';
|
||
content.style.height = 'auto';
|
||
content.style.padding = '12px 20px';
|
||
icon.classList.add('rotate-180');
|
||
}
|
||
});
|
||
});
|
||
|
||
// 2. 初始化图表实例
|
||
const educationForecastChart = echarts.init(document.getElementById('educationForecastChart'));
|
||
const populationMapChart = echarts.init(document.getElementById('populationMapChart'));
|
||
const highSchoolChart = echarts.init(document.getElementById('highSchoolChart'));
|
||
const populationTrendChart = echarts.init(document.getElementById('populationTrendChart'));
|
||
|
||
// 3. 加载地图数据并初始化地图图表
|
||
// 使用阿里云DataV提供的公开地图数据API
|
||
$.getJSON('https://geo.datav.aliyun.com/areas_v3/bound/530000_full.json', function(yunnanData) {
|
||
// 注册云南省地图
|
||
echarts.registerMap('yunnan', yunnanData);
|
||
|
||
// 云南省人口密度地图配置
|
||
const populationMapOption = {
|
||
tooltip: {trigger: 'item'},
|
||
legend: {top: 'bottom'},
|
||
series: [{
|
||
name: '人口密度',
|
||
type: 'map',
|
||
map: 'yunnan',
|
||
roam: true,
|
||
label: {show: true},
|
||
emphasis: {label: {show: true}},
|
||
data: [
|
||
{name: '昆明市', value: 630},
|
||
{name: '曲靖市', value: 234},
|
||
{name: '玉溪市', value: 145},
|
||
{name: '保山市', value: 115},
|
||
{name: '昭通市', value: 202},
|
||
{name: '丽江市', value: 57},
|
||
{name: '普洱市', value: 54},
|
||
{name: '临沧市', value: 88},
|
||
{name: '楚雄州', value: 93},
|
||
{name: '红河州', value: 147},
|
||
{name: '文山州', value: 118},
|
||
{name: '西双版纳州', value: 58},
|
||
{name: '大理州', value: 107},
|
||
{name: '德宏州', value: 142},
|
||
{name: '怒江州', value: 22},
|
||
{name: '迪庆州', value: 11}
|
||
]
|
||
}]
|
||
};
|
||
|
||
// 设置地图图表配置
|
||
populationMapChart.setOption(populationMapOption);
|
||
}).fail(function() {
|
||
console.error('地图数据加载失败,请检查网络连接或API地址');
|
||
// 显示错误提示
|
||
const mapContainer = document.getElementById('populationMapChart');
|
||
mapContainer.innerHTML = '<div class="flex items-center justify-center h-full text-red-400">地图数据加载失败</div>';
|
||
});
|
||
|
||
// 4. 义务教育阶段发展预测图表配置
|
||
const educationForecastOption = {
|
||
tooltip: {trigger: 'axis', axisPointer: {type: 'shadow'}},
|
||
legend: {data: ['在校生总数', '招生数'], textStyle: {color: '#86909C'}, top: 0},
|
||
grid: {left: '3%', right: '4%', bottom: '3%', containLabel: true},
|
||
xAxis: {type: 'category', data: ['2017', '2019', '2021', '2023', '2025', '2027', '2029'], axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}},
|
||
yAxis: {type: 'value', axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}, splitLine: {lineStyle: {color: '#1E293B'}}},
|
||
series: [
|
||
{
|
||
name: '在校生总数',
|
||
type: 'line',
|
||
smooth: true,
|
||
data: [437.8, 445.6, 439.2, 450.5, 441.7, 412.8, 371.8],
|
||
lineStyle: {color: '#165DFF'},
|
||
itemStyle: {color: '#165DFF'},
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{offset: 0, color: 'rgba(22, 93, 255, 0.5)'},
|
||
{offset: 1, color: 'rgba(22, 93, 255, 0)'}
|
||
])
|
||
}
|
||
},
|
||
{
|
||
name: '招生数',
|
||
type: 'line',
|
||
smooth: true,
|
||
data: [65.2, 63.8, 62.4, 61.1, 59.7, 58.3, 56.9],
|
||
lineStyle: {color: '#00C48C'},
|
||
itemStyle: {color: '#00C48C'},
|
||
areaStyle: {
|
||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||
{offset: 0, color: 'rgba(0, 196, 140, 0.5)'},
|
||
{offset: 1, color: 'rgba(0, 196, 140, 0)'}
|
||
])
|
||
}
|
||
}
|
||
]
|
||
};
|
||
|
||
// 5. 高中阶段教育发展预测图表配置
|
||
const highSchoolOption = {
|
||
tooltip: {trigger: 'axis'},
|
||
legend: {data: ['在校生总数', '招生数'], textStyle: {color: '#86909C'}, top: 0},
|
||
grid: {left: '3%', right: '4%', bottom: '3%', containLabel: true},
|
||
xAxis: {type: 'category', data: ['2017', '2019', '2021', '2023', '2025', '2027', '2029'], axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}},
|
||
yAxis: {type: 'value', axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}, splitLine: {lineStyle: {color: '#1E293B'}}},
|
||
series: [
|
||
{
|
||
name: '在校生总数',
|
||
type: 'line',
|
||
smooth: true,
|
||
data: [128.5, 136.2, 142.7, 156.1, 161.8, 163.1, 164.9],
|
||
lineStyle: {color: '#722ED1'},
|
||
itemStyle: {color: '#722ED1'}
|
||
},
|
||
{
|
||
name: '招生数',
|
||
type: 'line',
|
||
smooth: true,
|
||
data: [43.2, 45.8, 47.6, 52.3, 53.8, 54.2, 54.7],
|
||
lineStyle: {color: '#FF7D00'},
|
||
itemStyle: {color: '#FF7D00'}
|
||
}
|
||
]
|
||
};
|
||
|
||
// 6. 人口变化总体趋势图表配置
|
||
const populationTrendOption = {
|
||
tooltip: {trigger: 'axis', axisPointer: {type: 'shadow'}},
|
||
legend: {data: ['总人口', '出生率', '死亡率'], textStyle: {color: '#86909C'}, top: 0},
|
||
grid: {left: '3%', right: '4%', bottom: '3%', containLabel: true},
|
||
xAxis: [
|
||
{type: 'category', data: ['2017', '2019', '2021', '2023', '2025', '2027', '2029'], axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}}
|
||
],
|
||
yAxis: [
|
||
{type: 'value', name: '人口数(万)', min: 4500, max: 4900, interval: 100, axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}, splitLine: {lineStyle: {color: '#1E293B'}}},
|
||
{type: 'value', name: '出生率(‰)', min: 8, max: 15, interval: 1, axisLine: {lineStyle: {color: '#4E5969'}}, axisLabel: {color: '#86909C'}, splitLine: {show: false}}
|
||
],
|
||
series: [
|
||
{
|
||
name: '总人口',
|
||
type: 'bar',
|
||
data: [4770.5, 4808.3, 4830.5, 4850.3, 4860.2, 4865.1, 4868.3],
|
||
itemStyle: {color: '#165DFF'}
|
||
},
|
||
{
|
||
name: '出生率',
|
||
type: 'line',
|
||
yAxisIndex: 1,
|
||
data: [12.8, 11.5, 10.3, 9.6, 9.2, 9.0, 8.8],
|
||
lineStyle: {color: '#00C48C'},
|
||
itemStyle: {color: '#00C48C'}
|
||
},
|
||
{
|
||
name: '死亡率',
|
||
type: 'line',
|
||
yAxisIndex: 1,
|
||
data: [7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6],
|
||
lineStyle: {color: '#FF4D4F'},
|
||
itemStyle: {color: '#FF4D4F'}
|
||
}
|
||
]
|
||
};
|
||
|
||
// 7. 设置非地图图表配置
|
||
educationForecastChart.setOption(educationForecastOption);
|
||
highSchoolChart.setOption(highSchoolOption);
|
||
populationTrendChart.setOption(populationTrendOption);
|
||
|
||
// 8. 窗口大小变化时重新渲染图表
|
||
window.addEventListener('resize', function() {
|
||
educationForecastChart.resize();
|
||
if (populationMapChart) populationMapChart.resize();
|
||
highSchoolChart.resize();
|
||
populationTrendChart.resize();
|
||
});
|
||
|
||
// 9. 弹出层功能实现
|
||
function setupModal(btnId, modalId, contentId, title, dataFunc, renderFunc) {
|
||
const btn = document.getElementById(btnId);
|
||
const modal = document.getElementById(modalId);
|
||
const content = document.getElementById(contentId);
|
||
const closeBtns = modal.querySelectorAll('.close-modal');
|
||
|
||
// 打开模态框
|
||
btn.addEventListener('click', function() {
|
||
modal.style.opacity = '1';
|
||
modal.style.pointerEvents = 'auto';
|
||
modal.querySelector('div').style.transform = 'scale(1)';
|
||
|
||
// 加载并渲染数据
|
||
const data = dataFunc();
|
||
renderFunc(data, content);
|
||
});
|
||
|
||
// 关闭模态框
|
||
closeBtns.forEach(btn => {
|
||
btn.addEventListener('click', function() {
|
||
modal.style.opacity = '0';
|
||
modal.style.pointerEvents = 'none';
|
||
modal.querySelector('div').style.transform = 'scale(0.95)';
|
||
});
|
||
});
|
||
|
||
// 点击模态框外部关闭
|
||
modal.addEventListener('click', function(e) {
|
||
if (e.target === modal) {
|
||
modal.style.opacity = '0';
|
||
modal.style.pointerEvents = 'none';
|
||
modal.querySelector('div').style.transform = 'scale(0.95)';
|
||
}
|
||
});
|
||
}
|
||
|
||
// 教职工信息弹出层功能
|
||
setupModal('staffInfoBtn', 'staffInfoModal', 'staffInfoContent', '教职工详细信息',
|
||
// 模拟教职工数据
|
||
function() {
|
||
const totalStaff = 251400;
|
||
const categories = [
|
||
{name: '专任教师', percentage: 78.5},
|
||
{name: '行政人员', percentage: 12.3},
|
||
{name: '教辅人员', percentage: 6.2},
|
||
{name: '工勤人员', percentage: 3.0}
|
||
];
|
||
|
||
const genderDistribution = [
|
||
{name: '男性', percentage: 42.7},
|
||
{name: '女性', percentage: 57.3}
|
||
];
|
||
|
||
const ageGroups = [
|
||
{name: '25岁以下', percentage: 15.2},
|
||
{name: '26-35岁', percentage: 32.8},
|
||
{name: '36-45岁', percentage: 28.5},
|
||
{name: '46-55岁', percentage: 18.1},
|
||
{name: '56岁以上', percentage: 5.4}
|
||
];
|
||
|
||
return {
|
||
totalStaff,
|
||
categories,
|
||
genderDistribution,
|
||
ageGroups
|
||
};
|
||
},
|
||
// 渲染教职工数据
|
||
function(data, content) {
|
||
let html = '';
|
||
|
||
// 总人数
|
||
html += `
|
||
<div class="p-4 bg-primary/10 rounded-lg">
|
||
<p class="text-gray-400 text-sm mb-1">总教职工人数</p>
|
||
<h4 class="text-xl font-bold text-white">${data.totalStaff.toLocaleString()}</h4>
|
||
</div>
|
||
`;
|
||
|
||
// 人员类别分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">人员类别分布</h4>
|
||
<div class="space-y-2">
|
||
`;
|
||
data.categories.forEach(item => {
|
||
const count = Math.round(data.totalStaff * item.percentage / 100);
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${count.toLocaleString()}</span>
|
||
<span class="text-gray-400">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-secondary h-1.5 rounded-full" style="width: ${item.percentage}%">${item.percentage}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 性别分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">性别分布</h4>
|
||
<div class="grid grid-cols-2 gap-4">
|
||
`;
|
||
data.genderDistribution.forEach(item => {
|
||
const count = Math.round(data.totalStaff * item.percentage / 100);
|
||
html += `
|
||
<div class="p-3 bg-gray-800/50 rounded-lg">
|
||
<p class="text-gray-400 text-sm mb-1">${item.name}</p>
|
||
<div class="flex items-end space-x-1">
|
||
<h4 class="text-xl font-bold text-white">${count.toLocaleString()}</h4>
|
||
<span class="text-gray-400 mb-1">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 年龄分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">年龄分布</h4>
|
||
<div class="space-y-2">
|
||
`;
|
||
data.ageGroups.forEach(item => {
|
||
const count = Math.round(data.totalStaff * item.percentage / 100);
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${count.toLocaleString()}</span>
|
||
<span class="text-gray-400">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-accent h-1.5 rounded-full" style="width: ${item.percentage}%">${item.percentage}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
content.innerHTML = html;
|
||
}
|
||
);
|
||
|
||
// 学校总数信息弹出层功能
|
||
setupModal('schoolInfoBtn', 'schoolInfoModal', 'schoolInfoContent', '学校分布详细信息',
|
||
// 模拟学校数据
|
||
function() {
|
||
const totalSchools = 13804;
|
||
const schoolTypes = [
|
||
{name: '幼儿园', percentage: 35.2},
|
||
{name: '小学', percentage: 42.7},
|
||
{name: '初中', percentage: 15.3},
|
||
{name: '高中', percentage: 4.8},
|
||
{name: '其他', percentage: 2.0}
|
||
];
|
||
|
||
const regionDistribution = [
|
||
{name: '昆明市', percentage: 18.5},
|
||
{name: '曲靖市', percentage: 15.2},
|
||
{name: '玉溪市', percentage: 7.8},
|
||
{name: '保山市', percentage: 8.3},
|
||
{name: '昭通市', percentage: 13.1},
|
||
{name: '丽江市', percentage: 4.2},
|
||
{name: '普洱市', percentage: 8.5},
|
||
{name: '临沧市', percentage: 7.9},
|
||
{name: '其他州市', percentage: 18.5}
|
||
];
|
||
|
||
return {
|
||
totalSchools,
|
||
schoolTypes,
|
||
regionDistribution
|
||
};
|
||
},
|
||
// 渲染学校数据
|
||
function(data, content) {
|
||
let html = '';
|
||
|
||
// 总数量
|
||
html += `
|
||
<div class="p-4 bg-primary/10 rounded-lg">
|
||
<p class="text-gray-400 text-sm mb-1">总学校数量</p>
|
||
<h4 class="text-xl font-bold text-white">${data.totalSchools.toLocaleString()}</h4>
|
||
</div>
|
||
`;
|
||
|
||
// 学校类型分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">学校类型分布</h4>
|
||
<div class="space-y-2">
|
||
`;
|
||
data.schoolTypes.forEach(item => {
|
||
const count = Math.round(data.totalSchools * item.percentage / 100);
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${count.toLocaleString()}</span>
|
||
<span class="text-gray-400">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-secondary h-1.5 rounded-full" style="width: ${item.percentage}%">${item.percentage}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 地区分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">地区分布</h4>
|
||
<div class="space-y-2 max-h-60 overflow-y-auto pr-2">
|
||
`;
|
||
data.regionDistribution.forEach(item => {
|
||
const count = Math.round(data.totalSchools * item.percentage / 100);
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${count.toLocaleString()}</span>
|
||
<span class="text-gray-400">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-accent h-1.5 rounded-full" style="width: ${item.percentage}%">${item.percentage}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
content.innerHTML = html;
|
||
}
|
||
);
|
||
|
||
// 在校生总数信息弹出层功能
|
||
setupModal('studentInfoBtn', 'studentInfoModal', 'studentInfoContent', '在校生详细信息',
|
||
// 模拟在校生数据
|
||
function() {
|
||
const totalStudents = 4860200;
|
||
const educationLevels = [
|
||
{name: '学前教育', percentage: 14.5},
|
||
{name: '小学教育', percentage: 42.3},
|
||
{name: '初中教育', percentage: 21.8},
|
||
{name: '高中教育', percentage: 16.4},
|
||
{name: '高等教育', percentage: 5.0}
|
||
];
|
||
|
||
const genderDistribution = [
|
||
{name: '男性', percentage: 51.2},
|
||
{name: '女性', percentage: 48.8}
|
||
];
|
||
|
||
return {
|
||
totalStudents,
|
||
educationLevels,
|
||
genderDistribution
|
||
};
|
||
},
|
||
// 渲染在校生数据
|
||
function(data, content) {
|
||
let html = '';
|
||
|
||
// 总数量
|
||
html += `
|
||
<div class="p-4 bg-primary/10 rounded-lg">
|
||
<p class="text-gray-400 text-sm mb-1">在校生总人数</p>
|
||
<h4 class="text-xl font-bold text-white">${data.totalStudents.toLocaleString()}</h4>
|
||
</div>
|
||
`;
|
||
|
||
// 教育阶段分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">教育阶段分布</h4>
|
||
<div class="space-y-2">
|
||
`;
|
||
data.educationLevels.forEach(item => {
|
||
const count = Math.round(data.totalStudents * item.percentage / 100);
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${count.toLocaleString()}</span>
|
||
<span class="text-gray-400">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-secondary h-1.5 rounded-full" style="width: ${item.percentage}%">${item.percentage}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 性别分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">性别分布</h4>
|
||
<div class="grid grid-cols-2 gap-4">
|
||
`;
|
||
data.genderDistribution.forEach(item => {
|
||
const count = Math.round(data.totalStudents * item.percentage / 100);
|
||
html += `
|
||
<div class="p-3 bg-gray-800/50 rounded-lg">
|
||
<p class="text-gray-400 text-sm mb-1">${item.name}</p>
|
||
<div class="flex items-end space-x-1">
|
||
<h4 class="text-xl font-bold text-white">${count.toLocaleString()}</h4>
|
||
<span class="text-gray-400 mb-1">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
content.innerHTML = html;
|
||
}
|
||
);
|
||
|
||
// 毕业生数信息弹出层功能
|
||
setupModal('graduateInfoBtn', 'graduateInfoModal', 'graduateInfoContent', '毕业生详细信息',
|
||
// 模拟毕业生数据
|
||
function() {
|
||
const totalGraduates = 1256800;
|
||
const educationLevels = [
|
||
{name: '小学毕业', percentage: 38.5},
|
||
{name: '初中毕业', percentage: 32.7},
|
||
{name: '高中毕业', percentage: 21.3},
|
||
{name: '大学毕业', percentage: 7.5}
|
||
];
|
||
|
||
const employmentRates = [
|
||
{name: '小学毕业生', rate: 100},
|
||
{name: '初中毕业生', rate: 98.2},
|
||
{name: '高中毕业生', rate: 85.7},
|
||
{name: '大学毕业生', rate: 78.3}
|
||
];
|
||
|
||
return {
|
||
totalGraduates,
|
||
educationLevels,
|
||
employmentRates
|
||
};
|
||
},
|
||
// 渲染毕业生数据
|
||
function(data, content) {
|
||
let html = '';
|
||
|
||
// 总数量
|
||
html += `
|
||
<div class="p-4 bg-primary/10 rounded-lg">
|
||
<p class="text-gray-400 text-sm mb-1">毕业生总人数</p>
|
||
<h4 class="text-xl font-bold text-white">${data.totalGraduates.toLocaleString()}</h4>
|
||
</div>
|
||
`;
|
||
|
||
// 教育阶段分布
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">教育阶段分布</h4>
|
||
<div class="space-y-2">
|
||
`;
|
||
data.educationLevels.forEach(item => {
|
||
const count = Math.round(data.totalGraduates * item.percentage / 100);
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${count.toLocaleString()}</span>
|
||
<span class="text-gray-400">(${item.percentage}%)</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-secondary h-1.5 rounded-full" style="width: ${item.percentage}%">${item.percentage}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 升学率/就业率
|
||
html += `
|
||
<div>
|
||
<h4 class="text-lg font-semibold text-white mb-2">升学率/就业率</h4>
|
||
<div class="space-y-2">
|
||
`;
|
||
data.employmentRates.forEach(item => {
|
||
html += `
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-gray-300">${item.name}</span>
|
||
<div class="flex items-center space-x-2">
|
||
<span class="text-white font-medium">${item.rate}%</span>
|
||
</div>
|
||
</div>
|
||
<div class="w-full bg-gray-700/30 rounded-full h-1.5">
|
||
<div class="bg-accent h-1.5 rounded-full" style="width: ${item.rate}%">${item.rate}%</div>
|
||
</div>
|
||
`;
|
||
});
|
||
html += `
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
content.innerHTML = html;
|
||
}
|
||
);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |