diff --git a/CHANGELOG.md b/CHANGELOG.md index 26854b7c..56eb5d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - 新增 Qingdao / 青岛城市,结算锚点接入 Wunderground 青岛胶东国际机场 `ZSQD` 历史页,并补齐别名、时区、预热、官方来源和前端地区归类 - 城市决策卡顶部状态标签收口为 2-3 个高优先级信号,优先展示“实测突破 / 峰值窗口已过 / METAR 过旧 / AI 解读中 / 市场价格缺失 / 模型高度一致 / 需要等待下一报文”,让用户第一眼看到重点 +- 城市决策卡 AI 机场报文区明确拆分“快速判断已完成,AI 正在补充机场报文细节… / AI 机场报文解读已完成 / AI 解读未完整返回,当前使用规则证据”三种状态,减少 fallback 与流式返回造成的误解 - 城市决策卡新增 AI 机场报文解读缓存说明:页面内存缓存保留 loading / 流式片段 / 最终结果,`localStorage` 保存最终成功 payload,后端 AI 缓存不再因 `local_time` 变化失效 - 城市决策卡兜底文案明确标记“快速证据模式”,避免在 DeepSeek 未完整返回时误写成“AI 机场报文解读正常” - 城市决策卡流式 AI 解读改为只请求 METAR/官方观测核心解读与判断依据,最高温中枢、模型一致性和风险清单由后端规则补齐,减少等待时间 diff --git a/frontend/components/dashboard/scan-terminal/AiPinnedForecastView.tsx b/frontend/components/dashboard/scan-terminal/AiPinnedForecastView.tsx index 757b03e2..f1434c27 100644 --- a/frontend/components/dashboard/scan-terminal/AiPinnedForecastView.tsx +++ b/frontend/components/dashboard/scan-terminal/AiPinnedForecastView.tsx @@ -368,23 +368,46 @@ function AiPinnedCityCard({ isEn, isHkoObservation, }); + const aiRuleEvidenceMode = Boolean( + aiForecast.status === "failed" || + (aiForecast.status === "ready" && !aiCityForecast) || + aiForecast.payload?.degraded || + aiMeta?.fallback, + ); + const aiReadInProgressText = isEn + ? isHkoObservation + ? "Fast read is ready; AI is adding HKO observation details..." + : "Fast read is ready; AI is adding airport bulletin details..." + : isHkoObservation + ? "快速判断已完成,AI 正在补充香港天文台观测细节…" + : "快速判断已完成,AI 正在补充机场报文细节…"; + const aiReadCompleteText = isEn + ? isHkoObservation + ? "AI HKO observation read is complete." + : "AI airport bulletin read is complete." + : isHkoObservation + ? "AI 香港天文台观测解读已完成" + : "AI 机场报文解读已完成"; + const aiRuleEvidenceText = isEn + ? "AI read did not return completely; rule evidence is being used." + : "AI 解读未完整返回,当前使用规则证据"; const aiStatusLabel = aiForecast.status === "loading" ? isEn - ? "AI reading" - : "AI 解读中" + ? "Fast read ready" + : "快速判断已完成" : aiForecast.status === "ready" && aiCityForecast - ? aiForecast.payload?.degraded || aiMeta?.fallback + ? aiRuleEvidenceMode ? isEn - ? "Rule fallback" - : "规则兜底" + ? "Rule evidence" + : "规则证据模式" : isEn - ? "AI ready" - : "AI 已完成" - : aiForecast.status === "failed" + ? "AI read complete" + : "AI 解读已完成" + : aiRuleEvidenceMode ? isEn - ? "AI failed" - : "AI 失败" + ? "Rule evidence" + : "规则证据模式" : isEn ? "AI pending" : "AI 待返回"; @@ -392,11 +415,11 @@ function AiPinnedCityCard({ aiForecast.status === "loading" ? "blue" : aiForecast.status === "ready" && aiCityForecast - ? aiForecast.payload?.degraded || aiMeta?.fallback + ? aiRuleEvidenceMode ? "amber" : "green" - : aiForecast.status === "failed" - ? "red" + : aiRuleEvidenceMode + ? "amber" : "muted"; const marketFreshnessLabel = marketDecisionView.status === "ready" @@ -449,7 +472,7 @@ function AiPinnedCityCard({ : null, aiForecast.status === "loading" ? { - label: isEn ? "AI reading" : "AI 解读中", + label: isEn ? "Fast read ready" : "快速判断已完成", tone: aiStatusTone, } : null, @@ -685,17 +708,14 @@ function AiPinnedCityCard({ {aiForecast.status === "loading" ? ( <> -

- {localizedFinalJudgment || - aiForecast.streamText || - (isEn - ? isHkoObservation - ? "Fast read is ready; AI is adding HKO observation details..." - : "Fast read is ready; AI is adding airport bulletin details..." - : isHkoObservation - ? "快速判断已完成,AI 正在补充香港天文台观测细节…" - : "快速判断已完成,AI 正在补充机场报文细节…")} +

+ {aiReadInProgressText}

+ {localizedFinalJudgment || aiForecast.streamText ? ( +

+ {localizedFinalJudgment || aiForecast.streamText} +

+ ) : null}

{isEn ? isHkoObservation @@ -709,11 +729,13 @@ function AiPinnedCityCard({ ) : aiForecast.status === "ready" && aiCityForecast ? ( <>

- {localizedFinalJudgment || - (isEn ? "AI read returned without a final sentence." : "AI 已返回,但缺少最终判断。")} + {aiRuleEvidenceMode ? aiRuleEvidenceText : aiReadCompleteText}

@@ -723,34 +745,22 @@ function AiPinnedCityCard({ ) : aiForecast.status === "ready" ? ( <> -

- {aiForecast.payload?.status === "timeout" - ? isEn - ? "DeepSeek enhancement timed out. You can retry; city data and the right briefing were not refreshed." - : "DeepSeek 增强本次超时,可稍后重试;城市数据和右侧简报不会被刷新。" - : fallbackAiReason || - (isEn - ? "AI read is unavailable for this city right now." - : "该城市暂时没有可用的 AI 解读。")} +

+ {aiRuleEvidenceText}

) : aiForecast.status === "failed" ? ( <> -

- {isEn - ? isHkoObservation - ? "AI read failed. Model support and the HKO observation remain as fallback context." - : "AI read failed. Model support and the raw METAR remain as fallback context." - : isHkoObservation - ? "AI 解读失败。下方保留多模型支撑和香港天文台观测作为兜底上下文。" - : "AI 解读失败。下方保留多模型支撑和原始 METAR 作为兜底上下文。"} - {aiForecast.error ? ` ${aiForecast.error}` : ""} +

+ {aiRuleEvidenceText}