feat: Implement PolyWeather web application with FastAPI backend for weather data analysis and a Leaflet-based frontend.

This commit is contained in:
2569718930@qq.com
2026-03-05 18:02:11 +08:00
parent 37aaf1f909
commit e4a5be660f
3 changed files with 45 additions and 0 deletions
+16
View File
@@ -9,6 +9,7 @@ CITY_REGISTRY = {
"icao": "LTAC",
"tz_offset": 10800,
"use_fahrenheit": False,
"is_major": False,
"risk_level": "medium",
"risk_emoji": "🟡",
"airport_name": "Esenboğa 机场",
@@ -22,6 +23,7 @@ CITY_REGISTRY = {
"icao": "EGLC",
"tz_offset": 0,
"use_fahrenheit": False,
"is_major": True,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "London City 机场",
@@ -35,6 +37,7 @@ CITY_REGISTRY = {
"icao": "LFPG",
"tz_offset": 3600,
"use_fahrenheit": False,
"is_major": True,
"risk_level": "medium",
"risk_emoji": "🟡",
"airport_name": "Charles de Gaulle 机场",
@@ -48,6 +51,7 @@ CITY_REGISTRY = {
"icao": "RKSI",
"tz_offset": 32400,
"use_fahrenheit": False,
"is_major": True,
"risk_level": "high",
"risk_emoji": "🔴",
"airport_name": "仁川国际机场",
@@ -61,6 +65,7 @@ CITY_REGISTRY = {
"icao": "CYYZ",
"tz_offset": -18000,
"use_fahrenheit": False,
"is_major": True,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "Pearson 国际机场",
@@ -74,6 +79,7 @@ CITY_REGISTRY = {
"icao": "SAEZ",
"tz_offset": -10800,
"use_fahrenheit": False,
"is_major": True,
"risk_level": "medium",
"risk_emoji": "🟡",
"airport_name": "Ezeiza 国际机场",
@@ -87,6 +93,7 @@ CITY_REGISTRY = {
"icao": "NZWN",
"tz_offset": 46800,
"use_fahrenheit": False,
"is_major": False,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "惠灵顿国际机场",
@@ -100,6 +107,7 @@ CITY_REGISTRY = {
"icao": "KLGA",
"tz_offset": -18000,
"use_fahrenheit": True,
"is_major": True,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "LaGuardia 机场",
@@ -113,6 +121,7 @@ CITY_REGISTRY = {
"icao": "KORD",
"tz_offset": -21600,
"use_fahrenheit": True,
"is_major": False,
"risk_level": "high",
"risk_emoji": "🔴",
"airport_name": "O'Hare 国际机场",
@@ -126,6 +135,7 @@ CITY_REGISTRY = {
"icao": "KDAL",
"tz_offset": -21600,
"use_fahrenheit": True,
"is_major": False,
"risk_level": "medium",
"risk_emoji": "🟡",
"airport_name": "Dallas Love Field 机场",
@@ -139,6 +149,7 @@ CITY_REGISTRY = {
"icao": "KMIA",
"tz_offset": -18000,
"use_fahrenheit": True,
"is_major": False,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "Miami 国际机场",
@@ -152,6 +163,7 @@ CITY_REGISTRY = {
"icao": "KATL",
"tz_offset": -18000,
"use_fahrenheit": True,
"is_major": False,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "Hartsfield-Jackson 机场",
@@ -165,6 +177,7 @@ CITY_REGISTRY = {
"icao": "KSEA",
"tz_offset": -28800,
"use_fahrenheit": True,
"is_major": False,
"risk_level": "low",
"risk_emoji": "🟢",
"airport_name": "Sea-Tac 国际机场",
@@ -178,6 +191,7 @@ CITY_REGISTRY = {
"icao": "VILK",
"tz_offset": 19800,
"use_fahrenheit": False,
"is_major": False,
"risk_level": "medium",
"risk_emoji": "🟡",
"airport_name": "Chaudhary Charan Singh 国际机场",
@@ -191,6 +205,7 @@ CITY_REGISTRY = {
"icao": "SBGR",
"tz_offset": -10800,
"use_fahrenheit": False,
"is_major": True,
"risk_level": "high",
"risk_emoji": "🔴",
"airport_name": "São Paulo/Guarulhos 机场",
@@ -204,6 +219,7 @@ CITY_REGISTRY = {
"icao": "EDDM",
"tz_offset": 3600,
"use_fahrenheit": False,
"is_major": False,
"risk_level": "high",
"risk_emoji": "🔴",
"airport_name": "Munich 机场",
+1
View File
@@ -548,6 +548,7 @@ async def list_cities():
"airport": risk.get("airport_name", ""),
"icao": risk.get("icao", ""),
"temp_unit": "fahrenheit" if info["f"] else "celsius",
"is_major": CITY_REGISTRY.get(name, {}).get("is_major", True),
}
)
return {"cities": out}
+28
View File
@@ -71,6 +71,33 @@ function initMap() {
map.on("click", () => {
closePanel();
});
// Handle zoom-based visibility for local stations and minor cities
map.on("zoomend", updateMapVisibility);
}
function updateMapVisibility() {
if (!map) return;
const zoom = map.getZoom();
// 1. Handle Nearby Individual Stations (very high zoom only)
// These are the "Ankara-style" local station markers
if (zoom < 7) {
if (map.hasLayer(nearbyLayerGroup)) map.removeLayer(nearbyLayerGroup);
} else {
if (!map.hasLayer(nearbyLayerGroup)) map.addLayer(nearbyLayerGroup);
}
// 2. Handle Primary City Markers (Major vs Minor)
Object.values(markers).forEach(({ marker, city }) => {
const isMajor = city.is_major !== false;
// Hide minor cities (like Ankara/Atlanta) when zoomed way out
if (zoom < 4 && !isMajor) {
if (map.hasLayer(marker)) map.removeLayer(marker);
} else {
if (!map.hasLayer(marker)) map.addLayer(marker);
}
});
}
// ──────────────────────────────────────────────────────────
@@ -109,6 +136,7 @@ function addCityMarkers(cities) {
});
document.getElementById("cityCount").textContent = cities.length;
updateMapVisibility();
}
function updateMarkerTemp(cityName, temp) {