fix: make earth satellite and cable toggles fully unload

This commit is contained in:
linkong
2026-03-27 17:11:07 +08:00
parent 7a3ca6e1b3
commit 755729ee5e
5 changed files with 242 additions and 44 deletions

View File

@@ -38,6 +38,8 @@ import {
resetLandingPointVisualState,
getShowCables,
clearCableData,
getLandingPoints,
toggleCables,
} from "./cables.js";
import {
createSatellites,
@@ -126,6 +128,10 @@ let initialized = false;
let destroyed = false;
let isDataLoading = false;
let currentLoadToken = 0;
let cablesEnabled = true;
let satellitesEnabled = true;
let cableToggleToken = 0;
let satelliteToggleToken = 0;
const clock = new THREE.Clock();
const interactionRaycaster = new THREE.Raycaster();
@@ -344,6 +350,124 @@ function buildLoadErrorMessage(errors) {
.join("");
}
function updateSatelliteToggleUi(enabled, satelliteCount = getSatelliteCount()) {
const satBtn = document.getElementById("toggle-satellites");
if (satBtn) {
satBtn.classList.toggle("active", enabled);
const tooltip = satBtn.querySelector(".tooltip");
if (tooltip) tooltip.textContent = enabled ? "隐藏卫星" : "显示卫星";
}
const satelliteCountEl = document.getElementById("satellite-count");
if (satelliteCountEl) {
satelliteCountEl.textContent = `${enabled ? satelliteCount : 0}`;
}
}
function updateCableToggleUi(enabled) {
const cableBtn = document.getElementById("toggle-cables");
if (cableBtn) {
cableBtn.classList.toggle("active", enabled);
const tooltip = cableBtn.querySelector(".tooltip");
if (tooltip) tooltip.textContent = enabled ? "隐藏线缆" : "显示线缆";
}
const cableCountEl = document.getElementById("cable-count");
if (cableCountEl) {
cableCountEl.textContent = `${enabled ? getCableLines().length : 0}`;
}
const landingPointCountEl = document.getElementById("landing-point-count");
if (landingPointCountEl) {
landingPointCountEl.textContent = `${enabled ? getLandingPoints().length : 0}`;
}
const statusEl = document.getElementById("cable-status-summary");
if (statusEl && !enabled) {
statusEl.textContent = "0/0 运行中";
}
}
async function ensureCablesEnabled() {
if (!scene || !camera || !renderer || destroyed) {
return 0;
}
const earth = getEarth();
if (!earth) return 0;
cablesEnabled = true;
const requestToken = ++cableToggleToken;
clearCableData(earth);
const [cableCount] = await Promise.all([
loadGeoJSONFromPath(scene, earth),
loadLandingPoints(scene, earth),
]);
if (requestToken !== cableToggleToken || !cablesEnabled || destroyed) {
clearCableData(earth);
return 0;
}
toggleCables(true);
updateCableToggleUi(true);
setLegendItems("cables", getCableLegendItems());
refreshLegend();
return cableCount;
}
function disableCables() {
cablesEnabled = false;
cableToggleToken += 1;
clearCableData(getEarth());
updateCableToggleUi(false);
setLegendItems("cables", getCableLegendItems());
refreshLegend();
}
async function ensureSatellitesEnabled() {
if (!scene || !camera || !renderer || destroyed) return 0;
const earth = getEarth();
if (!earth) return 0;
satellitesEnabled = true;
const requestToken = ++satelliteToggleToken;
if (!getSatellitePoints()) {
createSatellites(scene, earth);
}
clearSatelliteData();
const satelliteCount = await loadSatellites();
if (
requestToken !== satelliteToggleToken ||
!satellitesEnabled ||
destroyed
) {
resetSatelliteState();
return 0;
}
updateSatellitePositions(POSITION_UPDATE_FORCE_DELTA, true);
toggleSatellites(true);
updateSatelliteToggleUi(true, satelliteCount);
setLegendItems("satellites", getSatelliteLegendItems());
refreshLegend();
return satelliteCount;
}
function disableSatellites() {
satellitesEnabled = false;
satelliteToggleToken += 1;
resetSatelliteState();
updateSatelliteToggleUi(false, 0);
setLegendItems("satellites", getSatelliteLegendItems());
refreshLegend();
}
function updateStatsSummary() {
updateEarthStats({
cableCount: getCableLines().length,
@@ -479,25 +603,8 @@ async function loadData(showWhiteSphere = false) {
}
const results = await Promise.allSettled([
loadGeoJSONFromPath(scene, earth),
loadLandingPoints(scene, earth),
(async () => {
clearSatelliteData();
const satelliteCount = await loadSatellites();
const satelliteCountEl = document.getElementById("satellite-count");
if (satelliteCountEl) {
satelliteCountEl.textContent = `${satelliteCount}`;
}
updateSatellitePositions(POSITION_UPDATE_FORCE_DELTA, true);
toggleSatellites(true);
const satBtn = document.getElementById("toggle-satellites");
if (satBtn) {
satBtn.classList.add("active");
const tooltip = satBtn.querySelector(".tooltip");
if (tooltip) tooltip.textContent = "隐藏卫星";
}
return satelliteCount;
})(),
cablesEnabled ? ensureCablesEnabled() : Promise.resolve(0),
satellitesEnabled ? ensureSatellitesEnabled() : Promise.resolve(0),
(async () => {
clearBGPData(earth);
const bgpResult = await loadBGPAnomalies(scene, earth);
@@ -526,13 +633,10 @@ async function loadData(showWhiteSphere = false) {
errors.push({ label: "电缆", reason: results[0].reason });
}
if (results[1].status === "rejected") {
errors.push({ label: "登陆点", reason: results[1].reason });
errors.push({ label: "卫星", reason: results[1].reason });
}
if (results[2].status === "rejected") {
errors.push({ label: "卫星", reason: results[2].reason });
}
if (results[3].status === "rejected") {
errors.push({ label: "BGP异常", reason: results[3].reason });
errors.push({ label: "BGP异常", reason: results[2].reason });
}
if (errors.length > 0) {
@@ -545,6 +649,8 @@ async function loadData(showWhiteSphere = false) {
}
updateStatsSummary();
updateCableToggleUi(cablesEnabled);
updateSatelliteToggleUi(satellitesEnabled);
setLegendItems("cables", getCableLegendItems());
setLegendItems("satellites", getSatelliteLegendItems());
setLegendItems("bgp", getBGPLegendItems());
@@ -565,6 +671,75 @@ export async function reloadData() {
await loadData(true);
}
export async function setCablesEnabled(enabled) {
if (enabled === cablesEnabled) {
updateCableToggleUi(enabled);
return getCableLines().length;
}
if (!enabled) {
clearLockedObject();
hideInfoCard();
disableCables();
showStatusMessage("线缆已隐藏", "info");
return 0;
}
setLoadingMessage("正在加载线缆数据...", "重建海缆与登陆点对象");
setLoading(true);
hideError();
try {
const cableCount = await ensureCablesEnabled();
showStatusMessage("线缆已显示", "info");
return cableCount;
} catch (error) {
cablesEnabled = false;
clearCableData(getEarth());
updateCableToggleUi(false);
const message = `线缆加载失败: ${error?.message || String(error)}`;
showError(message);
showStatusMessage(message, "error");
throw error;
} finally {
setLoading(false);
}
}
export async function setSatellitesEnabled(enabled) {
if (enabled === satellitesEnabled) {
updateSatelliteToggleUi(enabled);
return getSatelliteCount();
}
if (!enabled) {
clearLockedObject();
hideInfoCard();
disableSatellites();
return 0;
}
setLoadingMessage("正在加载卫星数据...", "重建卫星点位与轨迹缓存");
setLoading(true);
hideError();
try {
const satelliteCount = await ensureSatellitesEnabled();
showStatusMessage("卫星已显示", "info");
return satelliteCount;
} catch (error) {
satellitesEnabled = false;
resetSatelliteState();
updateSatelliteToggleUi(false, 0);
const message = `卫星加载失败: ${error?.message || String(error)}`;
showError(message);
showStatusMessage(message, "error");
throw error;
} finally {
setLoading(false);
}
}
function setupEventListeners() {
const handleResize = () => onWindowResize();
const handleMouseMove = (event) => onMouseMove(event);