diff --git a/frontend/lib/dashboard-utils.ts b/frontend/lib/dashboard-utils.ts index 2dd02381..a6720a38 100644 --- a/frontend/lib/dashboard-utils.ts +++ b/frontend/lib/dashboard-utils.ts @@ -977,13 +977,33 @@ export function computeFrontTrendSignal( return ""; })() : ""; + const peakTafStillRelevant = + peakWindowEndMinutes === null || + currentMinutes === null || + currentMinutes < peakWindowEndMinutes; const effectivePeakTafSummary = - peakTafSummary && peakTafSummary !== currentTafSummary ? peakTafSummary : ""; + peakTafStillRelevant && + peakTafSummary && + peakTafSummary !== currentTafSummary + ? peakTafSummary + : ""; + const currentTafLine = tafTimelineSummary + ? isEnglish(locale) + ? `Current TAF: ${tafTimelineSummary}` + : `当前 TAF:${tafTimelineSummary}` + : ""; + const peakTafLine = effectivePeakTafSummary + ? isEnglish(locale) + ? `Peak-window TAF: ${effectivePeakTafSummary}` + : `峰值窗口 TAF:${effectivePeakTafSummary}` + : ""; + const tafFallbackSummary = + currentTafLine || peakTafLine ? "" : tafSummary; upperAirSummary = [ baseUpperAirSummary, - tafTimelineSummary, - effectivePeakTafSummary, - tafSummary, + currentTafLine, + peakTafLine, + tafFallbackSummary, ] .filter(Boolean) .join(isEnglish(locale) ? " " : ""); @@ -992,9 +1012,9 @@ export function computeFrontTrendSignal( ? { label: isEnglish(locale) ? "Airport TAF" : "机场预报", note: - tafTimelineSummary || - effectivePeakTafSummary || - tafSummary || + currentTafLine || + peakTafLine || + tafFallbackSummary || (isEnglish(locale) ? "Airport TAF is available for the current peak window." : "当前峰值窗口已接入机场 TAF 预报。"), @@ -1449,9 +1469,9 @@ export function computeFrontTrendSignal( backendSummary && backendSummary !== summary ? backendSummary : ""; const combinedSummary = [ summary, - tafTimelineSummary, - effectivePeakTafSummary, - tafSummary, + currentTafLine, + peakTafLine, + tafFallbackSummary, tafContrastSummary, backendSupplement, ] diff --git a/web/analysis_service.py b/web/analysis_service.py index df175870..7d8c47c7 100644 --- a/web/analysis_service.py +++ b/web/analysis_service.py @@ -494,7 +494,9 @@ def _build_taf_signal( for segment in segments: start_local = segment["start_utc"].astimezone(local_tz) end_local = segment["end_utc"].astimezone(local_tz) - if end_local < peak_window_start or start_local > peak_window_end: + overlap_start = max(start_local, peak_window_start) + overlap_end = min(end_local, peak_window_end) + if overlap_end <= overlap_start: continue active_segments.append(segment) joined = " ".join(segment["tokens"]) @@ -538,7 +540,7 @@ def _build_taf_signal( if segment["type"] in {"PROB30 TEMPO", "PROB40 TEMPO"} or level == "high": disruption_level = "high" - marker_time_local = start_local + marker_time_local = overlap_start marker_hour = marker_time_local.strftime("%H:00") hazards = [] if level != "low": @@ -548,19 +550,19 @@ def _build_taf_signal( if segment_regimes: hazards.append("wind") summary_zh = ( - f"{segment['type']} {start_local.strftime('%H:%M')}-{end_local.strftime('%H:%M')} " + f"{segment['type']} {overlap_start.strftime('%H:%M')}-{overlap_end.strftime('%H:%M')} " f"{'有阵雨/雷暴扰动' if level == 'high' else '有云雨扰动' if level == 'medium' else '以稳定为主'}" ) summary_en = ( - f"{segment['type']} {start_local.strftime('%H:%M')}-{end_local.strftime('%H:%M')} " + f"{segment['type']} {overlap_start.strftime('%H:%M')}-{overlap_end.strftime('%H:%M')} " f"{'shows shower/thunder disruption' if level == 'high' else 'shows cloud/rain disruption' if level == 'medium' else 'stays relatively stable'}" ) markers.append( { "label_time": marker_hour, "marker_type": segment["type"], - "start_local": start_local.strftime("%H:%M"), - "end_local": end_local.strftime("%H:%M"), + "start_local": overlap_start.strftime("%H:%M"), + "end_local": overlap_end.strftime("%H:%M"), "suppression_level": level, "summary_zh": summary_zh, "summary_en": summary_en,