diff --git a/frontend/components/dashboard/FutureForecastModal.tsx b/frontend/components/dashboard/FutureForecastModal.tsx index 8089f080..ff8ab6c3 100644 --- a/frontend/components/dashboard/FutureForecastModal.tsx +++ b/frontend/components/dashboard/FutureForecastModal.tsx @@ -337,7 +337,10 @@ function DailyTemperatureChart({ dateStr }: { dateStr: string }) { (item) => item.index === ctx.dataIndex, ); if (!marker) return label; - return `${label}: ${marker.summary}`; + return `${label}: ${String(marker.summary || "").replace( + marker.markerType, + marker.displayType || marker.markerType, + )}`; } const value = ctx.parsed.y; if (value == null) return label; diff --git a/frontend/lib/dashboard-utils.ts b/frontend/lib/dashboard-utils.ts index 06d351a8..7964a37c 100644 --- a/frontend/lib/dashboard-utils.ts +++ b/frontend/lib/dashboard-utils.ts @@ -347,6 +347,10 @@ export function getTemperatureChartData( tafMarkerPoints[index] = tafMarkerValue; } return { + displayType: formatTafMarkerType( + String(marker?.marker_type || "").trim(), + locale, + ), endLocal: String(marker?.end_local || "").trim(), index, labelTime, @@ -414,11 +418,7 @@ export function getTemperatureChartData( if (tafMarkers.length) { const tafText = tafMarkers .slice(0, 4) - .map((marker) => - isEnglish(locale) - ? `${marker.markerType} ${marker.startLocal}-${marker.endLocal}` - : `${marker.markerType} ${marker.startLocal}-${marker.endLocal}`, - ) + .map((marker) => `${marker.displayType} ${marker.startLocal}-${marker.endLocal}`) .join(" | "); legendParts.push( isEnglish(locale) @@ -599,6 +599,36 @@ function bucketLabel(bucket: string | null, locale: Locale = "zh-CN") { ); } +function formatTafMarkerType(type: string, locale: Locale = "zh-CN") { + const normalized = String(type || "").trim().toUpperCase(); + if (isEnglish(locale)) { + return ( + { + BASE: "Base regime", + FM: "Hard shift", + TEMPO: "Temporary swing", + BECMG: "Gradual shift", + PROB30: "30% risk window", + PROB40: "40% risk window", + "PROB30 TEMPO": "30% temporary swing", + "PROB40 TEMPO": "40% temporary swing", + }[normalized] || normalized + ); + } + return ( + { + BASE: "基础时段", + FM: "明确切换", + TEMPO: "临时波动", + BECMG: "逐步转变", + PROB30: "30% 风险窗", + PROB40: "40% 风险窗", + "PROB30 TEMPO": "30% 临时波动", + "PROB40 TEMPO": "40% 临时波动", + }[normalized] || normalized + ); +} + export function wuRound(value: number | null | undefined) { const numeric = Number(value); if (!Number.isFinite(numeric)) return null; diff --git a/web/analysis_service.py b/web/analysis_service.py index ba7956b7..df175870 100644 --- a/web/analysis_service.py +++ b/web/analysis_service.py @@ -571,8 +571,8 @@ def _build_taf_signal( peak_window = f"{peak_window_start.strftime('%H:%M')}-{peak_window_end.strftime('%H:%M')}" if suppression_level == "high": - summary_zh = f"TAF 在峰值窗口({peak_window})提示阵雨或雷暴扰动,机场端压温风险偏高。" - summary_en = f"TAF flags shower or thunderstorm disruption around the peak window ({peak_window}), so airport-side suppression risk is high." + summary_zh = f"TAF 在峰值窗口({peak_window})提示阵雨或雷暴扰动,机场最高温可能被云雨压低。" + summary_en = f"TAF flags shower or thunderstorm disruption around the peak window ({peak_window}), airport high may get capped by showers/storms." elif suppression_level == "medium": summary_zh = f"TAF 在峰值窗口({peak_window})提示云量或弱降水扰动,需要防峰值被压低。" summary_en = f"TAF points to cloud or light-precip disruption around the peak window ({peak_window}); the airport high may be capped."