2026-03-21 13:02:07 +08:00
|
|
|
|
import type { CityDetail } from "@/lib/dashboard-types";
|
2026-04-22 23:43:27 +08:00
|
|
|
|
import { normalizeObservationSourceLabel } from "@/lib/source-labels";
|
2026-03-21 13:02:07 +08:00
|
|
|
|
|
|
|
|
|
|
export type OfficialSourceLink = {
|
|
|
|
|
|
label: string;
|
|
|
|
|
|
href: string;
|
|
|
|
|
|
kind: "agency" | "airport" | "metar";
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-13 11:02:45 +08:00
|
|
|
|
function buildJmaAmedasTenMinuteUrl(
|
|
|
|
|
|
localDate?: string | null,
|
|
|
|
|
|
options?: {
|
|
|
|
|
|
blockNo?: string;
|
|
|
|
|
|
precNo?: string;
|
|
|
|
|
|
},
|
|
|
|
|
|
) {
|
|
|
|
|
|
const blockNo = String(options?.blockNo || "0371").trim() || "0371";
|
|
|
|
|
|
const precNo = String(options?.precNo || "44").trim() || "44";
|
|
|
|
|
|
const match = String(localDate || "").match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
|
|
|
|
const now = new Date();
|
|
|
|
|
|
const year = match?.[1] || String(now.getFullYear());
|
|
|
|
|
|
const month = match?.[2] || String(now.getMonth() + 1).padStart(2, "0");
|
|
|
|
|
|
const day = match?.[3] || String(now.getDate()).padStart(2, "0");
|
|
|
|
|
|
return `https://www.data.jma.go.jp/stats/etrn/view/10min_a1.php?prec_no=${encodeURIComponent(precNo)}&block_no=${encodeURIComponent(blockNo)}&year=${encodeURIComponent(year)}&month=${encodeURIComponent(month)}&day=${encodeURIComponent(day)}&view=`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-21 13:02:07 +08:00
|
|
|
|
const CITY_SPECIFIC_SOURCES: Record<string, OfficialSourceLink[]> = {
|
|
|
|
|
|
singapore: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "MSS 官方天气",
|
|
|
|
|
|
href: "https://www.weather.gov.sg/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "樟宜机场",
|
|
|
|
|
|
href: "https://www.changiairport.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "WSSS METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=WSSS&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
wellington: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "MetService",
|
|
|
|
|
|
href: "https://www.metservice.com/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wellington Airport",
|
|
|
|
|
|
href: "https://www.wellingtonairport.co.nz/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NZWN METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=NZWN&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"hong kong": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "香港天文台",
|
|
|
|
|
|
href: "https://www.hko.gov.hk/en/index.html",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "香港国际机场",
|
|
|
|
|
|
href: "https://www.hongkongairport.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "VHHH METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=VHHH&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
2026-04-02 21:46:41 +08:00
|
|
|
|
{
|
2026-05-25 21:15:14 +08:00
|
|
|
|
label: "深圳站(HKO)",
|
2026-04-02 21:46:41 +08:00
|
|
|
|
href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-05-25 06:10:54 +08:00
|
|
|
|
"shenzhen": [
|
2026-04-02 21:46:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "香港天文台",
|
|
|
|
|
|
href: "https://www.hko.gov.hk/en/index.html",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-05-25 21:15:14 +08:00
|
|
|
|
label: "深圳站(HKO)",
|
2026-04-02 21:46:41 +08:00
|
|
|
|
href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
2026-03-21 13:02:07 +08:00
|
|
|
|
],
|
|
|
|
|
|
taipei: [
|
|
|
|
|
|
{
|
2026-04-02 21:46:41 +08:00
|
|
|
|
label: "Wunderground RCSS",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/tw/taipei/RCSS",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-02 21:46:41 +08:00
|
|
|
|
label: "台北松山机场",
|
|
|
|
|
|
href: "https://www.tsa.gov.tw/?lang=en",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-02 21:46:41 +08:00
|
|
|
|
label: "RCSS METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=RCSS&decoded=1&taf=1",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-04-05 01:23:10 +08:00
|
|
|
|
busan: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground RKPK",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/kr/busan/RKPK",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "金海国际机场",
|
|
|
|
|
|
href: "https://www.airport.co.kr/gimhaeeng/index.do",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "RKPK METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=RKPK&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-04-16 16:43:37 +08:00
|
|
|
|
manila: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground RPLL",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/ph/manila/RPLL",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Ninoy Aquino International Airport",
|
|
|
|
|
|
href: "https://www.newnaia.com.ph/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "RPLL METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=RPLL&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
karachi: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground OPKC",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/pk/karachi/OPKC",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Jinnah International Airport",
|
|
|
|
|
|
href: "https://www.caapakistan.com.pk/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "OPKC METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=OPKC&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-03-27 20:58:38 +08:00
|
|
|
|
istanbul: [
|
2026-03-30 19:03:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "MGM",
|
2026-05-15 00:41:53 +08:00
|
|
|
|
href: "https://www.mgm.gov.tr/?il=Istanbul&ilce=Istanbul%20Havalimani",
|
2026-03-30 19:03:13 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
2026-03-27 20:58:38 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NOAA LTFM Timeseries",
|
|
|
|
|
|
href: "https://www.weather.gov/wrh/timeseries?site=LTFM",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Istanbul Airport",
|
|
|
|
|
|
href: "https://www.istairport.com/en",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "LTFM METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=LTFM&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-03-30 19:03:13 +08:00
|
|
|
|
moscow: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NOAA UUWW Timeseries",
|
|
|
|
|
|
href: "https://www.weather.gov/wrh/timeseries?site=UUWW",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Vnukovo International Airport",
|
|
|
|
|
|
href: "https://vnukovo.ru/en/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "UUWW METAR",
|
|
|
|
|
|
href: "https://metar-taf.com/UUWW",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-03-21 13:02:07 +08:00
|
|
|
|
london: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Met Office",
|
|
|
|
|
|
href: "https://www.metoffice.gov.uk/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "EGLC METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=EGLC&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"new york": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS",
|
|
|
|
|
|
href: "https://www.weather.gov/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KLGA METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KLGA&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-03-29 23:29:17 +08:00
|
|
|
|
"los angeles": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Los Angeles/Oxnard",
|
|
|
|
|
|
href: "https://www.weather.gov/lox/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "LAX Airport",
|
|
|
|
|
|
href: "https://www.flylax.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KLAX METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KLAX&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"san francisco": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS San Francisco Bay Area",
|
|
|
|
|
|
href: "https://www.weather.gov/mtr/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "SFO Airport",
|
|
|
|
|
|
href: "https://www.flysfo.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KSFO METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KSFO&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-05-14 01:09:17 +08:00
|
|
|
|
denver: [
|
2026-03-29 23:29:17 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Denver/Boulder",
|
|
|
|
|
|
href: "https://www.weather.gov/bou/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Buckley Space Force Base",
|
|
|
|
|
|
href: "https://www.buckley.spaceforce.mil/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KBKF METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KBKF&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
austin: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Austin/San Antonio",
|
|
|
|
|
|
href: "https://www.weather.gov/ewx/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Austin-Bergstrom Airport",
|
|
|
|
|
|
href: "https://www.austintexas.gov/airport",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KAUS METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KAUS&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
houston: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Houston/Galveston",
|
|
|
|
|
|
href: "https://www.weather.gov/hgx/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "William P. Hobby Airport",
|
|
|
|
|
|
href: "https://www.fly2houston.com/hobby",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KHOU METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KHOU&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"mexico city": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "SMN",
|
|
|
|
|
|
href: "https://smn.conagua.gob.mx/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "AICM",
|
|
|
|
|
|
href: "https://www.aicm.com.mx/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "MMMX METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=MMMX&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-03-21 13:02:07 +08:00
|
|
|
|
ankara: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "MGM",
|
2026-05-15 00:41:53 +08:00
|
|
|
|
href: "https://www.mgm.gov.tr/?il=Ankara&ilce=Esenboga",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "LTAC METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=LTAC&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
paris: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Météo-France",
|
|
|
|
|
|
href: "https://meteofrance.com/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-19 14:25:38 +08:00
|
|
|
|
label: "LFPB METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=LFPB&decoded=1&taf=1",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
seoul: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KMA",
|
|
|
|
|
|
href: "https://www.weather.go.kr/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "RKSI METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=RKSI&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
shanghai: [
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NMC 浦东天气",
|
|
|
|
|
|
href: "https://m.nmc.cn/publish/forecast/ASH/pudong.html",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "上海浦东国际机场",
|
|
|
|
|
|
href: "https://www.shanghai-airport.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
2026-03-21 13:02:07 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "ZSPD METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=ZSPD&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
tokyo: [
|
|
|
|
|
|
{
|
2026-04-13 11:02:45 +08:00
|
|
|
|
label: "JMA 羽田10分钟实况",
|
|
|
|
|
|
href: "",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "RJTT METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=RJTT&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"tel aviv": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "IMS",
|
|
|
|
|
|
href: "https://ims.gov.il/en",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "LLBG METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=LLBG&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
toronto: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Environment Canada",
|
|
|
|
|
|
href: "https://weather.gc.ca/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "CYYZ METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=CYYZ&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"buenos aires": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "SMN",
|
|
|
|
|
|
href: "https://www.smn.gob.ar/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "SAEZ METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=SAEZ&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
chicago: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Chicago",
|
|
|
|
|
|
href: "https://www.weather.gov/lot/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KORD METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KORD&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
dallas: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Fort Worth",
|
|
|
|
|
|
href: "https://www.weather.gov/fwd/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KDAL METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KDAL&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
miami: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Miami",
|
|
|
|
|
|
href: "https://www.weather.gov/mfl/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KMIA METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KMIA&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
atlanta: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Peachtree City",
|
|
|
|
|
|
href: "https://www.weather.gov/ffc/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KATL METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KATL&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
seattle: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "NWS Seattle",
|
|
|
|
|
|
href: "https://www.weather.gov/sew/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "KSEA METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=KSEA&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
lucknow: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "IMD",
|
|
|
|
|
|
href: "https://mausam.imd.gov.in/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "VILK METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=VILK&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"sao paulo": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "INMET",
|
|
|
|
|
|
href: "https://portal.inmet.gov.br/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "SBGR METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=SBGR&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
munich: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "DWD",
|
|
|
|
|
|
href: "https://www.dwd.de/EN/Home/home_node.html",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "EDDM METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=EDDM&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
milan: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "MeteoAM",
|
|
|
|
|
|
href: "https://www.meteoam.it/en/home",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "LIMC METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=LIMC&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
warsaw: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "IMGW",
|
|
|
|
|
|
href: "https://meteo.imgw.pl/",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "EPWA METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=EPWA&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
madrid: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "AEMET",
|
|
|
|
|
|
href: "https://www.aemet.es/en/portada",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "LEMD METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=LEMD&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
chengdu: [
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NMC 双流天气",
|
|
|
|
|
|
href: "https://m.nmc.cn/publish/forecast/ASC/shuangliu.html",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "成都双流国际机场",
|
|
|
|
|
|
href: "https://www.cdairport.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
2026-03-21 13:02:07 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "ZUUU METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=ZUUU&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
chongqing: [
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NMC 渝北天气",
|
|
|
|
|
|
href: "https://m.nmc.cn/publish/forecast/ACQ/yubei.html",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "重庆江北国际机场",
|
|
|
|
|
|
href: "https://www.cqa.cn/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
2026-03-21 13:02:07 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "ZUCK METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=ZUCK&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-04-28 07:08:33 +08:00
|
|
|
|
qingdao: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground ZSQD",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/cn/qingdao/ZSQD",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "青岛胶东国际机场",
|
|
|
|
|
|
href: "https://www.qdairport.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "ZSQD METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=ZSQD&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-04-05 01:23:10 +08:00
|
|
|
|
"kuala lumpur": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground WMKK",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/my/sepang-district/WMKK",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "吉隆坡国际机场",
|
|
|
|
|
|
href: "https://airports.malaysiaairports.com.my/klia",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "WMKK METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=WMKK&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
jakarta: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground WIHH",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/id/jakarta/WIHH",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Halim Perdanakusuma Airport",
|
|
|
|
|
|
href: "https://www.angkasapura2.co.id/en/airport/read/HLP",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "WIHH METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=WIHH&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
helsinki: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground EFHK",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/fi/vantaa/EFHK",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Helsinki Airport",
|
|
|
|
|
|
href: "https://www.finavia.fi/en/airports/helsinki-airport",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "EFHK METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=EFHK&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
amsterdam: [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground EHAM",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/nl/schiphol/EHAM",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Amsterdam Airport Schiphol",
|
|
|
|
|
|
href: "https://www.schiphol.nl/en/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "EHAM METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=EHAM&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
"panama city": [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Wunderground MPMG",
|
|
|
|
|
|
href: "https://www.wunderground.com/history/daily/pa/panama-city/MPMG",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "Marcos A. Gelabert Airport",
|
|
|
|
|
|
href: "https://www.aeropuertos.net/aeropuerto-internacional-marcos-a-gelabert/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "MPMG METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=MPMG&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
2026-03-21 13:02:07 +08:00
|
|
|
|
beijing: [
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NMC 顺义天气",
|
|
|
|
|
|
href: "https://m.nmc.cn/publish/forecast/ABJ/shunyi.html",
|
|
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
label: "北京首都国际机场",
|
|
|
|
|
|
href: "https://www.bcia.com.cn/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
2026-03-21 13:02:07 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "ZBAA METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=ZBAA&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
wuhan: [
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "NMC 武汉天气",
|
|
|
|
|
|
href: "https://m.nmc.cn/publish/forecast/AHB/wuhan.html",
|
2026-03-21 13:02:07 +08:00
|
|
|
|
kind: "agency",
|
|
|
|
|
|
},
|
2026-04-06 07:21:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "武汉天河国际机场",
|
|
|
|
|
|
href: "https://www.whairport.com/",
|
|
|
|
|
|
kind: "airport",
|
|
|
|
|
|
},
|
2026-03-21 13:02:07 +08:00
|
|
|
|
{
|
|
|
|
|
|
label: "ZHHH METAR",
|
|
|
|
|
|
href: "https://aviationweather.gov/data/metar/?id=ZHHH&decoded=1&taf=1",
|
|
|
|
|
|
kind: "metar",
|
|
|
|
|
|
},
|
|
|
|
|
|
],
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export function getOfficialSourceLinks(detail: CityDetail): OfficialSourceLink[] {
|
|
|
|
|
|
const cityKey = String(detail.name || "").trim().toLowerCase();
|
2026-04-13 11:02:45 +08:00
|
|
|
|
const links = [...(CITY_SPECIFIC_SOURCES[cityKey] || [])].map((link) => {
|
|
|
|
|
|
if (cityKey === "tokyo" && link.kind === "agency" && link.label === "JMA 羽田10分钟实况") {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...link,
|
|
|
|
|
|
href: buildJmaAmedasTenMinuteUrl(detail.local_date, {
|
|
|
|
|
|
blockNo: "0371",
|
|
|
|
|
|
precNo: "44",
|
|
|
|
|
|
}),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2026-04-22 23:43:27 +08:00
|
|
|
|
return {
|
|
|
|
|
|
...link,
|
|
|
|
|
|
label: normalizeObservationSourceLabel(link.label, link.label),
|
|
|
|
|
|
};
|
2026-04-13 11:02:45 +08:00
|
|
|
|
});
|
2026-03-21 13:02:07 +08:00
|
|
|
|
const seen = new Set<string>();
|
|
|
|
|
|
return links.filter((link) => {
|
|
|
|
|
|
const key = `${link.label}|${link.href}`;
|
|
|
|
|
|
if (seen.has(key)) return false;
|
|
|
|
|
|
seen.add(key);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|