Add Polymarket market link and refresh side panel docs
This commit is contained in:
+25
-21
@@ -1,27 +1,31 @@
|
||||
# PolyWeather 侧边栏插件(MVP)
|
||||
# PolyWeather Side Panel
|
||||
|
||||
这是一个 Chrome / Edge 侧边栏扩展的 MVP,用于把 PolyWeather 右侧城市卡片移植到浏览器侧边栏中。
|
||||
`PolyWeather Side Panel` 是一个面向天气交易场景的 Chrome / Edge 浏览器侧边栏工具。
|
||||
|
||||
## 功能
|
||||
|
||||
- 侧边栏展示:
|
||||
- 城市选择
|
||||
- 风险徽章
|
||||
- 城市档案(结算源 / 距离 / 观测更新时间 / 周边站点)
|
||||
- 今日日内走势(简版 Canvas)
|
||||
- 多日预报(`DEB` 优先)
|
||||
- 基础判断卡(方向 / 置信度 / 原因)
|
||||
- 快捷按钮:
|
||||
- 今日日内分析
|
||||
- 历史对账
|
||||
- 打开网站查看更多
|
||||
- 自动识别城市:
|
||||
- 监听当前激活标签页 URL(例如 Polymarket `.../event/highest-temperature-in-ankara-...`)
|
||||
- 自动将侧边栏城市切换为 URL 对应城市
|
||||
- 设置页可配置:
|
||||
- 网站基础地址
|
||||
- API 基础地址
|
||||
- Bearer Token(可选)
|
||||
1. 自动识别当前 Polymarket 页面中的城市,也支持手动切换。
|
||||
2. 展示城市档案:结算站点、站点距离、观测更新时间、周边站点数量。
|
||||
3. 展示今日日内走势(简版):`DEB` 走势与官方观测(`METAR / HKO / CWA`)对照,可悬停查看时间与温度。
|
||||
4. 展示多日最高温预报(简版),当前以 `DEB` 优先。
|
||||
5. 支持一键刷新,强制拉取最新温度数据。
|
||||
6. 支持本地缓存,提升打开速度;刷新时自动更新缓存。
|
||||
7. 支持一键跳转到完整网站分析页面。
|
||||
|
||||
## 数据说明
|
||||
|
||||
- 香港使用 `HKO`(香港天文台)结算源。
|
||||
- 其他城市按配置使用 `METAR / NOAA / 官方数据源`。
|
||||
|
||||
## 权限说明
|
||||
|
||||
- `tabs`:用于识别当前活动标签页 URL 并自动匹配城市。
|
||||
- `storage`:用于保存插件配置与本地缓存,仅存储在本地浏览器。
|
||||
- `sidePanel`:用于在浏览器侧边栏展示界面。
|
||||
|
||||
## 隐私说明
|
||||
|
||||
本扩展不要求用户登录,不收集个人身份信息,不上传浏览历史,仅在必要时请求天气接口数据以完成展示功能。
|
||||
|
||||
## 本地安装(开发者模式)
|
||||
|
||||
@@ -43,7 +47,7 @@
|
||||
|
||||
## 说明
|
||||
|
||||
- 当前版本仍是轻量 MVP,重点是“监控 + 基础判断 + 导流回站”,未接入支付链路。
|
||||
- 当前版本仍是轻量产品,重点是“监控 + 基础判断 + 导流回站”,未接入支付链路。
|
||||
- 若你的 API 做了严格鉴权,请先在设置页填写 token 再使用。
|
||||
- 台北现在按 `NOAA RCTP` 结算参考展示。
|
||||
- 插件不会承载完整分析;完整结构判断、历史对账和更多信号仍以主站为准。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "PolyWeather Side Panel",
|
||||
"description": "PolyWeather 右侧城市卡片(浏览器侧边栏)",
|
||||
"version": "0.1.6",
|
||||
"description": "Weather side panel for Polymarket: auto-detect city, city profile, compact intraday DEB vs official observations, multi-day highs, refresh, cache, and quick jump to full analysis.",
|
||||
"version": "0.1.7",
|
||||
"icons": {
|
||||
"16": "icon-16.png",
|
||||
"32": "icon-32.png",
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useI18n } from "@/hooks/useI18n";
|
||||
import { getOfficialSourceLinks } from "@/lib/dashboard-official-sources";
|
||||
import { getCityScenery } from "@/lib/dashboard-scenery";
|
||||
import { CityDetail } from "@/lib/dashboard-types";
|
||||
import { getTodayPolymarketUrl } from "@/lib/polymarket-market-links";
|
||||
import {
|
||||
getCityProfileStats,
|
||||
getRiskBadgeLabel,
|
||||
@@ -167,6 +168,10 @@ export function DetailPanel() {
|
||||
() => (detail ? getOfficialSourceLinks(detail) : []),
|
||||
[detail],
|
||||
);
|
||||
const marketUrl = useMemo(
|
||||
() => getTodayPolymarketUrl(detail, locale),
|
||||
[detail, locale],
|
||||
);
|
||||
const scenery = getCityScenery(detail?.name);
|
||||
const blurActiveElement = () => {
|
||||
if (typeof document === "undefined") return;
|
||||
@@ -280,6 +285,21 @@ export function DetailPanel() {
|
||||
{getRiskBadgeLabel(panelRiskLevel, locale)}
|
||||
</span>
|
||||
<div className="relative group">
|
||||
{marketUrl ? (
|
||||
<a
|
||||
className="history-btn"
|
||||
href={marketUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title={
|
||||
locale === "en-US"
|
||||
? "Open today's Polymarket market"
|
||||
: "打开今日 Polymarket 题目页"
|
||||
}
|
||||
>
|
||||
{locale === "en-US" ? "Open Market" : "打开 Polymarket"}
|
||||
</a>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
className={clsx("history-btn", !isPro && "pro-locked")}
|
||||
|
||||
@@ -351,7 +351,7 @@ export const DOCS_PAGES: DocsPage[] = [
|
||||
content: {
|
||||
"zh-CN": {
|
||||
title: "浏览器插件",
|
||||
description: "侧边栏插件是主站的轻量入口,负责监控、基础判断和导流,不承载完整分析链路。",
|
||||
description: "PolyWeather Side Panel 是一个面向天气交易场景的浏览器侧边栏工具,负责自动识别城市、展示简版走势与城市档案,并把用户导回完整分析页面。",
|
||||
sections: [
|
||||
{
|
||||
id: "extension-install",
|
||||
@@ -372,9 +372,25 @@ export const DOCS_PAGES: DocsPage[] = [
|
||||
{
|
||||
type: "bullets",
|
||||
items: [
|
||||
"自动识别当前市场 URL,对应切换城市。",
|
||||
"展示风险徽章、城市档案、今日日内走势简版和多日预报。",
|
||||
"提供今日日内分析、历史对账和返回主站的快捷入口。",
|
||||
"自动识别当前 Polymarket 页面中的城市,也支持手动切换。",
|
||||
"展示城市档案:结算站点、站点距离、观测更新时间、周边站点数量。",
|
||||
"展示今日日内走势(简版):DEB 走势与官方观测(METAR / HKO / CWA)对照,可悬停查看时间与温度。",
|
||||
"展示多日最高温预报(简版),并提供一键刷新与跳转主站入口。",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "extension-permission",
|
||||
title: "权限与隐私",
|
||||
blocks: [
|
||||
{
|
||||
type: "bullets",
|
||||
items: [
|
||||
"`tabs`:用于识别当前活动标签页 URL 并自动匹配城市。",
|
||||
"`storage`:用于保存插件配置与本地缓存,仅存储在本地浏览器。",
|
||||
"`sidePanel`:用于在浏览器侧边栏展示界面。",
|
||||
"插件不要求用户登录,不收集个人身份信息,不上传浏览历史,仅在必要时请求天气接口数据。",
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -409,7 +425,7 @@ export const DOCS_PAGES: DocsPage[] = [
|
||||
},
|
||||
"en-US": {
|
||||
title: "Browser Extension",
|
||||
description: "The side-panel extension is a lightweight lead-in to the main site. It focuses on monitoring, basic bias, and traffic flow back to the full dashboard.",
|
||||
description: "PolyWeather Side Panel is a browser side-panel tool for weather trading workflows. It auto-detects cities, shows compact intraday and city-profile context, and routes users back to the full dashboard.",
|
||||
sections: [
|
||||
{
|
||||
id: "extension-install",
|
||||
@@ -430,9 +446,25 @@ export const DOCS_PAGES: DocsPage[] = [
|
||||
{
|
||||
type: "bullets",
|
||||
items: [
|
||||
"Auto-detects the current market URL and switches the side panel to the matching city.",
|
||||
"Shows risk badges, city profile, a compact intraday chart, and multi-day forecast.",
|
||||
"Provides quick links into the main intraday analysis and history reconciliation views.",
|
||||
"Auto-detects the current Polymarket page city, with manual switching also available.",
|
||||
"Shows a city profile with settlement station, station distance, observation timestamp, and nearby station count.",
|
||||
"Shows a compact intraday chart with DEB versus official observations (METAR / HKO / CWA), including hoverable time and temperature.",
|
||||
"Shows a compact multi-day daily-high forecast, plus refresh and jump-to-site actions.",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "extension-permission",
|
||||
title: "Permissions and privacy",
|
||||
blocks: [
|
||||
{
|
||||
type: "bullets",
|
||||
items: [
|
||||
"`tabs`: used to inspect the active tab URL and match the current city.",
|
||||
"`storage`: used for local configuration and local cache only.",
|
||||
"`sidePanel`: used to render the browser side panel UI.",
|
||||
"The extension does not require login, does not collect personally identifiable information, and does not upload browsing history. It only requests weather endpoints when needed to render the panel.",
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import type { CityDetail } from "@/lib/dashboard-types";
|
||||
import type { Locale } from "@/lib/i18n";
|
||||
|
||||
const CITY_TO_MARKET_SLUG: Record<string, string> = {
|
||||
ankara: "ankara",
|
||||
atlanta: "atlanta",
|
||||
austin: "austin",
|
||||
beijing: "beijing",
|
||||
"buenos aires": "buenos-aires",
|
||||
chengdu: "chengdu",
|
||||
chicago: "chicago",
|
||||
chongqing: "chongqing",
|
||||
dallas: "dallas",
|
||||
houston: "houston",
|
||||
"hong kong": "hong-kong",
|
||||
istanbul: "istanbul",
|
||||
london: "london",
|
||||
"los angeles": "los-angeles",
|
||||
lucknow: "lucknow",
|
||||
madrid: "madrid",
|
||||
mexico: "mexico-city",
|
||||
"mexico city": "mexico-city",
|
||||
miami: "miami",
|
||||
milan: "milan",
|
||||
munich: "munich",
|
||||
"new york": "nyc",
|
||||
paris: "paris",
|
||||
"san francisco": "san-francisco",
|
||||
"sao paulo": "sao-paulo",
|
||||
seattle: "seattle",
|
||||
seoul: "seoul",
|
||||
shanghai: "shanghai",
|
||||
shenzhen: "shenzhen",
|
||||
singapore: "singapore",
|
||||
taipei: "taipei",
|
||||
"tel aviv": "tel-aviv",
|
||||
tokyo: "tokyo",
|
||||
toronto: "toronto",
|
||||
warsaw: "warsaw",
|
||||
wellington: "wellington",
|
||||
wuhan: "wuhan",
|
||||
};
|
||||
|
||||
const MONTHS = [
|
||||
"january",
|
||||
"february",
|
||||
"march",
|
||||
"april",
|
||||
"may",
|
||||
"june",
|
||||
"july",
|
||||
"august",
|
||||
"september",
|
||||
"october",
|
||||
"november",
|
||||
"december",
|
||||
];
|
||||
|
||||
function normalizeCityKey(detail?: CityDetail | null) {
|
||||
return String(detail?.name || detail?.display_name || "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
function slugifyCityName(cityKey: string) {
|
||||
return cityKey
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/['’.]/g, "")
|
||||
.replace(/&/g, " and ")
|
||||
.replace(/\s+/g, "-");
|
||||
}
|
||||
|
||||
function normalizeDateParts(localDate?: string | null) {
|
||||
const value = String(localDate || "").trim();
|
||||
const match = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
||||
if (!match) return null;
|
||||
const year = Number(match[1]);
|
||||
const monthIndex = Number(match[2]) - 1;
|
||||
const day = Number(match[3]);
|
||||
if (
|
||||
!Number.isFinite(year) ||
|
||||
!Number.isFinite(monthIndex) ||
|
||||
!Number.isFinite(day) ||
|
||||
monthIndex < 0 ||
|
||||
monthIndex > 11
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
year,
|
||||
month: MONTHS[monthIndex],
|
||||
day,
|
||||
};
|
||||
}
|
||||
|
||||
export function getTodayPolymarketUrl(
|
||||
detail?: CityDetail | null,
|
||||
locale: Locale = "en-US",
|
||||
) {
|
||||
const cityKey = normalizeCityKey(detail);
|
||||
const citySlug = CITY_TO_MARKET_SLUG[cityKey] || slugifyCityName(cityKey);
|
||||
const dateParts = normalizeDateParts(detail?.local_date);
|
||||
if (!citySlug || !dateParts) return null;
|
||||
|
||||
const prefix =
|
||||
locale === "zh-CN"
|
||||
? "https://polymarket.com/zh/event/"
|
||||
: "https://polymarket.com/event/";
|
||||
|
||||
return `${prefix}highest-temperature-in-${citySlug}-on-${dateParts.month}-${dateParts.day}-${dateParts.year}`;
|
||||
}
|
||||
Reference in New Issue
Block a user