diff --git a/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx b/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx index 185f8438..6bb4a205 100644 --- a/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx +++ b/frontend/components/dashboard/scan-terminal/LiveTemperatureThresholdChart.tsx @@ -946,12 +946,14 @@ export function LiveTemperatureThresholdChart({ const isHKO = cityKey === 'hong kong' || cityKey === 'lau fau shan' || cityKey.includes('hongkong') || cityKey.includes('laufau'); const isTokyo = cityKey === 'tokyo'; const isSingapore = cityKey === 'singapore'; + const isParis = cityKey === 'paris'; const isWeatherStation = !runwaySensorCities.has(cityKey) - && !isHKO && !isTokyo && !isSingapore; + && !isHKO && !isTokyo && !isSingapore && !isParis; const runwayHeaderLabel = isHKO ? '参考站点 (1分钟)' : isTokyo ? '机场气象站 (10分钟)' : isSingapore ? '航站楼温度' + : isParis ? '官方机场观测 (15分钟)' : isWeatherStation ? '气象站实测' : '跑道实测 (1分钟)'; @@ -961,6 +963,7 @@ export function LiveTemperatureThresholdChart({ const runwayHighLabel = isHKO ? '参考站点' : isTokyo ? '机场气象站' : isSingapore ? '航站楼' + : isParis ? '官方机场观测' : isWeatherStation ? '气象站' : '跑道实测'; diff --git a/src/utils/telegram_push.py b/src/utils/telegram_push.py index 65204460..fbab72e9 100644 --- a/src/utils/telegram_push.py +++ b/src/utils/telegram_push.py @@ -947,6 +947,7 @@ def _build_airport_status_message( deb_pred: Optional[float], local_time: str = "", state: str = "", + source_label: str = "", ) -> str: _AIRPORT_EN = {"seoul": "Incheon", "singapore": "Changi", "busan": "Gimhae", "tokyo": "Haneda", "ankara": "Esenboğa", "helsinki": "Vantaa", "amsterdam": "Schiphol", @@ -1118,6 +1119,10 @@ def _build_airport_status_message( else: lines.append(f"DEB:{deb_pred:.1f}{temp_symbol}") + if source_label: + lines.append("") + lines.append(f"📡 {source_label}") + # Model summary (compact) models = city_weather.get("multi_model") or {} if isinstance(models, dict) and len(models) >= 2: @@ -1299,14 +1304,17 @@ def _process_airport_city( current_temp = airport_primary.get("temp") or (city_weather.get("current") or {}).get("temp") if not current_obs_time: current_obs_time = str(airport_primary.get("obs_time") or "") + source_label = "" # human-readable data source for Paris messages if city == "paris": - # AEROWEB provides real observations; prefer over AROME model nowcast airport_primary = city_weather.get("airport_primary") or {} - if airport_primary.get("source_code") != "aeroweb": + if airport_primary.get("source_code") == "aeroweb": + source_label = "AEROWEB 机场实况 · Météo-France" + else: arome_temp = _fetch_arome_temp() if arome_temp is not None: current_temp = arome_temp city_weather.setdefault("current", {})["temp"] = arome_temp + source_label = "AROME HD 15分钟临近预报 · Météo-France" if not current_obs_time: current_obs_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S") if current_temp is None or deb_pred is None: @@ -1352,7 +1360,7 @@ def _process_airport_city( or city_weather.get("local_time") or "" ) - message = _build_airport_status_message(city, city_weather, deb_pred, obs_local, state="") + message = _build_airport_status_message(city, city_weather, deb_pred, obs_local, state="", source_label=source_label) # Send to all target chats sent = False