Busan 机场观测面板:METAR 数据兜底展示

问题:AMOS 仅支持仁川 RKSI,釜山 RKPK 无法获取跑道级数据
解决:AmosRunwayPanel 新增 airportCurrent 回退模式

- 有 AMOS 数据时:展示完整跑道卡片网格(首尔/仁川)
- 无 AMOS 时:展示单张机场观测卡片(釜山/所有其他机场)
  包含:温度、风向风速、气压 QNH、能见度
  标注数据来源(METAR/AMOS)和是否过旧
- AirportCurrentConditions 类型新增 pressure_hpa 字段

这样首尔有完整的 4 对跑道数据,釜山至少展示机场官方观测值
This commit is contained in:
2569718930@qq.com
2026-05-10 18:58:42 +08:00
parent e1d21c6ce3
commit 3f351ac60c
3 changed files with 63 additions and 7 deletions
@@ -651,11 +651,12 @@ export function AiPinnedCityCard({
/>
</div>
{detail?.amos ? (
{(detail?.amos || detail?.airport_current) ? (
<AmosRunwayPanel
amos={detail.amos}
isEn={isEn}
tempSymbol={tempSymbol}
airportCurrent={detail?.airport_current ?? null}
/>
) : null}
@@ -13,16 +13,70 @@ export function AmosRunwayPanel({
amos,
isEn,
tempSymbol,
airportCurrent,
}: {
amos: AmosData;
amos?: AmosData | null;
isEn: boolean;
tempSymbol: string;
airportCurrent?: {
temp?: number | null;
wind_speed_kt?: number | null;
wind_dir?: number | null;
pressure_hpa?: number | null;
visibility_mi?: number | null;
raw_metar?: string | null;
source_label?: string | null;
obs_time?: string | null;
stale_for_today?: boolean | null;
} | null;
}) {
const runwayPairs = amos.runway_obs?.runway_pairs;
const runwayTemps = amos.runway_obs?.temperatures ?? amos.runway_temps;
const runwayWinds = amos.runway_obs?.wind_speeds;
const runwayVis = amos.runway_obs?.visibility_mor;
const runwayRvr = amos.runway_obs?.rvr;
const runwayPairs = amos?.runway_obs?.runway_pairs;
const runwayTemps = amos?.runway_obs?.temperatures ?? amos?.runway_temps;
const runwayWinds = amos?.runway_obs?.wind_speeds;
const runwayVis = amos?.runway_obs?.visibility_mor;
const runwayRvr = amos?.runway_obs?.rvr;
const hasAmosRunway = runwayPairs && runwayPairs.length > 0;
// Fallback: single-card METAR observation for non-AMOS airports
if (!hasAmosRunway) {
if (!airportCurrent?.temp && !airportCurrent?.wind_speed_kt) return null;
const sourceLabel = airportCurrent?.source_label || (isEn ? "METAR" : "机场报文");
const staleNote = airportCurrent?.stale_for_today
? isEn ? " (stale)" : "(过旧)"
: "";
return (
<div className="scan-amos-runway-panel">
<div className="scan-ai-city-section-title">
{isEn ? "Airport Observation" : "机场观测"} · {sourceLabel}{staleNote}
</div>
<div className="scan-amos-runway-grid scan-amos-single">
<div className="scan-amos-runway-card">
<div className={`scan-amos-runway-temp ${runwayTempClass(airportCurrent.temp)}`}>
{airportCurrent.temp != null ? `${airportCurrent.temp.toFixed(1)}${tempSymbol}` : "--"}
</div>
{airportCurrent.wind_speed_kt != null ? (
<div className="scan-amos-runway-detail">
{isEn ? "Wind " : "风 "}
{airportCurrent.wind_dir != null ? `${airportCurrent.wind_dir}° ` : ""}
{airportCurrent.wind_speed_kt}kt
</div>
) : null}
{airportCurrent.pressure_hpa != null ? (
<div className="scan-amos-runway-detail">
QNH {airportCurrent.pressure_hpa.toFixed(1)} hPa
</div>
) : null}
{airportCurrent.visibility_mi != null ? (
<div className="scan-amos-runway-detail">
{isEn ? "Vis " : "能见度 "}
{(airportCurrent.visibility_mi * 1609).toFixed(0)}m
</div>
) : null}
</div>
</div>
</div>
);
}
if (!runwayPairs || runwayPairs.length === 0) return null;
+1
View File
@@ -102,6 +102,7 @@ export interface AirportCurrentConditions {
is_official?: boolean;
is_settlement_anchor?: boolean;
stale_for_today?: boolean;
pressure_hpa?: number | null;
last_observation_local_date?: string | null;
current_local_date?: string | null;
}