Busan 机场观测面板:METAR 数据兜底展示
问题:AMOS 仅支持仁川 RKSI,釜山 RKPK 无法获取跑道级数据 解决:AmosRunwayPanel 新增 airportCurrent 回退模式 - 有 AMOS 数据时:展示完整跑道卡片网格(首尔/仁川) - 无 AMOS 时:展示单张机场观测卡片(釜山/所有其他机场) 包含:温度、风向风速、气压 QNH、能见度 标注数据来源(METAR/AMOS)和是否过旧 - AirportCurrentConditions 类型新增 pressure_hpa 字段 这样首尔有完整的 4 对跑道数据,釜山至少展示机场官方观测值
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user