From b866ebf6e3ed0d19bce7fc1360bb550400605d36 Mon Sep 17 00:00:00 2001
From: "2569718930@qq.com" <2569718930@qq.com>
Date: Wed, 25 Mar 2026 15:22:41 +0800
Subject: [PATCH] Clarify TAF intraday summaries
---
.../dashboard/FutureForecastModal.tsx | 7 +-
frontend/lib/dashboard-utils.ts | 137 ++++++++++++------
2 files changed, 102 insertions(+), 42 deletions(-)
diff --git a/frontend/components/dashboard/FutureForecastModal.tsx b/frontend/components/dashboard/FutureForecastModal.tsx
index 44954559..218cc6b0 100644
--- a/frontend/components/dashboard/FutureForecastModal.tsx
+++ b/frontend/components/dashboard/FutureForecastModal.tsx
@@ -1182,7 +1182,12 @@ export function FutureForecastModal() {
{view.front.summary ? (
- {view.front.summary}
+ {Array.isArray(view.front.summaryLines) &&
+ view.front.summaryLines.length > 0
+ ? view.front.summaryLines.map((line, index) => (
+
{line}
+ ))
+ : view.front.summary}
) : null}
diff --git a/frontend/lib/dashboard-utils.ts b/frontend/lib/dashboard-utils.ts
index accb426f..e6dfb5fa 100644
--- a/frontend/lib/dashboard-utils.ts
+++ b/frontend/lib/dashboard-utils.ts
@@ -832,6 +832,11 @@ export function computeFrontTrendSignal(
const currentDew = Number(detail.current?.dewpoint);
if (!slice.length) {
+ const fallbackSummary =
+ backendSummary ||
+ (isEnglish(locale)
+ ? "Insufficient intraday structured data. Keep baseline monitoring."
+ : "当日日内结构化数据不足,暂时只保留基础监控。");
return {
confidence: "low",
label: isEnglish(locale) ? "Monitoring" : "监控中",
@@ -845,11 +850,8 @@ export function computeFrontTrendSignal(
upperAirSummary,
precipMax: 0,
score: 0,
- summary:
- backendSummary ||
- (isEnglish(locale)
- ? "Insufficient intraday structured data. Keep baseline monitoring."
- : "当日日内结构化数据不足,暂时只保留基础监控。"),
+ summary: fallbackSummary,
+ summaryLines: [fallbackSummary],
weatherGovPeriods: [] as ReturnType,
};
}
@@ -918,6 +920,10 @@ export function computeFrontTrendSignal(
const markerSummary = (
marker:
| {
+ marker_type?: string | null;
+ start_local?: string | null;
+ end_local?: string | null;
+ suppression_level?: string | null;
summary_zh?: string | null;
summary_en?: string | null;
}
@@ -945,6 +951,66 @@ export function computeFrontTrendSignal(
return start !== null && start > currentMinutes;
})
: null;
+ const sameMarker = (
+ left:
+ | { marker_type?: string | null; start_local?: string | null; end_local?: string | null }
+ | null
+ | undefined,
+ right:
+ | { marker_type?: string | null; start_local?: string | null; end_local?: string | null }
+ | null
+ | undefined,
+ ) =>
+ !!left &&
+ !!right &&
+ String(left.marker_type || "") === String(right.marker_type || "") &&
+ String(left.start_local || "") === String(right.start_local || "") &&
+ String(left.end_local || "") === String(right.end_local || "");
+ const formatTafSegmentLine = (
+ marker:
+ | {
+ marker_type?: string | null;
+ start_local?: string | null;
+ end_local?: string | null;
+ suppression_level?: string | null;
+ }
+ | null
+ | undefined,
+ kind: "current" | "next" | "peak",
+ ) => {
+ if (!marker) return "";
+ const range = `${normalizeHm(marker.start_local) || "--:--"}-${normalizeHm(marker.end_local) || "--:--"}`;
+ const typeLabel = formatTafMarkerType(
+ String(marker.marker_type || ""),
+ locale,
+ );
+ const level = String(marker.suppression_level || "low").toLowerCase();
+ const statusText = isEnglish(locale)
+ ? level === "high"
+ ? "shows shower or thunderstorm disruption"
+ : level === "medium"
+ ? "shows cloud or light-rain disruption"
+ : "stays relatively stable"
+ : level === "high"
+ ? "有阵雨或雷暴扰动"
+ : level === "medium"
+ ? "有云量或弱降水扰动"
+ : "以稳定为主";
+ const prefix = isEnglish(locale)
+ ? kind === "current"
+ ? "Current TAF"
+ : kind === "next"
+ ? "Next TAF"
+ : "Peak-window TAF"
+ : kind === "current"
+ ? "当前 TAF"
+ : kind === "next"
+ ? "下一段 TAF"
+ : "峰值窗口 TAF";
+ return isEnglish(locale)
+ ? `${prefix}: ${typeLabel} (${range}), ${statusText}.`
+ : `${prefix}:${typeLabel}(${range}),${statusText}。`;
+ };
const peakWindowTafMarker =
tafSignal.available &&
peakWindowStartMinutes !== null &&
@@ -956,27 +1022,7 @@ export function computeFrontTrendSignal(
return start <= peakWindowEndMinutes && end >= peakWindowStartMinutes;
})
: null;
- const currentTafSummary = markerSummary(currentTafMarker);
const peakTafSummary = markerSummary(peakWindowTafMarker);
- const nextTafSummary = markerSummary(nextTafMarker);
- const tafTimelineSummary =
- tafSignal.available && dateStr === detail.local_date
- ? (() => {
- if (currentTafMarker && currentTafSummary) {
- const range = `${normalizeHm(currentTafMarker.start_local) || "--:--"}-${normalizeHm(currentTafMarker.end_local) || "--:--"}`;
- return isEnglish(locale)
- ? `Current active TAF segment (${range}): ${currentTafSummary}`
- : `当前生效的 TAF 时段(${range}):${currentTafSummary}`;
- }
- if (nextTafMarker && nextTafSummary) {
- const range = `${normalizeHm(nextTafMarker.start_local) || "--:--"}-${normalizeHm(nextTafMarker.end_local) || "--:--"}`;
- return isEnglish(locale)
- ? `Next TAF segment (${range}): ${nextTafSummary}`
- : `下一段 TAF 时段(${range}):${nextTafSummary}`;
- }
- return "";
- })()
- : "";
const peakTafStillRelevant =
peakWindowEndMinutes === null ||
currentMinutes === null ||
@@ -984,19 +1030,19 @@ export function computeFrontTrendSignal(
const effectivePeakTafSummary =
peakTafStillRelevant &&
peakTafSummary &&
- peakTafSummary !== currentTafSummary
+ !sameMarker(peakWindowTafMarker, currentTafMarker) &&
+ !sameMarker(peakWindowTafMarker, nextTafMarker)
? peakTafSummary
: "";
- const currentTafLine = tafTimelineSummary
- ? isEnglish(locale)
- ? `Current TAF: ${tafTimelineSummary}`
- : `当前 TAF:${tafTimelineSummary}`
- : "";
- const peakTafLine = effectivePeakTafSummary
- ? isEnglish(locale)
- ? `Peak-window TAF: ${effectivePeakTafSummary}`
- : `峰值窗口 TAF:${effectivePeakTafSummary}`
- : "";
+ const currentTafLine = currentTafMarker
+ ? formatTafSegmentLine(currentTafMarker, "current")
+ : nextTafMarker
+ ? formatTafSegmentLine(nextTafMarker, "next")
+ : "";
+ const peakTafLine =
+ effectivePeakTafSummary && peakWindowTafMarker
+ ? formatTafSegmentLine(peakWindowTafMarker, "peak")
+ : "";
const tafFallbackSummary =
currentTafLine || peakTafLine ? "" : tafSummary;
upperAirSummary = [
@@ -1465,18 +1511,26 @@ export function computeFrontTrendSignal(
return "";
})()
: "";
- const backendSupplement =
- backendSummary && backendSummary !== summary ? backendSummary : "";
- const combinedSummary = [
- summary,
+ const tafSummaryLineBody = [
currentTafLine,
peakTafLine,
tafFallbackSummary,
tafContrastSummary,
- backendSupplement,
]
.filter(Boolean)
.join(isEnglish(locale) ? " " : "");
+ const surfaceSummaryLine = summary
+ ? isEnglish(locale)
+ ? `Surface: ${summary}`
+ : `近地面:${summary}`
+ : "";
+ const tafSummaryLine = tafSummaryLineBody
+ ? isEnglish(locale)
+ ? `Airport TAF: ${tafSummaryLineBody}`
+ : `机场 TAF:${tafSummaryLineBody}`
+ : "";
+ const summaryLines = [surfaceSummaryLine, tafSummaryLine].filter(Boolean);
+ const combinedSummary = summaryLines.join(isEnglish(locale) ? " " : "");
const cloudNote = (() => {
if (cloudDelta >= 15 && tempDelta >= 0.8 && dewDelta >= 0.8) {
return isEnglish(locale)
@@ -1651,6 +1705,7 @@ export function computeFrontTrendSignal(
precipMax,
score,
summary: combinedSummary || backendSummary || summary,
+ summaryLines,
weatherGovPeriods,
};
}