feat: implement METAR data collection service and dashboard infrastructure

This commit is contained in:
2569718930@qq.com
2026-04-11 20:11:01 +08:00
parent 69168d2fdf
commit 77b4d7b341
14 changed files with 660 additions and 148 deletions
+12 -3
View File
@@ -29,6 +29,10 @@ function normalizeCityName(cityName: string) {
return encodeURIComponent(String(cityName).replace(/\s/g, "-"));
}
function normalizeDetailDepth(depth?: "panel" | "full") {
return depth === "full" ? "full" : "panel";
}
async function fetchJson<T>(url: string): Promise<T> {
const response = await fetch(url, {
headers: { Accept: "application/json" },
@@ -155,17 +159,21 @@ export const dashboardClient = {
return request;
},
async getCityDetail(cityName: string, options?: { force?: boolean }) {
async getCityDetail(
cityName: string,
options?: { force?: boolean; depth?: "panel" | "full" },
) {
const force = options?.force ?? false;
const depth = normalizeDetailDepth(options?.depth);
if (!force) {
const requestKey = `${cityName}::cached`;
const requestKey = `${cityName}::${depth}::cached`;
const existing = pendingCityDetailRequests.get(requestKey);
if (existing) {
return existing;
}
const request = fetchJson<CityDetail>(
`/api/city/${normalizeCityName(cityName)}?force_refresh=false`,
`/api/city/${normalizeCityName(cityName)}?force_refresh=false&depth=${depth}`,
).finally(() => {
pendingCityDetailRequests.delete(requestKey);
});
@@ -176,6 +184,7 @@ export const dashboardClient = {
const params = new URLSearchParams({
force_refresh: "true",
depth,
_ts: String(Date.now()),
});
return fetchJson<CityDetail>(
+1
View File
@@ -327,6 +327,7 @@ export interface AiAnalysisStructured {
export interface CityDetail {
name: string;
display_name: string;
detail_depth?: "panel" | "full";
lat: number;
lon: number;
temp_symbol: string;