2026-03-20 19:07:11 +08:00
|
|
|
|
# PolyWeather 前端
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
PolyWeather Pro 的生产前端工程。
|
2026-03-06 19:10:05 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
线上地址:
|
|
|
|
|
|
- [https://polyweather-pro.vercel.app/](https://polyweather-pro.vercel.app/)
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
## 技术栈
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-06 19:10:05 +08:00
|
|
|
|
- Next.js App Router
|
2026-03-14 10:53:53 +08:00
|
|
|
|
- React + Tailwind
|
|
|
|
|
|
- Leaflet + Chart.js
|
|
|
|
|
|
- Supabase Auth
|
2026-03-20 19:07:11 +08:00
|
|
|
|
- WalletConnect + 浏览器 EVM 钱包
|
2026-03-06 19:10:05 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
## 运行模型
|
2026-03-06 19:10:05 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
1. 浏览器 -> Next 应用(`frontend`)
|
|
|
|
|
|
2. Next Route Handlers(`/api/*`)-> FastAPI 后端
|
|
|
|
|
|
3. FastAPI -> 分析服务 / 支付服务
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-24 04:03:41 +08:00
|
|
|
|
## 当前前端能力
|
|
|
|
|
|
|
2026-05-19 00:05:07 +08:00
|
|
|
|
- 主站 Dashboard 支持地图、城市详情、今日日内分析和账户中心
|
|
|
|
|
|
- `/docs` 已提供公开双语产品文档中心,解释日内分析、校准概率、模型栈、TAF 和结算来源
|
2026-03-24 04:03:41 +08:00
|
|
|
|
- 今日日内分析支持:
|
2026-04-10 08:04:25 +08:00
|
|
|
|
- `锚点状态`
|
|
|
|
|
|
- `当前节奏`
|
2026-04-18 14:40:29 +08:00
|
|
|
|
- `校准模型概率`
|
2026-04-10 08:04:25 +08:00
|
|
|
|
- `模型区间与分歧`
|
2026-04-18 14:40:29 +08:00
|
|
|
|
- `专业气象结论条`
|
|
|
|
|
|
- `气象证据链 / 失效条件 / 确认条件`
|
2026-03-24 04:03:41 +08:00
|
|
|
|
- 非香港机场城市的 `TAF` 时段提示与走势图联动
|
|
|
|
|
|
- `/ops` 已支持桌面表格 + 手机端卡片化视图
|
2026-04-10 08:04:25 +08:00
|
|
|
|
- 点击城市图标后会显示地图顶部同步提醒与详情面板内同步徽标,避免用户误判为卡住
|
|
|
|
|
|
- 城市详情会自动识别“单模型 / 单日”的稀疏缓存并主动刷新,避免误把残缺 detail 当作完整结果
|
2026-04-18 14:40:29 +08:00
|
|
|
|
- 右侧详情面板在多日预报仍未补齐时会显示同步占位卡,不再把“只有今天一张卡”的中间态伪装成完整数据
|
|
|
|
|
|
- 日内分析弹窗在 full detail / market scan 同步时会锁住旧内容并显示刷新状态,避免用户短暂看到旧城市或旧日期的数据
|
2026-04-27 01:38:37 +08:00
|
|
|
|
- 城市决策卡支持从地图点击城市进入;机会榜和日历仍按 Pro 权限控制,地图探索和城市简报可作为轻量入口
|
|
|
|
|
|
- 城市决策卡的 AI 机场报文解读包括最终判断、METAR 解读、推理说明、模型集群备注、风险提示和原始 METAR
|
|
|
|
|
|
- AI 机场报文解读按 `city + local_date + locale + METAR signature` 做页面内存缓存和 `localStorage` 最终结果缓存;切换选项卡返回时会优先恢复已有内容
|
|
|
|
|
|
- 市场价格层使用完整 `all_buckets` 匹配温度桶,并把 `模型-市场差` 解释为 `模型概率 - 市场隐含概率`
|
2026-05-23 21:42:46 +08:00
|
|
|
|
- 概率区展示当前生产概率引擎输出(legacy 高斯或 EMOS),模型共识只作为辅助参考
|
|
|
|
|
|
- 缓存桶状态与 summary cache hit/miss
|
2026-03-24 04:03:41 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
## 本地开发
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd frontend
|
|
|
|
|
|
cp .env.example .env.local
|
2026-04-10 08:04:25 +08:00
|
|
|
|
npm ci
|
2026-03-06 08:41:19 +08:00
|
|
|
|
npm run dev
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-20 22:00:02 +08:00
|
|
|
|
## Vercel 最小部署配置
|
|
|
|
|
|
|
|
|
|
|
|
只跑看板和基础鉴权时,先填这 4 项:
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-06 19:10:05 +08:00
|
|
|
|
```env
|
|
|
|
|
|
POLYWEATHER_API_BASE_URL=https://<your-fastapi-host>
|
2026-03-20 22:00:02 +08:00
|
|
|
|
NEXT_PUBLIC_SUPABASE_URL=https://<your-supabase-project>.supabase.co
|
|
|
|
|
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-anon-key>
|
2026-03-14 10:53:53 +08:00
|
|
|
|
POLYWEATHER_AUTH_ENABLED=true
|
2026-03-06 08:41:19 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-20 22:00:02 +08:00
|
|
|
|
建议显式补:
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
|
|
|
|
|
```env
|
2026-03-20 22:00:02 +08:00
|
|
|
|
POLYWEATHER_AUTH_REQUIRED=true
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
如果你只是开放游客浏览,可改成:
|
|
|
|
|
|
|
|
|
|
|
|
```env
|
|
|
|
|
|
POLYWEATHER_AUTH_ENABLED=false
|
|
|
|
|
|
POLYWEATHER_AUTH_REQUIRED=false
|
2026-03-14 10:53:53 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-20 22:00:02 +08:00
|
|
|
|
## 可选环境变量
|
|
|
|
|
|
|
|
|
|
|
|
仅在对应功能启用时填写:
|
2026-03-14 10:53:53 +08:00
|
|
|
|
|
|
|
|
|
|
```env
|
2026-03-20 22:00:02 +08:00
|
|
|
|
# 看板分享令牌
|
|
|
|
|
|
POLYWEATHER_DASHBOARD_ACCESS_TOKEN=
|
|
|
|
|
|
|
|
|
|
|
|
# 前端 API 转发到后端时使用的共享令牌
|
|
|
|
|
|
POLYWEATHER_BACKEND_ENTITLEMENT_TOKEN=
|
|
|
|
|
|
|
|
|
|
|
|
# 钱包支付
|
|
|
|
|
|
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=
|
|
|
|
|
|
NEXT_PUBLIC_WALLETCONNECT_POLYGON_RPC_URL=https://polygon-bor-rpc.publicnode.com
|
2026-03-22 13:42:48 +08:00
|
|
|
|
NEXT_PUBLIC_PAYMENT_ALLOWED_HOSTS=polyweather-pro.vercel.app
|
2026-03-24 04:03:41 +08:00
|
|
|
|
POLYWEATHER_OPS_ADMIN_EMAILS=yhrsc30@gmail.com
|
2026-03-20 22:00:02 +08:00
|
|
|
|
|
|
|
|
|
|
# 社群入口
|
2026-03-14 10:53:53 +08:00
|
|
|
|
NEXT_PUBLIC_TELEGRAM_GROUP_URL=https://t.me/<your_group>
|
2026-05-24 16:03:29 +08:00
|
|
|
|
NEXT_PUBLIC_TELEGRAM_BOT_URL=https://t.me/polyyuanbot
|
2026-04-10 08:04:25 +08:00
|
|
|
|
|
|
|
|
|
|
# 推荐默认关闭的前端观测 / 预热开关
|
|
|
|
|
|
NEXT_PUBLIC_POLYWEATHER_APP_ANALYTICS=false
|
|
|
|
|
|
NEXT_PUBLIC_POLYWEATHER_WEB_VITALS=false
|
|
|
|
|
|
NEXT_PUBLIC_POLYWEATHER_EAGER_CITY_SUMMARIES=false
|
2026-03-12 12:01:29 +08:00
|
|
|
|
```
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-20 22:00:02 +08:00
|
|
|
|
更完整的 Vercel 配置说明见:
|
|
|
|
|
|
- [docs/FRONTEND_DEPLOYMENT_ZH.md](/E:/web/PolyWeather/docs/FRONTEND_DEPLOYMENT_ZH.md)
|
|
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
## 路由处理器
|
2026-03-06 19:10:05 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
天气:
|
2026-03-14 10:53:53 +08:00
|
|
|
|
|
2026-03-06 08:41:19 +08:00
|
|
|
|
- `GET /api/cities`
|
2026-03-06 19:10:05 +08:00
|
|
|
|
- `GET /api/city/[name]`
|
2026-03-09 10:53:23 +08:00
|
|
|
|
- `GET /api/city/[name]/summary`
|
2026-03-12 12:01:29 +08:00
|
|
|
|
- `GET /api/city/[name]/detail`
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
鉴权:
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
2026-03-14 10:53:53 +08:00
|
|
|
|
- `GET /api/auth/me`
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
支付:
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
2026-03-14 10:53:53 +08:00
|
|
|
|
- `GET /api/payments/config`
|
|
|
|
|
|
- `GET /api/payments/wallets`
|
|
|
|
|
|
- `POST /api/payments/wallets/challenge`
|
|
|
|
|
|
- `POST /api/payments/wallets/verify`
|
|
|
|
|
|
- `POST /api/payments/intents`
|
|
|
|
|
|
- `GET /api/payments/intents/[intentId]`
|
|
|
|
|
|
- `POST /api/payments/intents/[intentId]/submit`
|
|
|
|
|
|
- `POST /api/payments/intents/[intentId]/confirm`
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
2026-03-21 14:52:25 +08:00
|
|
|
|
Ops:
|
|
|
|
|
|
|
|
|
|
|
|
- `GET /ops`
|
|
|
|
|
|
- `GET /api/ops/users`
|
|
|
|
|
|
- `GET /api/ops/leaderboard/weekly`
|
|
|
|
|
|
- `GET /api/ops/memberships`
|
|
|
|
|
|
- `GET /api/ops/payments/incidents`
|
|
|
|
|
|
- `POST /api/ops/users/grant-points`
|
|
|
|
|
|
- `POST /api/ops/payments/incidents/[eventId]/resolve`
|
|
|
|
|
|
|
|
|
|
|
|
## Ops 管理后台
|
|
|
|
|
|
|
|
|
|
|
|
当前前端已内置轻量管理页:
|
|
|
|
|
|
|
|
|
|
|
|
- [https://polyweather-pro.vercel.app/ops](https://polyweather-pro.vercel.app/ops)
|
|
|
|
|
|
|
|
|
|
|
|
页面当前支持:
|
|
|
|
|
|
|
|
|
|
|
|
- 系统状态
|
|
|
|
|
|
- SQLite / rollout / 支付运行态
|
2026-04-10 08:04:25 +08:00
|
|
|
|
- 缓存桶状态与 summary cache hit/miss
|
2026-03-21 14:52:25 +08:00
|
|
|
|
- 用户查询
|
|
|
|
|
|
- 当前会员
|
|
|
|
|
|
- 本周积分榜
|
|
|
|
|
|
- 手动补分
|
|
|
|
|
|
- 支付异常单筛选与标记已处理
|
2026-03-24 04:03:41 +08:00
|
|
|
|
- 手机端卡片化视图
|
2026-03-21 14:52:25 +08:00
|
|
|
|
|
|
|
|
|
|
注意:
|
|
|
|
|
|
|
2026-03-24 04:03:41 +08:00
|
|
|
|
- `/ops` 现在是前后端双层管理员限制
|
|
|
|
|
|
- Vercel 前端和后端都应配置相同的 `POLYWEATHER_OPS_ADMIN_EMAILS`
|
2026-03-21 14:52:25 +08:00
|
|
|
|
- 前端登录邮箱本身不会自动获得管理员权限
|
|
|
|
|
|
|
|
|
|
|
|
## 支付安全补充
|
|
|
|
|
|
|
|
|
|
|
|
为降低“旧页面/旧配置导致打到旧收款地址”的风险,支付区现在会:
|
|
|
|
|
|
|
|
|
|
|
|
1. 点击支付前重新请求 `/api/payments/config`
|
|
|
|
|
|
2. 若 `receiver_contract` 已更新,先切到最新地址
|
|
|
|
|
|
3. 若后端返回的 `tx_payload.to` 与最新地址不一致,直接阻断支付
|
2026-03-22 13:42:48 +08:00
|
|
|
|
4. 仅允许在 `NEXT_PUBLIC_PAYMENT_ALLOWED_HOSTS` 白名单域名上创建 payment intent
|
|
|
|
|
|
5. 支付区会明确显示当前账号、付款钱包和收款合约,避免账号/钱包/地址混淆
|
2026-03-21 14:52:25 +08:00
|
|
|
|
|
|
|
|
|
|
这意味着:
|
|
|
|
|
|
|
|
|
|
|
|
- 旧标签页风险已明显降低
|
|
|
|
|
|
- 但支付地址变更后,仍建议在 Vercel 上 redeploy 当前 production,并清理明显过期 deployment
|
|
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
## 缓存行为
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
- `cities` / `summary` / `history`:`ETag + Cache-Control`
|
|
|
|
|
|
- `summary?force_refresh=true`:`no-store`
|
|
|
|
|
|
- 支付相关路由:`no-store`
|
2026-04-18 14:40:29 +08:00
|
|
|
|
- 当 detail 缓存只返回单模型或单日 forecast 时,前端会自动强刷完整 detail,并在补齐前显示同步提示 / 占位卡
|
|
|
|
|
|
- 今日日内分析打开时如果正在切换城市、日期或 detail 深度,弹窗会阻断旧内容点击并显示刷新锁
|
2026-04-10 08:04:25 +08:00
|
|
|
|
|
|
|
|
|
|
## Vercel 节流建议
|
|
|
|
|
|
|
|
|
|
|
|
- 生产环境建议关闭 `Web Analytics` 和 `Speed Insights`
|
|
|
|
|
|
- 建议把自建 `app analytics / web vitals / eager city summaries` 默认保持关闭
|
|
|
|
|
|
- 如果你部署在 Vercel,可在 Firewall 中加一条 `WordPress / php scanner` 拦截规则,避免无效扫描白白触发 middleware
|
2026-03-12 12:01:29 +08:00
|
|
|
|
|
2026-03-30 00:46:01 +08:00
|
|
|
|
## AGPL 与商用边界说明
|
2026-03-09 04:41:24 +08:00
|
|
|
|
|
2026-03-30 00:46:01 +08:00
|
|
|
|
此前端代码随仓库一起采用 `AGPL-3.0-only`。
|
|
|
|
|
|
生产私有运营流程、商业策略调优、敏感生产参数、品牌与托管服务能力不在代码许可证授权范围内。
|
2026-03-06 08:41:19 +08:00
|
|
|
|
|
2026-03-20 19:07:11 +08:00
|
|
|
|
详见根目录策略文档:`docs/OPEN_CORE_POLICY.md`
|
2026-03-06 19:10:05 +08:00
|
|
|
|
|
2026-05-23 21:42:46 +08:00
|
|
|
|
最后更新:`2026-05-23`
|