- Vue 47.8%
- Python 30.7%
- JavaScript 19.7%
- CSS 1.6%
- HTML 0.2%
| backend | ||
| public/map | ||
| src | ||
| .gitignore | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| vite.config.js | ||
| 任务书符合性核查.md | ||
| 项目结构说明.md | ||
欧洲近地表空气污染物时空演变与可视化平台
基于 Vue 3 + Element Plus + ECharts + Leaflet(前端)与 FastAPI + rasterio(后端)实现的空气污染物时空可视化系统,对应课程实训任务书《欧洲近地表空气污染物时空演变与可视化平台》。
数据源为欧洲环境署(EEA)欧洲空气质量插值数据集(GeoTIFF 格式、1km 分辨率)。后端对 data/ 目录下的真实栅格文件做国家级分区统计(Zonal Statistics),前端大屏、分析与后台页面全部基于真实数据渲染。
当前真实数据集(data/ 目录)
| 文件 | 污染物 | 年份 | 有效格网 | 网格均值 |
|---|---|---|---|---|
| EEA_1kmgrid_2015_pm25_avg.tif | PM2.5 | 2015 | 5,114,394 | 8.89 μg/m³ |
| EEA_1kmgrid_2020_pm25_avg.tif | PM2.5 | 2020 | 5,116,940 | 6.88 μg/m³ |
| EEA_1kmgrid_2020_pm10_avg.tif | PM10 | 2020 | 5,903,167 | 12.23 μg/m³ |
| EEA_1kmgrid_2020_no2_avg.tif | NO₂ | 2020 | 5,902,994 | 4.91 μg/m³ |
| EEA_1kmgrid_2020_o3_somo10.tif | O₃ (SOMO10) | 2020 | 5,903,167 | 20,156 μg/m³·天 |
投影:ETRS89-extended / LAEA Europe(EPSG:3035,等积方位投影)。
功能页面
| 页面 | 路由 | 核心内容 |
|---|---|---|
| 可视化大屏 | /dashboard |
KPI 指标卡(欧洲年均、较基期变化、超 WHO 指导值国家数、较基期改善)、Leaflet 交互热力图(国家 choropleth + 5000 格网热力采样层 + 热点脉冲标注)、年份切换(PM2.5 支持 2015↔2020 播放)、国家排名 TOP15、1km 格网浓度分布直方图(真实栅格统计) |
| 时空分析 | /analysis |
多国家横向对比(≤6,按区域分组)、长期演变(PM2.5 2015→2020)、区域聚合分析、年度横向对比柱状图、明细表(可排序/分页)、CSV 导出 |
| 后台管理 | /admin |
真实 GeoTIFF 数据源清单(文件名/体积/有效格网数/网格均值)、空间/时序分析任务(进度条)、用户反馈处理 |
技术栈
- 前端:Vue 3(Composition API)+ Vite + Element Plus + ECharts 5 + Leaflet / leaflet.heat + Vue Router 4
- 后端:FastAPI + rasterio(GeoTIFF 读取、国家边界重投影与栅格化、分区统计)+ NumPy + pymysql
- 数据库:MySQL 8.0(存储数据集元数据、国家统计结果、热点/热力采样点、直方图;原始 GeoTIFF 留本地 data/)
- 投影转换:rasterio.warp(EPSG:4326 ⇄ EPSG:3035)
快速开始
0. 前置:MySQL(首次)
本项目使用本地免安装 MySQL 8.0 存储聚合统计结果。MySQL 已部署在 backend/mysql/ 目录下:
# 启动 MySQL(后台运行)
cd backend/mysql/mysql-8.0.28-winx64
./bin/mysqld.exe --console
# 验证连接
./bin/mysql.exe -u root -e "SELECT VERSION();"
MySQL 账号信息:
- 数据库:
air_pollution- 用户:
air_user/ 密码:air1234- 配置文件:
backend/db.py的CONFIG字典
1. 启动后端
cd backend
pip install -r requirements.txt
python run.py # http://127.0.0.1:8000
# 自动建表、计算→写入MySQL、后续启动从MySQL秒级加载
2. 启动前端(另开终端)
npm install npm run dev # http://localhost:5173 npm run build # 生产构建
> PowerShell 下若提示脚本禁止执行,使用 `npm.cmd run dev`,或执行
> `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
> 后端未启动时,前端自动回退到 `src/api/mock.js` 模拟数据(页面功能不受影响,页面顶部会显示数据来源标签)。
## 后端 API(/api/v1)
| 接口 | 说明 |
|------|------|
| `GET /meta` | 元数据:污染物清单、各污染物可用年份、40 国基础信息 |
| `GET /kpi?pollutant=&year=` | 大屏 KPI:欧洲年均、最高国家、超 WHO 国家数、较基期改善 |
| `GET /country-yearly?pollutant=&year=` | 国家年均值(choropleth 着色,分区统计结果) |
| `GET /ranking?pollutant=&year=&topN=` | 国家浓度排名 |
| `GET /heatpoints?pollutant=&year=` | 热力图层采样点(高值 2000 + 随机 3000,共约 5000 格网,已转 WGS84) |
| `GET /hotspots?pollutant=&year=` | 热点区域(浓度最高格网,0.6° 空间去重) |
| `GET /country-yearly-series?pollutant=` | 多国多年年均序列 |
| `GET /histogram?pollutant=&year=` | 1km 格网浓度分布直方图(12 区间) |
| `GET /datasets` | 数据源清单(后台管理页) |
| `GET /db-status` | MySQL 持久化状态(行数、连接信息、数据源标识) |
## 目录结构
├── backend/ # FastAPI 后端 │ ├── main.py # API 路由(含 MySQL 集成启动) │ ├── zonal.py # 分区统计核心(栅格化 + 聚合 + 缓存) │ ├── db.py # MySQL 持久化层(建表/读写/回退) │ ├── countries.py # 40 国基础信息 │ ├── run.py # 启动入口 │ ├── requirements.txt │ └── mysql/ # 本地免安装 MySQL 8.0 │ └── mysql-8.0.28-winx64/ ├── data/ # EEA GeoTIFF 真实数据(5 个栅格) ├── public/map/europe.json # 欧洲国家边界 GeoJSON(40 国) ├── src/ │ ├── api/service.js # 数据服务层(真实后端优先,模拟数据兜底) │ ├── api/mock.js # 模拟数据层(后端未启动时的回退) │ ├── components/charts/ │ │ ├── EuropeMapChart.vue # Leaflet 热力图(choropleth + heat + 热点标注) │ │ ├── RankingChart.vue / CompareChart.vue │ ├── views/ # 大屏 / 分析 / 后台三个页面 │ ├── layouts/MainLayout.vue # 响应式布局(桌面侧边栏 + 移动端抽屉) │ └── router/index.js
## 数据说明
- **原始数据**:`data/` 目录 GeoTIFF(5 个栅格,不修改、不复制)
- **持久化存储**:MySQL `air_pollution` 库,5 张表:
- `datasets` — 数据集元数据 + 全网格统计
- `country_stats` — 40 国年度均值/极值/格网数(200 行)
- `hotspots` — 热点区域标注(89 行)
- `heat_points` — 热力图层采样点(~25000 行)
- `histograms` — 浓度分布直方图(5 组)
- **启动策略**:优先从 MySQL 加载(秒级);缺失或 MySQL 不可用时回退到 rasterio 实时计算并写回 MySQL
- **有效值过滤**:排除 nodata、NaN 及未声明的 `-9999` 哨兵值(浓度必须为正)
- EPSG:3035 为等积投影且分辨率统一 1km,每个格网面积相等,算术平均即面积加权平均
- 参考标准:WHO 2021 AQG(PM2.5=5、NO₂=10、PM10=20 μg/m³;O₃ SOMO10 无年均指导值)
- 分析任务与用户反馈为演示数据