From 42b9c2780e078cb147c13c36ad643af852e2f0c7 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Thu, 5 Mar 2026 21:40:37 +0800 Subject: [PATCH] feat: Introduce initial web application structure with dark theme styling, data collection, and client-side logic. --- src/data_collection/weather_sources.py | 12 ++-- web/static/app.js | 85 +++++++++++++++++++------- web/static/style.css | 54 ++++++++++++---- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/src/data_collection/weather_sources.py b/src/data_collection/weather_sources.py index 7db38242..09bc67f2 100644 --- a/src/data_collection/weather_sources.py +++ b/src/data_collection/weather_sources.py @@ -658,8 +658,10 @@ class WeatherDataCollector: if obs_list: obs = obs_list[0] if isinstance(obs_list, list) else obs_list temp = obs.get("sicaklik") + wind_speed = obs.get("ruzgarHiz") + wind_dir = obs.get("ruzgarYon") if temp is not None and temp > -9000: - return ist_no, temp + return ist_no, {"temp": temp, "wind_speed": wind_speed, "wind_dir": wind_dir} except: pass return None, None @@ -668,9 +670,9 @@ class WeatherDataCollector: station_temps = {} with ThreadPoolExecutor(max_workers=10) as executor: fetch_results = list(executor.map(fetch_single_station, target_ist_nos)) - for ist_no, temp in fetch_results: + for ist_no, data in fetch_results: if ist_no is not None: - station_temps[ist_no] = temp + station_temps[ist_no] = data # 4. 组装最终结果 for ist_no, temp in station_temps.items(): @@ -696,7 +698,9 @@ class WeatherDataCollector: "name": display_name, "lat": lat, "lon": lon, - "temp": temp, + "temp": temp.get("temp") if isinstance(temp, dict) else temp, + "wind_speed": temp.get("wind_speed") if isinstance(temp, dict) else None, + "wind_dir": temp.get("wind_dir") if isinstance(temp, dict) else None, "istNo": ist_no }) diff --git a/web/static/app.js b/web/static/app.js index c5b4e02d..b3e75337 100644 --- a/web/static/app.js +++ b/web/static/app.js @@ -70,18 +70,18 @@ function initMap() { // Initialize Heatmap layer (requires Leaflet.heat) heatLayer = L.heatLayer([], { - radius: 70, - blur: 50, - maxZoom: 10, + radius: 160, // Large radius for field blending + blur: 50, // Lower blur for more defined radar-like edges + max: 1.0, // We will pass normalized intensities [0, 1] gradient: { - 0.0: "blue", - 0.2: "cyan", - 0.4: "lime", - 0.6: "yellow", - 0.8: "orange", - 1.0: "red", + 0.0: "#3b82f6", // Blue (Coldest in localized set) + 0.2: "#06b6d4", // Cyan + 0.4: "#10b981", // Green + 0.6: "#facc15", // Yellow + 0.8: "#f97316", // Orange + 1.0: "#ef4444", // Red (Hottest in localized set) }, - opacity: 0.5, + opacity: 0.45, }).addTo(map); // Close panel and clear selection when clicking on empty map space @@ -101,10 +101,10 @@ function updateMapVisibility() { // These are the "Ankara-style" local station markers if (zoom < 7) { if (map.hasLayer(nearbyLayerGroup)) map.removeLayer(nearbyLayerGroup); - if (map.hasLayer(heatLayer)) map.removeLayer(heatLayer); + if (heatLayer && map.hasLayer(heatLayer)) map.removeLayer(heatLayer); } else { if (!map.hasLayer(nearbyLayerGroup)) map.addLayer(nearbyLayerGroup); - if (!map.hasLayer(heatLayer)) map.addLayer(heatLayer); + if (heatLayer && !map.hasLayer(heatLayer)) map.addLayer(heatLayer); } // 2. Handle Primary City Markers (Major vs Minor) @@ -309,16 +309,31 @@ function renderNearbyStations(data) { // Filter out stations too far if needed, but il handles grouping nicely. // Skip if it is the exact same marker as main (though coordinates might slightly differ) const sym = data.temp_symbol || "°C"; + // Wind info if available + let windHtml = ""; + if (st.wind_dir != null) { + const rot = (parseFloat(st.wind_dir) + 180) % 360; + const speed = st.wind_speed != null ? `${st.wind_speed}k` : ""; + windHtml = ` +