759 lines
18 KiB
TypeScript
759 lines
18 KiB
TypeScript
import type { CityDetail } from "@/lib/dashboard-types";
|
||
import { normalizeObservationSourceLabel } from "@/lib/source-labels";
|
||
|
||
export type OfficialSourceLink = {
|
||
label: string;
|
||
href: string;
|
||
kind: "agency" | "airport" | "metar";
|
||
};
|
||
|
||
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=`;
|
||
}
|
||
|
||
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",
|
||
},
|
||
{
|
||
label: "深圳站(HKO)",
|
||
href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm",
|
||
kind: "agency",
|
||
},
|
||
],
|
||
"shenzhen": [
|
||
{
|
||
label: "香港天文台",
|
||
href: "https://www.hko.gov.hk/en/index.html",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "深圳站(HKO)",
|
||
href: "https://www.hko.gov.hk/sc/wxinfo/ts/index.htm",
|
||
kind: "airport",
|
||
},
|
||
],
|
||
taipei: [
|
||
{
|
||
label: "Wunderground RCSS",
|
||
href: "https://www.wunderground.com/history/daily/tw/taipei/RCSS",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "台北松山机场",
|
||
href: "https://www.tsa.gov.tw/?lang=en",
|
||
kind: "airport",
|
||
},
|
||
{
|
||
label: "RCSS METAR",
|
||
href: "https://aviationweather.gov/data/metar/?id=RCSS&decoded=1&taf=1",
|
||
kind: "metar",
|
||
},
|
||
],
|
||
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",
|
||
},
|
||
],
|
||
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",
|
||
},
|
||
],
|
||
istanbul: [
|
||
{
|
||
label: "MGM",
|
||
href: "https://www.mgm.gov.tr/?il=Istanbul&ilce=Istanbul%20Havalimani",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
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",
|
||
},
|
||
],
|
||
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",
|
||
},
|
||
],
|
||
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",
|
||
},
|
||
],
|
||
"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",
|
||
},
|
||
],
|
||
denver: [
|
||
{
|
||
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",
|
||
},
|
||
],
|
||
ankara: [
|
||
{
|
||
label: "MGM",
|
||
href: "https://www.mgm.gov.tr/?il=Ankara&ilce=Esenboga",
|
||
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",
|
||
},
|
||
{
|
||
label: "LFPB METAR",
|
||
href: "https://aviationweather.gov/data/metar/?id=LFPB&decoded=1&taf=1",
|
||
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: [
|
||
{
|
||
label: "NMC 浦东天气",
|
||
href: "https://m.nmc.cn/publish/forecast/ASH/pudong.html",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "上海浦东国际机场",
|
||
href: "https://www.shanghai-airport.com/",
|
||
kind: "airport",
|
||
},
|
||
{
|
||
label: "ZSPD METAR",
|
||
href: "https://aviationweather.gov/data/metar/?id=ZSPD&decoded=1&taf=1",
|
||
kind: "metar",
|
||
},
|
||
],
|
||
tokyo: [
|
||
{
|
||
label: "JMA 羽田10分钟实况",
|
||
href: "",
|
||
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: [
|
||
{
|
||
label: "NMC 双流天气",
|
||
href: "https://m.nmc.cn/publish/forecast/ASC/shuangliu.html",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "成都双流国际机场",
|
||
href: "https://www.cdairport.com/",
|
||
kind: "airport",
|
||
},
|
||
{
|
||
label: "ZUUU METAR",
|
||
href: "https://aviationweather.gov/data/metar/?id=ZUUU&decoded=1&taf=1",
|
||
kind: "metar",
|
||
},
|
||
],
|
||
chongqing: [
|
||
{
|
||
label: "NMC 渝北天气",
|
||
href: "https://m.nmc.cn/publish/forecast/ACQ/yubei.html",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "重庆江北国际机场",
|
||
href: "https://www.cqa.cn/",
|
||
kind: "airport",
|
||
},
|
||
{
|
||
label: "ZUCK METAR",
|
||
href: "https://aviationweather.gov/data/metar/?id=ZUCK&decoded=1&taf=1",
|
||
kind: "metar",
|
||
},
|
||
],
|
||
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",
|
||
},
|
||
],
|
||
"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",
|
||
},
|
||
],
|
||
beijing: [
|
||
{
|
||
label: "NMC 顺义天气",
|
||
href: "https://m.nmc.cn/publish/forecast/ABJ/shunyi.html",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "北京首都国际机场",
|
||
href: "https://www.bcia.com.cn/",
|
||
kind: "airport",
|
||
},
|
||
{
|
||
label: "ZBAA METAR",
|
||
href: "https://aviationweather.gov/data/metar/?id=ZBAA&decoded=1&taf=1",
|
||
kind: "metar",
|
||
},
|
||
],
|
||
wuhan: [
|
||
{
|
||
label: "NMC 武汉天气",
|
||
href: "https://m.nmc.cn/publish/forecast/AHB/wuhan.html",
|
||
kind: "agency",
|
||
},
|
||
{
|
||
label: "武汉天河国际机场",
|
||
href: "https://www.whairport.com/",
|
||
kind: "airport",
|
||
},
|
||
{
|
||
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();
|
||
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",
|
||
}),
|
||
};
|
||
}
|
||
return {
|
||
...link,
|
||
label: normalizeObservationSourceLabel(link.label, link.label),
|
||
};
|
||
});
|
||
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;
|
||
});
|
||
}
|