feat: implement ScanTerminalDashboard UI and state management with supporting tests

This commit is contained in:
2569718930@qq.com
2026-05-15 15:02:15 +08:00
parent 747c8aa401
commit 5e8548999a
4 changed files with 96 additions and 14 deletions
+65 -1
View File
@@ -509,6 +509,61 @@ function pickRicherHourly(
return incomingCount >= currentCount ? incomingValue : currentValue;
}
function countObservationSeriesPoints<T extends { time?: string | null; temp?: number | null }>(
value: T[] | null | undefined,
) {
return (Array.isArray(value) ? value : []).filter((row) => {
const time = String(row?.time || "").trim();
const temp = Number(row?.temp);
return Boolean(time) && Number.isFinite(temp);
}).length;
}
function pickRicherObservationSeries<
T extends { time?: string | null; temp?: number | null },
>(
currentValue: T[] | null | undefined,
incomingValue: T[] | null | undefined,
): T[] | undefined {
const incomingCount = countObservationSeriesPoints(incomingValue);
const currentCount = countObservationSeriesPoints(currentValue);
if (incomingCount <= 0) return currentValue || undefined;
if (currentCount <= 0) return incomingValue || undefined;
return (incomingCount >= currentCount ? incomingValue : currentValue) || undefined;
}
function mergeTrendInfo(
currentValue: CityDetail["trend"] | undefined,
incomingValue: CityDetail["trend"] | undefined,
) {
if (!incomingValue) return currentValue;
if (!currentValue) return incomingValue;
return {
...currentValue,
...incomingValue,
recent: pickRicherObservationSeries(
currentValue.recent,
incomingValue.recent,
),
};
}
function mergeMgmData(
currentValue: CityDetail["mgm"] | undefined,
incomingValue: CityDetail["mgm"] | undefined,
) {
if (!incomingValue) return currentValue;
if (!currentValue) return incomingValue;
return {
...currentValue,
...incomingValue,
hourly: pickRicherObservationSeries(
currentValue.hourly,
incomingValue.hourly,
),
};
}
function pickPreferredNearbyStations(
currentValue: CityDetail["official_nearby"] | CityDetail["mgm_nearby"],
incomingValue: CityDetail["official_nearby"] | CityDetail["mgm_nearby"],
@@ -546,7 +601,16 @@ function mergeCityDetail(
airport_current: incoming.airport_current || current.airport_current,
deb: incoming.deb || current.deb,
probabilities: incoming.probabilities || current.probabilities,
trend: incoming.trend || current.trend,
trend: mergeTrendInfo(current.trend, incoming.trend),
metar_today_obs: pickRicherObservationSeries(
current.metar_today_obs,
incoming.metar_today_obs,
),
settlement_today_obs: pickRicherObservationSeries(
current.settlement_today_obs,
incoming.settlement_today_obs,
),
mgm: mergeMgmData(current.mgm, incoming.mgm),
multi_model: pickRicherModelMap(current.multi_model, incoming.multi_model),
multi_model_daily: mergeDailyModelMap(
current.multi_model_daily,