diff --git a/VERSION b/VERSION index 8239f42d..9eb2aa3f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.31.3 +0.32.0 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 77529440..becbda1b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,25 @@ This project follows the repository versioning rule: - `improvement` -> `+0.0.1`(bugfix + 小功能混合) - `bugfix` -> `+0.0.1` +## [0.32.0] — 2026-04-22 + +### ✨ Highlights +- Earth 设置新增“地球默认大小”持久化项,重置视角、缩放百分比重置和 BGP 巡航视图现在统一复用这一份默认 zoom +- 卫星焦点层次继续收口:巡航进入 presentation 前不再过早 dim,非焦点卫星改成“降亮度/尾迹/背板”而不是去饱和度 + +### 🔧 Improvements +- Earth 设置面板区块和左右留白进一步收紧,整体更贴近 HUD 面板的密度 +- toolbar 展开边界缓存改为按需刷新,减少 document 级 mousemove 期间的重复布局读取 +- Scrollbar 和 ScrollbarOverlay 收窄 observer 范围,减少大表格和动态菜单下的额外刷新成本 +- 更新 [earth-frontend-context.md](/home/ray/dev/linkong/planet/docs/technical/earth-frontend-context.md),补充默认视图大小已进入 Earth 设置持久化真源 + +### 🐛 Fixes +- 修复开启巡航后,尚未进入连线/presentation 时卫星已经整体变暗的问题 +- 修复默认大小重置链路分散在多个入口、实际 reset/cruise/缩放提示不一致的问题 +- 修复开启地形后卫星反馈层与地球背面可见性之间的一组表现问题,保留正面反馈同时恢复背面轨道遮挡 + +--- + ## [0.31.3] — 2026-04-22 ### ✨ Highlights diff --git a/docs/technical/earth-frontend-context.md b/docs/technical/earth-frontend-context.md index d657257d..b2d6c5e9 100644 --- a/docs/technical/earth-frontend-context.md +++ b/docs/technical/earth-frontend-context.md @@ -258,6 +258,7 @@ Earth 设置面板当前由 [controls.js](/home/ray/dev/linkong/planet/frontend/ 当前持久化的范围是: - 旋转模式 +- 地球默认大小(作为重置视角、缩放重置和巡航视图的默认 zoom 真源) - HUD 面板显示/隐藏 - 图层控制开关:`地形 / 卫星 / 轨迹 / 海缆 / BGP` - 地形透明度 diff --git a/docs/version-history.md b/docs/version-history.md index 6be5ff63..1916da29 100644 --- a/docs/version-history.md +++ b/docs/version-history.md @@ -16,12 +16,13 @@ ## Current Version - `main` 当前主线历史推导到:`0.16.5` -- `dev` 当前开发分支历史推导到:`0.31.3` +- `dev` 当前开发分支历史推导到:`0.32.0` ## Timeline | Version | Type | Branch | Commit | Summary | | --- | --- | --- | --- | --- | +| `0.32.0` | feature | `dev` | `pending` | Earth 设置新增默认地球大小真源,并继续收口卫星焦点层次、toolbar/scrollbar 性能与 HUD 设置面板细节 | | `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 重构归档 | diff --git a/frontend/package.json b/frontend/package.json index 752e928b..67ad99ce 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "planet-frontend", - "version": "0.31.3", + "version": "0.32.0", "private": true, "packageManager": "bun@1", "dependencies": { diff --git a/frontend/public/earth/css/hud.css b/frontend/public/earth/css/hud.css index c5193d8f..f75badf0 100644 --- a/frontend/public/earth/css/hud.css +++ b/frontend/public/earth/css/hud.css @@ -566,7 +566,8 @@ .earth-settings-content { overflow-y: auto; - padding-right: 4px; + padding-inline: 8px; + padding-right: 10px; scrollbar-width: thin; scrollbar-color: rgba(160, 186, 216, 0.34) transparent; } @@ -585,11 +586,11 @@ } .earth-settings-section { - padding: 12px 0 20px; + padding: 6px 0 10px; } .earth-settings-section-title { - margin-bottom: 12px; + margin-bottom: 10px; color: var(--hud-text-soft); font-size: calc(0.62rem * var(--hud-scale)); letter-spacing: 0.16em; @@ -599,7 +600,7 @@ .earth-settings-list { display: flex; flex-direction: column; - gap: 10px; + gap: 8px; } .earth-settings-item { @@ -607,7 +608,7 @@ align-items: center; justify-content: space-between; gap: 12px; - padding: 11px 14px; + padding: 10px 13px; border-radius: 14px; background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent), @@ -629,7 +630,7 @@ .earth-settings-item--stacked { align-items: stretch; flex-direction: column; - gap: 14px; + gap: 10px; cursor: default; } @@ -644,7 +645,7 @@ .earth-settings-slider-row { display: flex; align-items: center; - gap: 14px; + gap: 12px; } .earth-settings-segmented { @@ -783,7 +784,7 @@ .earth-settings-copy { display: flex; flex-direction: column; - gap: 4px; + gap: 3px; } .earth-settings-item-title { diff --git a/frontend/public/earth/index.html b/frontend/public/earth/index.html index 43df5e51..c4882284 100644 --- a/frontend/public/earth/index.html +++ b/frontend/public/earth/index.html @@ -512,6 +512,30 @@ +
+
视图
+
+
+
+ 地球默认大小 + 用于重置视角、缩放重置和巡航视图的默认缩放比例 +
+
+ + 100% +
+
+
+
地形
diff --git a/frontend/public/earth/js/bgp-cruise-adapter.js b/frontend/public/earth/js/bgp-cruise-adapter.js index 679b3b48..a0de8c70 100644 --- a/frontend/public/earth/js/bgp-cruise-adapter.js +++ b/frontend/public/earth/js/bgp-cruise-adapter.js @@ -169,13 +169,11 @@ export function createBGPCruiseAdapter({ cardPlacement = getCardScreenCoords(marker); setMarkerLocked(marker); showMarkerOverlay(marker); - applySatelliteHighlights(marker); await focusView({ lat: marker.userData?.latitude ?? 0, lon: marker.userData?.longitude ?? 0, rotLon: (marker.userData?.longitude ?? 0) - 270, - zoom: 1.0, duration: interrupt ? Math.round(CRUISE_CONFIG.focusDurationMs * 0.78) : CRUISE_CONFIG.focusDurationMs, @@ -203,6 +201,8 @@ export function createBGPCruiseAdapter({ return false; } + applySatelliteHighlights(marker); + const connectorDelayCompleted = await context.wait(CRUISE_CONNECTOR_DRAW_MS); if (!connectorDelayCompleted || !context.isCurrent()) { cardPlacement = null; diff --git a/frontend/public/earth/js/constants.js b/frontend/public/earth/js/constants.js index 8cdac78f..f764be17 100644 --- a/frontend/public/earth/js/constants.js +++ b/frontend/public/earth/js/constants.js @@ -3,6 +3,7 @@ // Scene configuration export const CONFIG = { defaultCameraZ: 300, + defaultViewZoom: 1.0, minZoom: 0.5, maxZoom: 5.0, earthRadius: 100, diff --git a/frontend/public/earth/js/controls.js b/frontend/public/earth/js/controls.js index 167b2ec7..b6d41e89 100644 --- a/frontend/public/earth/js/controls.js +++ b/frontend/public/earth/js/controls.js @@ -44,6 +44,8 @@ export let showTerrain = false; export let layoutExpanded = false; export let rotationMode = ROTATION_MODE.ROTATE; let dayNightEnabled = true; +let defaultEarthZoom = CONFIG.defaultViewZoom; +let activeCamera = null; let earthObj = null; let listeners = []; @@ -73,6 +75,7 @@ const SETTINGS_SHEET_MIN_SCALE = 0.06; const SETTINGS_SHEET_MAX_SCALE_X = 0.22; const SETTINGS_SHEET_MAX_SCALE_Y = 0.18; const EARTH_SETTINGS_STORAGE_KEY = "planet.earth.settings.v1"; +const DEFAULT_EARTH_ZOOM_STEP = 0.01; let settingsModalTimer = null; let settingsSheetAnimation = null; let terrainToggleToken = 0; @@ -120,6 +123,26 @@ function shouldIncludeLayerInStartupLoad(definition) { return Boolean(definition?.getVisible?.()); } +function clampEarthZoomLevel(nextZoom) { + const parsedZoom = Number.parseFloat(nextZoom); + if (!Number.isFinite(parsedZoom)) { + return CONFIG.defaultViewZoom; + } + return Math.min(CONFIG.maxZoom, Math.max(CONFIG.minZoom, parsedZoom)); +} + +function formatZoomPercent(zoom) { + return `${Math.round(zoom * 100)}%`; +} + +function getZoomResetTooltipText(zoom) { + return `重置缩放到${formatZoomPercent(zoom)}`; +} + +function getZoomResetStatusMessage(zoom) { + return `缩放已重置到${formatZoomPercent(zoom)}`; +} + function canUseLocalStorage() { try { return typeof window !== "undefined" && !!window.localStorage; @@ -145,6 +168,7 @@ function getCurrentSettingsSnapshot() { ), terrainOpacity: getTerrainOpacity(), dayNightEnabled, + defaultEarthZoom, }; } @@ -160,6 +184,7 @@ function cloneEarthSettings(settings) { rotationMode: settings.rotationMode, terrainOpacity: settings.terrainOpacity, dayNightEnabled: settings.dayNightEnabled, + defaultEarthZoom: settings.defaultEarthZoom, panelVisibility: { ...(settings.panelVisibility || {}) }, layerVisibility: { ...(settings.layerVisibility || {}) }, }; @@ -197,6 +222,9 @@ function normalizeEarthSettings(rawSettings, defaults) { const nextDayNightEnabled = typeof rawSettings?.dayNightEnabled === "boolean" ? rawSettings.dayNightEnabled : defaults.dayNightEnabled; + const nextDefaultEarthZoom = clampEarthZoomLevel( + rawSettings?.defaultEarthZoom ?? defaults.defaultEarthZoom, + ); return { rotationMode: nextRotationMode, @@ -206,6 +234,7 @@ function normalizeEarthSettings(rawSettings, defaults) { ? nextTerrainOpacity : defaults.terrainOpacity, dayNightEnabled: nextDayNightEnabled, + defaultEarthZoom: nextDefaultEarthZoom, }; } @@ -251,6 +280,46 @@ function persistEarthSettings() { } } +function syncDefaultEarthZoomUi(nextZoom) { + const slider = document.getElementById("default-earth-size-slider"); + const value = document.getElementById("default-earth-size-value"); + const zoomValue = document.getElementById("zoom-value"); + const tooltipText = getZoomResetTooltipText(nextZoom); + + if (slider instanceof HTMLInputElement) { + slider.min = CONFIG.minZoom.toString(); + slider.max = CONFIG.maxZoom.toString(); + slider.step = DEFAULT_EARTH_ZOOM_STEP.toString(); + slider.value = nextZoom.toFixed(2); + } + if (value) { + value.textContent = formatZoomPercent(nextZoom); + } + if (zoomValue instanceof HTMLElement) { + zoomValue.title = tooltipText; + const tooltip = zoomValue.querySelector(".tooltip"); + if (tooltip) { + tooltip.textContent = tooltipText; + } + } +} + +function setDefaultEarthZoom(nextZoom, { persist = true, applyToCurrentView = true } = {}) { + defaultEarthZoom = clampEarthZoomLevel(nextZoom); + syncDefaultEarthZoomUi(defaultEarthZoom); + + if (applyToCurrentView && activeCamera) { + zoomLevel = defaultEarthZoom; + applyZoom(activeCamera); + } + + if (persist) { + persistEarthSettings(); + } + + return defaultEarthZoom; +} + async function applyEarthSettings(settings) { if (!settings) return; @@ -277,6 +346,11 @@ async function applyEarthSettings(settings) { applyDayNightEnabled(settings.dayNightEnabled, { persist: false }); } + setDefaultEarthZoom(settings.defaultEarthZoom, { + persist: false, + applyToCurrentView: true, + }); + await applyLayerVisibilitySettings(settings.layerVisibility, { persist: false, silent: true, @@ -660,7 +734,7 @@ export function applyImmediateView(targetEarthObj, camera, options = {}) { const { lat = EARTH_CONFIG.chinaLat, rotLon = EARTH_CONFIG.chinaRotLon, - zoom = 1.0, + zoom = getDefaultEarthZoomLevel(), } = options; const nextRotation = getViewRotation(lat, rotLon); @@ -956,6 +1030,7 @@ function setupSettingsControls() { const terrainOpacitySlider = document.getElementById("terrain-opacity-slider"); const terrainOpacityValue = document.getElementById("terrain-opacity-value"); + const defaultEarthSizeSlider = document.getElementById("default-earth-size-slider"); const rotationModeButtons = document.querySelectorAll("[data-rotation-mode]"); const syncTerrainOpacityUi = (nextOpacity) => { const safeOpacity = Math.round(nextOpacity * 100); @@ -968,6 +1043,7 @@ function setupSettingsControls() { }; syncTerrainOpacityUi(getTerrainOpacity()); + syncDefaultEarthZoomUi(defaultEarthZoom); if (terrainOpacitySlider instanceof HTMLInputElement) { bindListener(terrainOpacitySlider, "input", (event) => { @@ -982,6 +1058,18 @@ function setupSettingsControls() { }); } + if (defaultEarthSizeSlider instanceof HTMLInputElement) { + bindListener(defaultEarthSizeSlider, "input", (event) => { + const target = event.currentTarget; + if (!(target instanceof HTMLInputElement)) return; + const nextZoom = Number.parseFloat(target.value); + setDefaultEarthZoom( + Number.isFinite(nextZoom) ? nextZoom : defaultEarthZoom, + { persist: true, applyToCurrentView: true }, + ); + }); + } + rotationModeButtons.forEach((button) => { bindListener(button, "click", (event) => { const target = event.currentTarget; @@ -1303,6 +1391,7 @@ function resetCleanup() { export function setupControls(camera, renderer, scene, earth) { resetCleanup(); + activeCamera = camera; earthObj = earth; setupZoomControls(camera); setupWheelZoom(camera, renderer); @@ -1407,7 +1496,7 @@ function setupZoomControls(camera) { bindListener(zoomValue, "click", () => { const startZoomVal = zoomLevel; - const targetZoom = 1.0; + const targetZoom = getDefaultEarthZoomLevel(); const startDistance = CONFIG.defaultCameraZ / startZoomVal; const targetDistance = CONFIG.defaultCameraZ / targetZoom; @@ -1424,8 +1513,8 @@ function setupZoomControls(camera) { updateZoomDisplay(zoomLevel, distance.toFixed(0)); }, () => { - zoomLevel = 1.0; - showStatusMessage("缩放已重置到100%", "info"); + zoomLevel = targetZoom; + showStatusMessage(getZoomResetStatusMessage(targetZoom), "info"); }, ); }); @@ -1482,6 +1571,7 @@ function animateValue(start, end, duration, onUpdate, onComplete) { export function resetView(camera) { if (!earthObj) return; + const defaultZoom = getDefaultEarthZoomLevel(); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( @@ -1490,7 +1580,7 @@ export function resetView(camera) { lat: pos.coords.latitude, lon: pos.coords.longitude, rotLon: pos.coords.longitude - 270, - zoom: 1.0, + zoom: defaultZoom, duration: 800, suppressStatus: false, }), @@ -1499,7 +1589,7 @@ export function resetView(camera) { lat: EARTH_CONFIG.chinaLat, lon: EARTH_CONFIG.chinaLon, rotLon: EARTH_CONFIG.chinaRotLon, - zoom: 1.0, + zoom: defaultZoom, duration: 800, suppressStatus: false, }), @@ -1510,7 +1600,7 @@ export function resetView(camera) { lat: EARTH_CONFIG.chinaLat, lon: EARTH_CONFIG.chinaLon, rotLon: EARTH_CONFIG.chinaRotLon, - zoom: 1.0, + zoom: defaultZoom, duration: 800, suppressStatus: false, }); @@ -1877,6 +1967,8 @@ function setupToolbarHubCluster() { } let collapseTimer = null; + let expandedToolbarBounds = null; + let refreshBoundsFrameId = 0; const layoutToolbarOrbs = () => { const orbs = Array.from(cluster.querySelectorAll(".earth-toolbar-orb")); @@ -1942,11 +2034,24 @@ function setupToolbarHubCluster() { orb.style.setProperty("--orb-x", `${x.toFixed(2)}px`); orb.style.setProperty("--orb-y", `${y.toFixed(2)}px`); }); + + if (cluster.classList.contains("is-expanded")) { + scheduleExpandedToolbarBoundsRefresh(); + } }; const setExpanded = (expanded) => { cluster.classList.toggle("is-expanded", expanded); cluster.classList.toggle("is-collapsed", !expanded); + if (!expanded) { + expandedToolbarBounds = null; + if (refreshBoundsFrameId) { + cancelAnimationFrame(refreshBoundsFrameId); + refreshBoundsFrameId = 0; + } + return; + } + scheduleExpandedToolbarBoundsRefresh(); }; const scheduleCollapse = () => { @@ -1966,6 +2071,10 @@ function setupToolbarHubCluster() { cleanupFns.push(() => { if (collapseTimer) clearTimeout(collapseTimer); + if (refreshBoundsFrameId) { + cancelAnimationFrame(refreshBoundsFrameId); + refreshBoundsFrameId = 0; + } }); // Start collapsed — hub acts as the hover target to reveal the arc @@ -2034,9 +2143,23 @@ function setupToolbarHubCluster() { }; }; + const scheduleExpandedToolbarBoundsRefresh = () => { + if (refreshBoundsFrameId) return; + refreshBoundsFrameId = window.requestAnimationFrame(() => { + expandedToolbarBounds = collectExpandedToolbarBounds(); + refreshBoundsFrameId = 0; + }); + }; + bindListener(document, "mousemove", (event) => { if (!cluster.classList.contains("is-expanded")) return; - const activeBounds = collectExpandedToolbarBounds(); + if ( + event.target instanceof Element && + event.target.closest("#toolbar-cluster, .earth-stack-toolbar") + ) { + scheduleExpandedToolbarBoundsRefresh(); + } + const activeBounds = expandedToolbarBounds; if (!activeBounds) { scheduleCollapse(); return; @@ -2052,10 +2175,23 @@ function setupToolbarHubCluster() { scheduleCollapse(); } }); + + bindListener(cluster, "mouseenter", () => { + if (cluster.classList.contains("is-expanded")) { + scheduleExpandedToolbarBoundsRefresh(); + } + }); + + bindListener(cluster, "focusin", () => { + if (cluster.classList.contains("is-expanded")) { + scheduleExpandedToolbarBoundsRefresh(); + } + }); } export function teardownControls() { resetCleanup(); + activeCamera = null; } export function getAutoRotate() { @@ -2143,7 +2279,7 @@ export function focusEarthView(camera, options = {}) { lat = EARTH_CONFIG.chinaLat, lon = EARTH_CONFIG.chinaLon, rotLon = lon - 270, - zoom = 1.0, + zoom = getDefaultEarthZoomLevel(), duration = 800, suppressStatus = true, } = options; @@ -2181,6 +2317,10 @@ export function getZoomLevel() { return zoomLevel; } +export function getDefaultEarthZoomLevel() { + return defaultEarthZoom; +} + export function getShowTerrain() { return showTerrain; } diff --git a/frontend/public/earth/js/satellites.js b/frontend/public/earth/js/satellites.js index de1397fd..7109d715 100644 --- a/frontend/public/earth/js/satellites.js +++ b/frontend/public/earth/js/satellites.js @@ -31,6 +31,10 @@ let satelliteSatrecCache = new Map(); const TRAIL_LENGTH = SATELLITE_CONFIG.trailLength; const DOT_TEXTURE_SIZE = 32; const POSITION_UPDATE_INTERVAL_MS = 250; +const DIMMED_SATELLITE_BRIGHTNESS = 0.42; +const DIMMED_SATELLITE_TRAIL_BRIGHTNESS = 0.24; +const DIMMED_SATELLITE_POINT_OPACITY = 0.62; +const DIMMED_SATELLITE_BACKDROP_OPACITY = 0.1; const scratchWorldSatellitePosition = new THREE.Vector3(); const scratchToCamera = new THREE.Vector3(); @@ -746,16 +750,16 @@ export function updateSatellitePositions(deltaTime = 0, force = false) { const rule = getSatelliteLegendRule(props); const { r, g, b } = getSatelliteRuleColor(rule); - if (highlightedSatelliteIndices !== null && !highlightedSatelliteIndices.has(i)) { - const lum = r * 0.299 + g * 0.587 + b * 0.114; - colors[i * 3] = lum * 0.75 + r * 0.25; - colors[i * 3 + 1] = lum * 0.75 + g * 0.25; - colors[i * 3 + 2] = lum * 0.75 + b * 0.25; - } else { - colors[i * 3] = r; - colors[i * 3 + 1] = g; - colors[i * 3 + 2] = b; - } + const isNonFocusDimmed = + highlightedSatelliteIndices !== null && !highlightedSatelliteIndices.has(i); + const pointBrightness = isNonFocusDimmed ? DIMMED_SATELLITE_BRIGHTNESS : 1; + const trailBrightness = isNonFocusDimmed + ? DIMMED_SATELLITE_TRAIL_BRIGHTNESS + : 1; + + colors[i * 3] = r * pointBrightness; + colors[i * 3 + 1] = g * pointBrightness; + colors[i * 3 + 2] = b * pointBrightness; const satPosition = satellitePositions[i]; for (let j = 0; j < TRAIL_LENGTH; j++) { @@ -771,9 +775,9 @@ export function updateSatellitePositions(deltaTime = 0, force = false) { trailPositions[trailIdx + 1] = trailPoint.y; trailPositions[trailIdx + 2] = trailPoint.z; const alpha = (j + 1) / satPosition.trailCount; - trailColors[trailIdx] = r * alpha; - trailColors[trailIdx + 1] = g * alpha; - trailColors[trailIdx + 2] = b * alpha; + trailColors[trailIdx] = r * alpha * trailBrightness; + trailColors[trailIdx + 1] = g * alpha * trailBrightness; + trailColors[trailIdx + 2] = b * alpha * trailBrightness; continue; } } @@ -1097,10 +1101,10 @@ export function setSatelliteRingState(index, state, position) { function applyDimMaterialState(isDimmed) { if (satellitePoints) { - satellitePoints.material.opacity = isDimmed ? 0.32 : 0.9; + satellitePoints.material.opacity = isDimmed ? DIMMED_SATELLITE_POINT_OPACITY : 0.9; } if (satelliteBackdropPoints) { - satelliteBackdropPoints.material.opacity = isDimmed ? 0.12 : 0.42; + satelliteBackdropPoints.material.opacity = isDimmed ? DIMMED_SATELLITE_BACKDROP_OPACITY : 0.42; } } diff --git a/frontend/public/earth/js/ui.js b/frontend/public/earth/js/ui.js index dcf303a9..d0d628bb 100644 --- a/frontend/public/earth/js/ui.js +++ b/frontend/public/earth/js/ui.js @@ -155,7 +155,15 @@ export function updateZoomDisplay(zoomLevel, distance) { const slider = getElement("zoom-slider"); const cameraDistanceEl = getElement("camera-distance"); - if (zoomValueEl) zoomValueEl.textContent = percent + "%"; + if (zoomValueEl) { + const tooltip = zoomValueEl.querySelector(".tooltip"); + const label = `${percent}%`; + if (zoomValueEl.firstChild?.nodeType === Node.TEXT_NODE) { + zoomValueEl.firstChild.nodeValue = label; + } else { + zoomValueEl.insertBefore(document.createTextNode(label), tooltip || null); + } + } if (zoomLevelEl) zoomLevelEl.textContent = "缩放: " + percent + "%"; if (slider) slider.value = zoomLevel; if (cameraDistanceEl) cameraDistanceEl.textContent = distance + " km"; diff --git a/frontend/src/components/Scrollbar/Scrollbar.tsx b/frontend/src/components/Scrollbar/Scrollbar.tsx index 81ea9fd3..5fd54519 100644 --- a/frontend/src/components/Scrollbar/Scrollbar.tsx +++ b/frontend/src/components/Scrollbar/Scrollbar.tsx @@ -132,13 +132,10 @@ function Scrollbar({ resizeObserver.observe(viewport) resizeObserver.observe(trackX) resizeObserver.observe(trackY) - Array.from(viewport.children).forEach((child) => resizeObserver.observe(child)) mutationObserver.observe(viewport, { childList: true, subtree: true, - attributes: true, - characterData: true, }) viewport.addEventListener('scroll', scheduleUpdate, { passive: true }) diff --git a/frontend/src/components/Scrollbar/ScrollbarOverlay.tsx b/frontend/src/components/Scrollbar/ScrollbarOverlay.tsx index a7b0f23e..f883c699 100644 --- a/frontend/src/components/Scrollbar/ScrollbarOverlay.tsx +++ b/frontend/src/components/Scrollbar/ScrollbarOverlay.tsx @@ -156,7 +156,6 @@ function ScrollbarOverlay({ scheduleUpdate() }) resizeObserver.observe(target) - Array.from(target.children).forEach((child) => resizeObserver?.observe(child)) scheduleUpdate() } @@ -169,7 +168,6 @@ function ScrollbarOverlay({ mutationObserver.observe(container, { childList: true, subtree: true, - attributes: true, }) window.addEventListener('resize', scheduleUpdate) diff --git a/pyproject.toml b/pyproject.toml index b27d25b9..9f3e3157 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "planet" -version = "0.31.3" +version = "0.32.0" description = "智能星球计划 - 态势感知系统" requires-python = ">=3.14" dependencies = [ diff --git a/uv.lock b/uv.lock index f0e2f2b7..232bdb18 100644 --- a/uv.lock +++ b/uv.lock @@ -475,7 +475,7 @@ wheels = [ [[package]] name = "planet" -version = "0.31.3" +version = "0.32.0" source = { virtual = "." } dependencies = [ { name = "aiofiles" },