From 437efc848ce8d640aa446bd36d732a7e4642450e Mon Sep 17 00:00:00 2001 From: rayd1o Date: Wed, 22 Apr 2026 03:52:09 +0800 Subject: [PATCH] release: bump version to 0.31.3 --- TODO.md | 2 + VERSION | 2 +- docs/CHANGELOG.md | 21 + docs/technical/earth-frontend-context.md | 82 ++ docs/version-history.md | 3 +- frontend/package.json | 2 +- frontend/public/earth/css/hud.css | 111 ++- frontend/public/earth/css/toolbar.css | 40 +- frontend/public/earth/index.html | 16 +- frontend/public/earth/js/celestial.js | 106 ++- frontend/public/earth/js/constants.js | 42 + frontend/public/earth/js/controls.js | 879 +++++++++++++++--- frontend/public/earth/js/earth.js | 50 +- .../public/earth/js/layer-startup-tasks.js | 174 ++++ frontend/public/earth/js/main.js | 264 +++--- frontend/public/earth/js/satellites.js | 23 +- frontend/public/earth/js/terrain.js | 16 +- pyproject.toml | 2 +- uv.lock | 2 +- 19 files changed, 1516 insertions(+), 321 deletions(-) create mode 100644 frontend/public/earth/js/layer-startup-tasks.js diff --git a/TODO.md b/TODO.md index 6da363a7..2a968fcd 100644 --- a/TODO.md +++ b/TODO.md @@ -20,3 +20,5 @@ - [x] 在 activity layer 之后继续补 `route leak` 和 `path instability / flap` detector - [ ] 对 [frontend/public/earth/js/bgp.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/bgp.js) 做按职责拆分的小重构,拆成 data / markers / overlays / animation,降低后续维护复杂度 - [ ] 可选优化(非必做):将 BGP incident/collector 标点改为 HTML marker(参考 worldmonitor 的 `htmlElementsData` 思路),实现近乎固定屏幕尺寸与更高密度可点击性 +- [ ] 保持 Earth 当前这批纯个人偏好设置继续走本地持久化:`旋转模式`、HUD 面板显示/隐藏、`地形透明度` 暂不升级到后端系统设置,避免把设备级偏好过早做成全局配置 +- [ ] 如果后续明确需要“账号级同步 Earth 偏好”,再单独设计 `Earth user preferences`:优先按用户维度而不是全局系统设置保存,并规划 `localStorage -> backend` 的平滑迁移策略 diff --git a/VERSION b/VERSION index c415e1c6..8239f42d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.31.2 +0.31.3 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9c9c8701..77529440 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,27 @@ This project follows the repository versioning rule: - `improvement` -> `+0.0.1`(bugfix + 小功能混合) - `bugfix` -> `+0.0.1` +## [0.31.3] — 2026-04-22 + +### ✨ Highlights +- Earth 图层注册表和启动任务框架继续收口,启动顺序、启动模式、启动提示和任务注册现在都能从统一入口扩展 +- 修复 Earth 普通旋转模式与巡航模式切换时的一组交互回归,同时让卫星/地形/昼夜模式的表现更稳定 + +### 🔧 Improvements +- 新增 [layer-startup-tasks.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/layer-startup-tasks.js) 启动任务注册表,支持 `registerLayerStartupTask(id, taskFactory)`,并拆成海缆 / 卫星 / BGP 独立注册函数 +- Earth 图层控制改成注册表驱动,统一承载 `startupPriority`、`startupMode`、`startupLabel`、`startupMessage` 与图层持久化元信息 +- Earth 设置支持持久化图层开关、旋转模式、HUD 面板显示状态、地形透明度与日夜模式,并提供一键重置 +- 更新 [earth-frontend-context.md](/home/ray/dev/linkong/planet/docs/technical/earth-frontend-context.md) 记录图层注册表、启动任务、设置持久化与巡航适配边界 + +### 🐛 Fixes +- 修复普通旋转模式下点击海缆 / 卫星 / BGP 后卡片和选中表现会被异常清空的问题 +- 修复巡航模式切回旋转再切回巡航后无法继续自动巡航的问题 +- 修复开启地形后卫星选中反馈层被高海拔区域吞掉的问题,并恢复轨道只在地球前半侧可见 +- 修复关闭日夜模式后地球照明仍沿真实昼夜切换、亮部过曝和偏色的问题,改成更中性的 inspection lighting +- 修复 toolbar 收起态仍挡住地球交互,以及首帧短暂展开闪现的问题 + +--- + ## [0.31.0] — 2026-04-21 ## [0.31.2] — 2026-04-21 diff --git a/docs/technical/earth-frontend-context.md b/docs/technical/earth-frontend-context.md index a9ed753b..d657257d 100644 --- a/docs/technical/earth-frontend-context.md +++ b/docs/technical/earth-frontend-context.md @@ -67,6 +67,7 @@ React 路由入口: - 旋转/缩放/布局 - HUD 面板拖拽 - 图层开关状态机 +- Earth 设置读取、持久化与重置 这份文件是 Earth 前端当前最核心的 UI 控制入口。 @@ -99,6 +100,7 @@ React 路由入口: - [bgp-cruise-adapter.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/bgp-cruise-adapter.js) - [news.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/news.js) - [tv.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/tv.js) +- [layer-startup-tasks.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/layer-startup-tasks.js) - [cruise-sequencer.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/cruise-sequencer.js) - [callout-connector.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/callout-connector.js) @@ -109,6 +111,16 @@ React 路由入口: - 面板内容 - hover/lock/selection 语义 +其中 Earth 启动加载链现在也拆成了两层: + +- `controls.js` + - 提供图层注册表与启动元信息 +- `layer-startup-tasks.js` + - 提供图层启动任务注册表 + - 通过 `registerLayerStartupTask(id, taskFactory)` 扩展启动任务 +- `main.js` + - 只负责读取排序后的启动图层,再按映射执行队列 + 其中巡航模式现在已经拆成两层: - `cruise-sequencer.js` @@ -169,6 +181,57 @@ Earth 图层按钮现在不应再只有“开/关”两态,而应支持: 因此后续如果别的图层也需要异步启用,应该直接走这套状态机,而不是再手写一套临时 loading class。 +另外,Earth 图层控制现在已经收成“注册表驱动”: + +- 图层元数据 + - `id` + - `icon` + - `label` + - `meta` + - `buttonId` + - `persist` + - `startupPriority` + - `startupMode` + - `startupLabel` + - `startupMessage` +- 图层行为 + - `getVisible()` + - `setVisible(next, options)` + +当前入口仍在 [controls.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/controls.js)。 + +这意味着后续新增图层时,优先应补一条图层注册定义,而不是同时去改: + +- 图层面板 HTML +- 持久化快照 +- 初始化恢复 +- click 绑定 + +这四处现在都应该由注册表派生。 + +其中: + +- `startupPriority` + - 描述图层参与启动加载时的顺序 +- `startupMode` + - `visible` + - 仅当前图层处于启用/可见状态时,才加入启动加载队列 + - `preload` + - 即使当前图层未显示,也会参与启动预加载 + +当前 `main.js` 会通过注册表读取排序后的启动图层列表,再动态拼装启动加载队列,而不是手写一串固定步骤。像 BGP 这类需要尽早准备数据、但不一定默认显示的图层,应该优先走 `startupMode: "preload"`,而不是在启动流程里写隐式特判。 + +此外,启动阶段给用户看的提示文案也应尽量从注册表派生: + +- `startupLabel` + - 用于描述当前启动任务的业务名称 +- `startupMessage` + - 用于描述启动中的提示文案 + - 可以是字符串 + - 也可以是对象,用于像海缆这种“准备阶段 / 主加载阶段”两段式文案 + +这样后续新增会参与启动加载的图层时,顺序、模式和提示文案都在同一处定义,不需要再去 `main.js` 里补第二套常量。 + ### `data-status-target` 图层按钮可以通过: @@ -182,6 +245,25 @@ Earth 图层按钮现在不应再只有“开/关”两态,而应支持: 以后别的异步图层也可以沿用这套约定。 +## 当前设置持久化 + +Earth 设置面板当前由 [controls.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/controls.js) 统一负责: + +- 捕获默认值 +- 从 `localStorage` 读取上次设置 +- 初始化应用当前设置 +- 用户变更后即时持久化 +- 一键重置回默认值 + +当前持久化的范围是: + +- 旋转模式 +- HUD 面板显示/隐藏 +- 图层控制开关:`地形 / 卫星 / 轨迹 / 海缆 / BGP` +- 地形透明度 + +也就是说,Earth 设置不是一次性 UI 状态了,而是本地设备级偏好。后续如果再加入新的设置项,应优先接入同一条持久化链,而不是各自散着写 `localStorage`。 + ## 当前地形链路 真实地形首次启用会慢,原因不只是一个: diff --git a/docs/version-history.md b/docs/version-history.md index 433c0a7b..6be5ff63 100644 --- a/docs/version-history.md +++ b/docs/version-history.md @@ -16,12 +16,13 @@ ## Current Version - `main` 当前主线历史推导到:`0.16.5` -- `dev` 当前开发分支历史推导到:`0.31.2` +- `dev` 当前开发分支历史推导到:`0.31.3` ## Timeline | Version | Type | Branch | Commit | Summary | | --- | --- | --- | --- | --- | +| `0.31.3` | bugfix | `dev` | `pending` | 收口 Earth 图层注册表与启动任务框架,修复旋转/巡航切换、卫星地形遮挡与日夜关闭照明回归 | | `0.31.2` | bugfix | `dev` | `pending` | 将 Earth 巡航模式拆成通用 sequencer、通用连线和 BGP 巡航适配层,并修复空白点击推进与连线动画回归 | | `0.31.1` | bugfix | `dev` | `pending` | Earth 图层开关统一 loading 状态机,卫星首次加载可见化,并将文档按 technical / plans / deprecated 重构归档 | | `0.31.0` | feature | `dev` | `pending` | Earth 巡航展示模式:自动轮播 BGP 事件,连线逐帧追踪,卫星/海缆联动高亮,视觉状态全面统一 | diff --git a/frontend/package.json b/frontend/package.json index 540783b3..752e928b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "planet-frontend", - "version": "0.31.2", + "version": "0.31.3", "private": true, "packageManager": "bun@1", "dependencies": { diff --git a/frontend/public/earth/css/hud.css b/frontend/public/earth/css/hud.css index 8e773d50..c5193d8f 100644 --- a/frontend/public/earth/css/hud.css +++ b/frontend/public/earth/css/hud.css @@ -538,7 +538,7 @@ .earth-settings-kicker { color: var(--hud-text-soft); - font-size: var(--hud-panel-header-title-size); + font-size: calc(0.72rem * var(--hud-scale)); letter-spacing: 0.16em; text-transform: uppercase; } @@ -548,6 +548,22 @@ flex-shrink: 0; } +.earth-settings-reset { + display: inline-flex; + align-items: center; + gap: 6px; + margin-left: auto; + padding-inline: calc(10px * var(--hud-scale)); + color: var(--hud-text-soft); + font-size: calc(0.68rem * var(--hud-scale)); + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.earth-settings-reset .material-symbols-rounded { + font-size: calc(0.86rem * var(--hud-scale)); +} + .earth-settings-content { overflow-y: auto; padding-right: 4px; @@ -575,7 +591,7 @@ .earth-settings-section-title { margin-bottom: 12px; color: var(--hud-text-soft); - font-size: var(--hud-kicker-size); + font-size: calc(0.62rem * var(--hud-scale)); letter-spacing: 0.16em; text-transform: uppercase; } @@ -590,9 +606,9 @@ display: flex; align-items: center; justify-content: space-between; - gap: 16px; - padding: 15px 16px; - border-radius: 16px; + gap: 12px; + padding: 11px 14px; + border-radius: 14px; background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent), rgba(255, 255, 255, 0.025); @@ -648,10 +664,10 @@ border: 0; background: transparent; color: var(--hud-text-soft); - padding: 8px 14px; + padding: calc(5px * var(--hud-scale)) calc(10px * var(--hud-scale)); border-radius: 999px; font: inherit; - font-size: 0.82rem; + font-size: calc(0.7rem * var(--hud-scale)); font-weight: 600; letter-spacing: 0.02em; cursor: pointer; @@ -680,18 +696,23 @@ .earth-settings-slider { flex: 1 1 auto; width: 100%; - height: 6px; + height: calc(4px * var(--hud-scale)); appearance: none; background: linear-gradient(90deg, rgba(132, 164, 204, 0.32), rgba(94, 130, 172, 0.5)); border-radius: 999px; outline: none; cursor: pointer; + transition: background 0.18s ease; +} + +.earth-settings-slider:hover { + background: linear-gradient(90deg, rgba(152, 184, 224, 0.44), rgba(114, 155, 202, 0.64)); } .earth-settings-slider::-webkit-slider-thumb { appearance: none; - width: 18px; - height: 18px; + width: calc(14px * var(--hud-scale)); + height: calc(14px * var(--hud-scale)); border-radius: 50%; background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.22) 55%, transparent 70%), @@ -699,26 +720,62 @@ border: 1px solid rgba(222, 236, 252, 0.4); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06), - 0 6px 16px rgba(0, 0, 0, 0.24); + 0 4px 10px rgba(0, 0, 0, 0.24); + transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease; +} + +.earth-settings-slider:hover::-webkit-slider-thumb { + transform: scale(1.22); + background: + radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.32) 55%, transparent 70%), + linear-gradient(180deg, rgba(188, 216, 252, 1), rgba(108, 155, 210, 0.98)); + border-color: rgba(232, 244, 255, 0.72); + box-shadow: + 0 0 0 3px rgba(145, 186, 255, 0.22), + 0 6px 14px rgba(0, 0, 0, 0.3); +} + +.earth-settings-slider:active::-webkit-slider-thumb { + transform: scale(1.08); + box-shadow: + 0 0 0 4px rgba(145, 186, 255, 0.32), + 0 4px 10px rgba(0, 0, 0, 0.28); } .earth-settings-slider::-moz-range-thumb { - width: 18px; - height: 18px; + width: calc(14px * var(--hud-scale)); + height: calc(14px * var(--hud-scale)); border-radius: 50%; background: linear-gradient(180deg, rgba(164, 196, 236, 0.95), rgba(85, 127, 181, 0.92)); border: 1px solid rgba(222, 236, 252, 0.4); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06), - 0 6px 16px rgba(0, 0, 0, 0.24); + 0 4px 10px rgba(0, 0, 0, 0.24); + transition: transform 0.18s ease, box-shadow 0.18s ease; +} + +.earth-settings-slider:hover::-moz-range-thumb { + transform: scale(1.22); + background: linear-gradient(180deg, rgba(188, 216, 252, 1), rgba(108, 155, 210, 0.98)); + border-color: rgba(232, 244, 255, 0.72); + box-shadow: + 0 0 0 3px rgba(145, 186, 255, 0.22), + 0 6px 14px rgba(0, 0, 0, 0.3); +} + +.earth-settings-slider:active::-moz-range-thumb { + transform: scale(1.08); + box-shadow: + 0 0 0 4px rgba(145, 186, 255, 0.32), + 0 4px 10px rgba(0, 0, 0, 0.28); } .earth-settings-slider-value { flex: 0 0 auto; - min-width: 46px; + min-width: calc(34px * var(--hud-scale)); text-align: right; color: var(--hud-text-soft); - font-size: 0.78rem; + font-size: calc(0.66rem * var(--hud-scale)); letter-spacing: 0.04em; font-variant-numeric: tabular-nums; } @@ -731,13 +788,13 @@ .earth-settings-item-title { color: var(--hud-text); - font-size: calc(0.98rem * var(--hud-scale)); + font-size: calc(0.76rem * var(--hud-scale)); font-weight: 600; } .earth-settings-item-subtitle { color: var(--hud-text-muted); - font-size: 0.82rem; + font-size: calc(0.67rem * var(--hud-scale)); line-height: 1.4; } @@ -750,11 +807,11 @@ } .earth-settings-link-meta .material-symbols-rounded:first-child { - font-size: 1.1rem; + font-size: calc(0.9rem * var(--hud-scale)); } .earth-settings-link-meta .material-symbols-rounded:last-child { - font-size: 1rem; + font-size: calc(0.82rem * var(--hud-scale)); } .earth-settings-switch { @@ -770,8 +827,8 @@ } .earth-settings-switch-track { - width: 48px; - height: 30px; + width: calc(38px * var(--hud-scale)); + height: calc(22px * var(--hud-scale)); border-radius: 999px; background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(215, 229, 242, 0.12); @@ -782,10 +839,10 @@ .earth-settings-switch-track::after { content: ""; position: absolute; - top: 3px; - left: 3px; - width: 22px; - height: 22px; + top: calc(3px * var(--hud-scale)); + left: calc(3px * var(--hud-scale)); + width: calc(16px * var(--hud-scale)); + height: calc(16px * var(--hud-scale)); border-radius: 50%; background: #edf4fc; box-shadow: 0 6px 14px rgba(1, 8, 18, 0.26); @@ -798,7 +855,7 @@ } .earth-settings-switch input:checked + .earth-settings-switch-track::after { - transform: translateX(18px); + transform: translateX(calc(16px * var(--hud-scale))); } @media (max-width: 960px) { diff --git a/frontend/public/earth/css/toolbar.css b/frontend/public/earth/css/toolbar.css index 33898b6f..353be6b4 100644 --- a/frontend/public/earth/css/toolbar.css +++ b/frontend/public/earth/css/toolbar.css @@ -9,6 +9,7 @@ align-items: center; justify-content: center; z-index: 200; + pointer-events: none; } .earth-toolbar-group, @@ -40,6 +41,7 @@ border: none; box-shadow: none; padding: 0; + pointer-events: none; } .earth-toolbar-cluster { @@ -103,6 +105,14 @@ pointer-events: auto; } +.earth-toolbar-cluster.is-collapsed .earth-toolbar-orb > * { + pointer-events: none; +} + +.earth-toolbar-hub > * { + pointer-events: auto; +} + .earth-toolbar-orb > .liquid-glass-surface { animation: floatDock 4.6s ease-in-out infinite; animation-delay: var(--orb-delay, 0s); @@ -120,7 +130,7 @@ border: none; background: transparent; color: var(--hud-text-soft); - font-size: 14px; + font-size: calc(14px * var(--toolbar-scale)); cursor: pointer; display: inline-flex; align-items: center; @@ -361,7 +371,7 @@ opacity: 0; visibility: hidden; pointer-events: none; - transform: translate(-50%, 8px); + transform: translate(-50%, calc(8px * var(--toolbar-scale))); } .earth-toolbar-popover::before { @@ -381,7 +391,7 @@ top: auto; right: auto; bottom: calc(100% + (12px * var(--toolbar-scale))); - transform: translate(-50%, 10px); + transform: translate(-50%, calc(10px * var(--toolbar-scale))); display: flex; flex-direction: column; align-items: center; @@ -398,16 +408,16 @@ .earth-zoom-toolbar .earth-zoom-btn, .earth-zoom-toolbar .earth-zoom-value { - width: 42px; - min-width: 42px; + width: calc(42px * var(--toolbar-scale)); + min-width: calc(42px * var(--toolbar-scale)); border-radius: 50%; color: var(--hud-text-soft); animation: none; } .earth-zoom-toolbar .earth-zoom-btn { - height: 42px; - font-size: 20px; + height: calc(42px * var(--toolbar-scale)); + font-size: calc(20px * var(--toolbar-scale)); font-weight: 500; line-height: 1; } @@ -416,9 +426,9 @@ display: inline-flex; align-items: center; justify-content: center; - height: 42px; + height: calc(42px * var(--toolbar-scale)); padding: 0; - font-size: 0.68rem; + font-size: calc(11px * var(--toolbar-scale)); letter-spacing: normal; } @@ -429,15 +439,15 @@ .earth-toolbar-btn .earth-toolbar-tooltip { position: absolute; - bottom: 56px; + bottom: calc(56px * var(--toolbar-scale)); left: 50%; transform: translateX(-50%); background: linear-gradient(180deg, rgba(18, 31, 52, 0.96), rgba(8, 18, 32, 0.95)); color: var(--hud-text); - padding: 6px 12px; - border-radius: 6px; - font-size: 12px; + padding: calc(6px * var(--toolbar-scale)) calc(12px * var(--toolbar-scale)); + border-radius: calc(6px * var(--toolbar-scale)); + font-size: calc(12px * var(--toolbar-scale)); white-space: nowrap; opacity: 0; visibility: hidden; @@ -453,7 +463,7 @@ .earth-toolbar-popover:focus-within > .earth-toolbar-btn .earth-toolbar-tooltip { opacity: 1; visibility: visible; - bottom: 58px; + bottom: calc(58px * var(--toolbar-scale)); } .earth-toolbar-btn .earth-toolbar-tooltip::after { @@ -462,6 +472,6 @@ top: 100%; left: 50%; transform: translateX(-50%); - border: 6px solid transparent; + border: calc(6px * var(--toolbar-scale)) solid transparent; border-top-color: rgba(18, 31, 52, 0.96); } diff --git a/frontend/public/earth/index.html b/frontend/public/earth/index.html index d0f94d7a..43df5e51 100644 --- a/frontend/public/earth/index.html +++ b/frontend/public/earth/index.html @@ -154,7 +154,7 @@
-
+