From 2c6a4287d20d325f7beb9f7accdd77c274772c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E6=B5=A9?= Date: Mon, 31 Mar 2025 20:43:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=95=B4=E7=90=86=20HCesiumViewerCls?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../h-cesium-viewer/h-cesium-viewer-class.ts | 12 ++---- src/components/h-cesium-viewer/index.vue | 43 +++++-------------- src/pages/cesium-viewer.page.vue | 3 +- 3 files changed, 15 insertions(+), 43 deletions(-) diff --git a/src/components/h-cesium-viewer/h-cesium-viewer-class.ts b/src/components/h-cesium-viewer/h-cesium-viewer-class.ts index 657dcb6..b0eed2e 100644 --- a/src/components/h-cesium-viewer/h-cesium-viewer-class.ts +++ b/src/components/h-cesium-viewer/h-cesium-viewer-class.ts @@ -3,7 +3,6 @@ import * as Cesium from 'cesium'; import { VIEWER_OPTIONS_FN } from './VIEWER_OPTIONS'; export interface GroundStationOptions { - // 调整顺序以符合 ESLint 规则 color?: Cesium.Color; // 点的可选颜色 height?: number; // 可选高度,默认为0 id: string; // 站点的唯一标识符 @@ -27,19 +26,16 @@ export class HCesiumViewerCls { /** * 向视图中添加地面站实体 * @param options - 地面站的选项参数 - * @returns 添加的实体对象,如果视图未初始化则返回 undefined + * @returns 添加的实体对象。 */ - addGroundStation(options: GroundStationOptions): Cesium.Entity | undefined { + addGroundStation(options: GroundStationOptions): Cesium.Entity { if (!this.viewer) { - console.error('视图未初始化。请先调用 initCesiumViewer 方法。'); - return; + throw new Error('视图未初始化。请先调用 initCesiumViewer 方法。'); } const { - // 调整解构赋值顺序 - // color = Cesium.Color.RED, // 默认颜色 - 已移除,将使用随机颜色 height = 0, // 如果未提供,默认高度为0 - id, // 获取 id + id, latitude, longitude, name, diff --git a/src/components/h-cesium-viewer/index.vue b/src/components/h-cesium-viewer/index.vue index df3f7b1..79dc0f1 100644 --- a/src/components/h-cesium-viewer/index.vue +++ b/src/components/h-cesium-viewer/index.vue @@ -4,54 +4,36 @@ import * as Cesium from 'cesium'; // 引入 Cesium 类型 import { type GroundStationOptions, HCesiumViewerCls } from './h-cesium-viewer-class'; -// 根据项目规则,vue, pinia, vue-router/auto, @vueuse/core, vue-i18n, consola/browser, src/stores, src/utils -// 的 API 是自动导入的,因此不需要显式 import { watchEffect, ref, onMounted, onBeforeUnmount, defineProps } from 'vue'; -// defineProps, ref, watchEffect, onMounted, onBeforeUnmount, consola 应该可以直接使用 - const props = defineProps<{ groundStationList?: Array; }>(); -const hCesiumViewer = new HCesiumViewerCls(); -// Object.assign(globalThis, { hCesiumViewer }); // 考虑移除或替换为更标准的 Vue 依赖注入或 provide/inject +const hCesiumViewerInst = new HCesiumViewerCls(); +Object.assign(globalThis, { hCesiumViewer: hCesiumViewerInst }); // 使用 Map 存储当前显示的站点实体,键为站点唯一标识符,值为 Cesium.Entity // 使用 ref 包裹 Map 以便在 watchEffect 中正确跟踪其变化 const currentStationEntities = ref>(new Map()); -// 移除 getStationKey 函数,将使用 station.id 作为唯一标识符 - onMounted(() => { - hCesiumViewer.initCesiumViewer('cesiumContainer'); + hCesiumViewerInst.initCesiumViewer('cesiumContainer'); + Object.assign(globalThis, { hCesiumViewer: hCesiumViewerInst }); // 使用 watchEffect 监听 props.groundStationList 的变化并同步 Cesium 实体 watchEffect(() => { - // 确保 viewer 已经初始化 - if (!hCesiumViewer.viewer) { - consola.warn('Cesium Viewer 尚未初始化,无法更新地面站。'); - // 清理可能存在的旧实体引用(以防万一 viewer 初始化延迟) - // 使用 for...of 替换 forEach - for (const entity of currentStationEntities.value.values()) { - hCesiumViewer.removeGroundStation(entity); - } - currentStationEntities.value.clear(); - return; - } - const newStations = props.groundStationList ?? []; // 处理 props 可能为 undefined 的情况,默认为空数组 const newStationKeys = new Set(newStations.map((station) => station.id)); // 使用 station.id 作为键 const currentKeys = new Set(currentStationEntities.value.keys()); // 当前 Cesium 中所有站点的键集合 // 1. 移除不再存在于新列表中的站点 // 遍历当前 Cesium 中的站点键 - // 使用 for...of 替换 forEach for (const key of currentKeys) { // 如果当前键不在新列表的键集合中,则说明该站点需要被移除 if (!newStationKeys.has(key)) { const entityToRemove = currentStationEntities.value.get(key); if (entityToRemove) { // consola.debug(`移除地面站: ${key}`); // 调试日志:输出移除信息 - hCesiumViewer.removeGroundStation(entityToRemove); // 从 Cesium 中移除实体 + hCesiumViewerInst.removeGroundStation(entityToRemove); // 从 Cesium 中移除实体 currentStationEntities.value.delete(key); // 从内部 Map 中移除引用 } } @@ -59,13 +41,12 @@ onMounted(() => { // 2. 添加新列表中的、当前尚未显示的站点 // 遍历新列表中的站点 - // 使用 for...of 替换 forEach for (const station of newStations) { const key = station.id; // 使用 station.id 作为键 // 如果新站点的键不在当前 Cesium 的键集合中,则说明该站点是新增的 if (!currentKeys.has(key)) { // consola.debug(`添加地面站: ${key}`); // 调试日志:输出添加信息 - const newEntity = hCesiumViewer.addGroundStation(station); // 向 Cesium 添加实体 + const newEntity = hCesiumViewerInst.addGroundStation(station); // 向 Cesium 添加实体 if (newEntity) { currentStationEntities.value.set(key, newEntity); // 将新实体的引用添加到内部 Map } else { @@ -73,28 +54,24 @@ onMounted(() => { consola.error(`添加地面站失败: ${key}`); } } - // 注意:此逻辑仅处理添加和移除。如果需要更新现有站点的属性(如颜色、大小等), - // 则需要在此处添加额外的比较和更新逻辑。 - // 例如:找到已存在的实体,比较 props 中的属性与实体当前属性,如有不同则调用相应方法更新实体。 } }); }); onBeforeUnmount(() => { // 组件卸载前,清理所有由该组件添加的地面站实体 - if (hCesiumViewer.viewer) { + if (hCesiumViewerInst.viewer) { // consola.debug('组件卸载,清理所有地面站...'); // 调试日志 - // 使用 for...of 替换 forEach for (const entity of currentStationEntities.value.values()) { // 确保 viewer 仍然存在,避免在销毁过程中出错 - if (hCesiumViewer.viewer && hCesiumViewer.viewer.entities) { - hCesiumViewer.removeGroundStation(entity); + if (hCesiumViewerInst.viewer && hCesiumViewerInst.viewer.entities) { + hCesiumViewerInst.removeGroundStation(entity); } } } currentStationEntities.value.clear(); // 清空内部 Map // 销毁 Cesium Viewer 实例,释放资源 - hCesiumViewer.destroy(); + hCesiumViewerInst.destroy(); // consola.debug('Cesium Viewer 已销毁。'); // 调试日志 }); diff --git a/src/pages/cesium-viewer.page.vue b/src/pages/cesium-viewer.page.vue index d6098ac..112760a 100644 --- a/src/pages/cesium-viewer.page.vue +++ b/src/pages/cesium-viewer.page.vue @@ -15,12 +15,11 @@ const groundStations = ref([ // 添加一个随机站点 const addRandomStation = () => { - const randomId = `gs-random-${Math.random().toString(36).slice(7)}`; // 使用 slice 替换 substring + const randomId = `gs-random-${Math.random().toString(36).slice(7)}`; const randomLon = Math.random() * 360 - 180; // -180 to 180 const randomLat = Math.random() * 180 - 90; // -90 to 90 const randomHeight = Math.random() * 1000; // 0 to 1000 meters groundStations.value.push({ - // 调整属性顺序 height: randomHeight, id: randomId, latitude: randomLat,