From 7f9e7745485340c479fb67fa154b578ef4c1d8ac Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Fri, 3 Apr 2026 01:53:28 +0800 Subject: [PATCH] Refine ops dashboards and align browser extension data views --- extension/README.md | 8 +++++--- extension/sidepanel.js | 44 +++++++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/extension/README.md b/extension/README.md index 87be1c3b..edff4b5f 100644 --- a/extension/README.md +++ b/extension/README.md @@ -6,7 +6,7 @@ 1. 自动识别当前 Polymarket 页面中的城市,也支持手动切换。 2. 展示城市档案:结算站点、站点距离、观测更新时间、周边站点数量。 -3. 展示今日日内走势(简版):`DEB` 走势与官方观测(`METAR / HKO / CWA`)对照,可悬停查看时间与温度。 +3. 展示今日日内走势(简版):`DEB` 走势与官方观测(`METAR / HKO / CWA / Wunderground`)对照,可悬停查看时间与温度。 4. 展示多日最高温预报(简版),当前以 `DEB` 优先。 5. 支持一键刷新,强制拉取最新温度数据。 6. 支持本地缓存,提升打开速度;刷新时自动更新缓存。 @@ -15,7 +15,8 @@ ## 数据说明 - 香港使用 `HKO`(香港天文台)结算源。 -- 其他城市按配置使用 `METAR / NOAA / 官方数据源`。 +- 其他城市按配置使用 `METAR / NOAA / Wunderground / 官方数据源`。 +- 城市展示名以主站返回值为准,例如 `aurora` 市场在插件中会显示为 `Denver`。 ## 权限说明 @@ -49,5 +50,6 @@ - 当前版本仍是轻量产品,重点是“监控 + 基础判断 + 导流回站”,未接入支付链路。 - 若你的 API 做了严格鉴权,请先在设置页填写 token 再使用。 -- 台北现在按 `NOAA RCTP` 结算参考展示。 +- 插件会按主站返回的结算源展示参考口径,例如 `Taipei / Shenzhen` 当前走 `Wunderground`,`Hong Kong / Lau Fau Shan` 走 `HKO`。 +- 点击“打开网站查看更多”会回到主站继续查看完整分析。 - 插件不会承载完整分析;完整结构判断、历史对账和更多信号仍以主站为准。 diff --git a/extension/sidepanel.js b/extension/sidepanel.js index be5b579e..790e1e2d 100644 --- a/extension/sidepanel.js +++ b/extension/sidepanel.js @@ -20,7 +20,8 @@ const I18N = { settlementAirport: "结算机场", hko: "香港天文台 (HKO)", cwa: "交通部中央气象署 (CWA)", - noaa: "NOAA RCTP(台湾桃园国际机场)", + noaa: "NOAA 官方时序", + wunderground: "Wunderground 结算站", city: "城市", refresh: "刷新数据", cityProfile: "城市档案", @@ -38,9 +39,12 @@ const I18N = { nearbyMonitoringSuffix: "个参与监控", today: "今天", omSeries: "OM预测", - noaaSettlementRef: "NOAA RCTP 结算参考", + noaaSettlementRef: "NOAA 结算参考", noaaSettlementLegend: - "台北按 NOAA RCTP 最终完成质控后的最高整度摄氏值结算;图中曲线仅作结算参考。", + "该城市按 NOAA 最终完成质控后的最高整度读数结算;图中曲线仅作结算参考。", + wundergroundSettlementRef: "Wunderground 结算参考", + wundergroundSettlementLegend: + "该城市按配置的 Wunderground 站点结算;图中曲线仅作结算参考。", loadCityDetailFailed: "加载城市详情失败", refreshFailed: "刷新温度数据失败", initFailed: "初始化失败", @@ -81,7 +85,8 @@ const I18N = { settlementAirport: "Settlement Airport", hko: "Hong Kong Observatory (HKO)", cwa: "Central Weather Administration (CWA)", - noaa: "NOAA RCTP (Taiwan Taoyuan International Airport)", + noaa: "NOAA official timeseries", + wunderground: "Wunderground settlement station", city: "City", refresh: "Refresh data", cityProfile: "City Profile", @@ -99,9 +104,12 @@ const I18N = { nearbyMonitoringSuffix: " stations monitored", today: "Today", omSeries: "OM Forecast", - noaaSettlementRef: "NOAA RCTP Settlement Reference", + noaaSettlementRef: "NOAA Settlement Reference", noaaSettlementLegend: - "Taipei settles on NOAA RCTP using the finalized highest rounded whole-degree Celsius reading; the plotted line is only a settlement reference.", + "This city settles on NOAA using the finalized highest rounded reading; the plotted line is only a settlement reference.", + wundergroundSettlementRef: "Wunderground Settlement Reference", + wundergroundSettlementLegend: + "This city settles on the configured Wunderground station; the plotted line is only a settlement reference.", loadCityDetailFailed: "Failed to load city detail", refreshFailed: "Failed to refresh weather data", initFailed: "Initialization failed", @@ -471,6 +479,7 @@ function riskText(level) { function getSettlementSourceDisplay(detail) { const source = String(detail?.current?.settlement_source || "").toLowerCase(); + const sourceLabel = String(detail?.current?.settlement_source_label || "").trim(); if (source === "hko") { return { label: t("settlementSource"), @@ -489,6 +498,14 @@ function getSettlementSourceDisplay(detail) { value: t("noaa") }; } + if (source === "wunderground") { + const stationLabel = sourceLabel || t("wunderground"); + const station = String(detail?.current?.station_code || detail?.risk?.icao || "").trim(); + return { + label: t("settlementSource"), + value: station ? `${stationLabel} (${station})` : stationLabel + }; + } const airport = detail?.risk?.airport || "--"; const icao = detail?.risk?.icao ? ` (${detail.risk.icao})` : ""; return { @@ -727,7 +744,9 @@ function drawTrendChart(detail) { const sourceCode = String(detail?.current?.settlement_source || "").toLowerCase(); const obsSeriesLabel = sourceCode === "noaa" ? t("noaaSettlementRef") - : String(detail?.current?.settlement_source_label || "OBS").toUpperCase(); + : sourceCode === "wunderground" + ? t("wundergroundSettlementRef") + : String(detail?.current?.settlement_source_label || "OBS").toUpperCase(); if (!points.length) { setChartHover([], tempSymbol); ctx.fillStyle = "#8ba0be"; @@ -987,6 +1006,7 @@ function renderDetail(detail) { state.detail = detail; renderRiskBadge(detail); renderFreshness(detail); + const tempSymbol = detail?.temp_symbol || "°C"; const profile = getSettlementSourceDisplay(detail); els.settlementLabel.textContent = profile.label; @@ -1007,6 +1027,8 @@ function renderDetail(detail) { const sourceCode = String(detail?.current?.settlement_source || "").toLowerCase(); const sourceTag = sourceCode === "noaa" ? t("noaaSettlementRef") + : sourceCode === "wunderground" + ? t("wundergroundSettlementRef") : String(detail?.current?.settlement_source_label || "").toUpperCase() || "OBS"; const obs = getObservationRows(detail); if (obs.length >= 2) { @@ -1014,12 +1036,16 @@ function renderDetail(detail) { const last = obs[obs.length - 1]; els.chartLegend.textContent = sourceCode === "noaa" - ? `${sourceTag}: ${first.temp}°C@${first.time} -> ${last.temp}°C@${last.time} | ${t("noaaSettlementLegend")}` - : `${sourceTag}: ${first.temp}°C@${first.time} -> ${last.temp}°C@${last.time}`; + ? `${sourceTag}: ${first.temp}${tempSymbol}@${first.time} -> ${last.temp}${tempSymbol}@${last.time} | ${t("noaaSettlementLegend")}` + : sourceCode === "wunderground" + ? `${sourceTag}: ${first.temp}${tempSymbol}@${first.time} -> ${last.temp}${tempSymbol}@${last.time} | ${t("wundergroundSettlementLegend")}` + : `${sourceTag}: ${first.temp}${tempSymbol}@${first.time} -> ${last.temp}${tempSymbol}@${last.time}`; } else { els.chartLegend.textContent = sourceCode === "noaa" ? `${sourceTag}: ${t("noContinuousObs")} | ${t("noaaSettlementLegend")}` + : sourceCode === "wunderground" + ? `${sourceTag}: ${t("noContinuousObs")} | ${t("wundergroundSettlementLegend")}` : `${sourceTag}: ${t("noContinuousObs")}`; } }