From 7261a45cab6c419e64f534ef5b078e0aae3703ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E6=B5=A9?= Date: Wed, 2 Apr 2025 19:09:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E5=9C=B0=E9=9D=A2?= =?UTF-8?q?=E7=AB=99=E5=92=8C=E5=8D=AB=E6=98=9F=E7=8A=B6=E6=80=81=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E4=B8=BA=E4=BD=BF=E7=94=A8=20Set?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../h-cesium-viewer/h-cesium-viewer-class.ts | 95 ++++++++++++++----- .../h-cesium-viewer/h-cesium-viewer.vue | 14 +-- .../h-cesium-viewer/helper/_TOOLTIP_MAP.ts | 2 +- .../h-cesium-viewer/helper/_VIEWER_OPTIONS.ts | 4 +- .../h-cesium-viewer/helper/configureCesium.ts | 18 +++- .../helper/configureMapTile.ts | 7 +- .../helper/configureTimeLine.ts | 11 ++- src/components/h-cesium-viewer/types.ts | 13 ++- .../h-cesium-viewer/useHCesiumViewerCls.ts | 3 +- .../useHCesiumViewerClsGroundStation.ts | 22 +++-- .../useHCesiumViewerClsSatellite.ts | 25 +++-- src/pages/cesium-viewer.page.vue | 34 +++++-- 12 files changed, 180 insertions(+), 68 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 6dd8162..5534486 100644 --- a/src/components/h-cesium-viewer/h-cesium-viewer-class.ts +++ b/src/components/h-cesium-viewer/h-cesium-viewer-class.ts @@ -1,15 +1,27 @@ import * as Cesium from 'cesium'; -import { eciToEcf, gstime, propagate, type SatRec, twoline2satrec } from 'satellite.js'; +import { + eciToEcf, + gstime, + propagate, + type SatRec, + twoline2satrec, +} from 'satellite.js'; -import type { GroundStationOptions, SatelliteOptions } from './h-cesium-viewer-class.types'; // 2小时 +import type { + GroundStationOptions, + SatelliteOptions, +} from './h-cesium-viewer-class.types'; import { VIEWER_OPTIONS_FN } from './helper/_VIEWER_OPTIONS'; import { configureCesium } from './helper/configureCesium'; import { configureTimeLine } from './helper/configureTimeLine'; -const 默认轨道时长秒 = 2 * 60 * 60; +const 默认轨道时长秒 = 2 * 60 * 60; // 2小时 -export { type GroundStationOptions, type SatelliteOptions } from './h-cesium-viewer-class.types'; +export { + type GroundStationOptions, + type SatelliteOptions, +} from './h-cesium-viewer-class.types'; Cesium.Ion.defaultAccessToken = import.meta.env.VITE_CESIUM_ION_TOKEN; // 用了离线地图的情况是不需要的。 @@ -67,12 +79,19 @@ export class HCesiumViewerCls { } // 解构赋值获取站点信息 - const { height = 0, id, latitude, longitude, name, pixelSize = 10 } = options; + const { + height = 0, + id, + latitude, + longitude, + name, + pixelSize = 10, + } = options; const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height); const groundStationEntity = new Cesium.Entity({ // 使用传入的 id 作为实体的唯一标识符 - id: id, + id, label: { font: '14pt sans-serif', outlineWidth: 2, @@ -81,14 +100,14 @@ export class HCesiumViewerCls { text: name, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, }, - name: name, + name, point: { color: Cesium.Color.fromRandom(), // 随机颜色 outlineColor: Cesium.Color.WHITE, outlineWidth: 2, pixelSize, }, - position: position, + position, }); const addedEntity = this.viewer.entities.add(groundStationEntity); @@ -161,9 +180,11 @@ export class HCesiumViewerCls { } = options; // --- 从 tle 字符串解析 name, tle1, tle2 --- - const tleLines = tle.trim().split('\n'); + const tleLines = tle.trim().split('\n') as [string, string, string]; if (tleLines.length < 3) { - console.error(`无效的 TLE 格式 (ID: ${id}): TLE 字符串 "${tle}" 至少需要三行`); + console.error( + `无效的 TLE 格式 (ID: ${id}): TLE 字符串 "${tle}" 至少需要三行`, + ); return null; } const name = tleLines[0].trim(); @@ -185,8 +206,8 @@ export class HCesiumViewerCls { // 创建卫星实体 const satelliteEntity = this.viewer.entities.add({ - id: id, - name: name, + id, + name, label: { text: name, font: '14pt sans-serif', @@ -223,7 +244,11 @@ export class HCesiumViewerCls { const orbitPositions: Cesium.Cartesian3[] = []; // 用于存储完整轨道点 for (let i = 0; i <= orbitDurationSeconds; i += timeStepSeconds) { - const time = Cesium.JulianDate.addSeconds(startTime, i, new Cesium.JulianDate()); + const time = Cesium.JulianDate.addSeconds( + startTime, + i, + new Cesium.JulianDate(), + ); const jsDate = Cesium.JulianDate.toDate(time); try { @@ -238,7 +263,11 @@ export class HCesiumViewerCls { const positionEcf = eciToEcf(positionAndVelocity.position, gmst); // 转换为 Cesium 坐标(单位:米) - const cesiumPosition = new Cesium.Cartesian3(positionEcf.x * 1000, positionEcf.y * 1000, positionEcf.z * 1000); + const cesiumPosition = new Cesium.Cartesian3( + positionEcf.x * 1000, + positionEcf.y * 1000, + positionEcf.z * 1000, + ); // 添加位置样本 positionProperty.addSample(time, cesiumPosition); @@ -254,7 +283,9 @@ export class HCesiumViewerCls { // 设置卫星的位置和方向 satelliteEntity.position = positionProperty; - satelliteEntity.orientation = new Cesium.VelocityOrientationProperty(positionProperty); + satelliteEntity.orientation = new Cesium.VelocityOrientationProperty( + positionProperty, + ); // --- 添加卫星地面覆盖范围 --- // 使用 CallbackProperty 动态计算星下点位置 @@ -266,7 +297,8 @@ export class HCesiumViewerCls { return; // 如果位置无效,则不返回任何内容 } // 转换为地理坐标(包含高度) - const satelliteCartographic = Cesium.Cartographic.fromCartesian(satelliteCartesian); + const satelliteCartographic = + Cesium.Cartographic.fromCartesian(satelliteCartesian); if (!satelliteCartographic) { return; // 如果转换失败,则不返回任何内容 } @@ -277,7 +309,11 @@ export class HCesiumViewerCls { 0, ); // 转换回笛卡尔坐标 - return Cesium.Cartographic.toCartesian(subsatelliteCartographic, Cesium.Ellipsoid.WGS84, result); + return Cesium.Cartographic.toCartesian( + subsatelliteCartographic, + Cesium.Ellipsoid.WGS84, + result, + ); }, false, Cesium.ReferenceFrame.FIXED, @@ -289,7 +325,8 @@ export class HCesiumViewerCls { if (!satelliteCartesian) { return 100_000; // 默认半径 100km } - const satelliteCartographic = Cesium.Cartographic.fromCartesian(satelliteCartesian); + const satelliteCartographic = + Cesium.Cartographic.fromCartesian(satelliteCartesian); if (!satelliteCartographic) { return 100_000; } @@ -336,7 +373,11 @@ export class HCesiumViewerCls { } // 存储实体引用 - this.currentSatelliteEntities.set(id, { entity: satelliteEntity, orbitEntity, coverageEntity }); + this.currentSatelliteEntities.set(id, { + entity: satelliteEntity, + orbitEntity, + coverageEntity, + }); return satelliteEntity; } @@ -361,7 +402,9 @@ export class HCesiumViewerCls { if (satelliteData.entity) { removedMain = this.viewer.entities.remove(satelliteData.entity); if (!removedMain) { - console.warn(`尝试从 Cesium 移除卫星主体 ID 为 "${entityId}" 的实体失败。`); + console.warn( + `尝试从 Cesium 移除卫星主体 ID 为 "${entityId}" 的实体失败。`, + ); } } @@ -369,15 +412,21 @@ export class HCesiumViewerCls { if (satelliteData.orbitEntity) { removedOrbit = this.viewer.entities.remove(satelliteData.orbitEntity); if (!removedOrbit) { - console.warn(`尝试从 Cesium 移除卫星轨道 ID 为 "${satelliteData.orbitEntity.id}" 的实体失败。`); + console.warn( + `尝试从 Cesium 移除卫星轨道 ID 为 "${satelliteData.orbitEntity.id}" 的实体失败。`, + ); } } // 移除覆盖范围 if (satelliteData.coverageEntity) { - removedCoverage = this.viewer.entities.remove(satelliteData.coverageEntity); + removedCoverage = this.viewer.entities.remove( + satelliteData.coverageEntity, + ); if (!removedCoverage) { - console.warn(`尝试从 Cesium 移除卫星覆盖范围 ID 为 "${satelliteData.coverageEntity.id}" 的实体失败。`); + console.warn( + `尝试从 Cesium 移除卫星覆盖范围 ID 为 "${satelliteData.coverageEntity.id}" 的实体失败。`, + ); } } diff --git a/src/components/h-cesium-viewer/h-cesium-viewer.vue b/src/components/h-cesium-viewer/h-cesium-viewer.vue index 3b97fd1..17dd6db 100644 --- a/src/components/h-cesium-viewer/h-cesium-viewer.vue +++ b/src/components/h-cesium-viewer/h-cesium-viewer.vue @@ -1,19 +1,19 @@ diff --git a/src/components/h-cesium-viewer/helper/_TOOLTIP_MAP.ts b/src/components/h-cesium-viewer/helper/_TOOLTIP_MAP.ts index 6ef7487..d10f59b 100644 --- a/src/components/h-cesium-viewer/helper/_TOOLTIP_MAP.ts +++ b/src/components/h-cesium-viewer/helper/_TOOLTIP_MAP.ts @@ -16,5 +16,5 @@ export const TOOLTIP_MAP = { ARG_OF_PERICENTER_近地点幅角: "8位数字,如'181.9338',表示近地点相对升交点的角度(度),范围0°-360°", MEAN_ANOMALY_平近点角: "8位数字,如'171.6150',表示历元时的平近点角(度),范围0°-360°", MEAN_MOTION_平均运动: "11位数字,如'2.21786616',表示卫星每天绕地球的圈数(圈/天)", - REV_AT_EPOCH_历元时的圈数: "5位数字,如'13',表示卫星在历元时完成的轨道圈数,最后以为是校验和,共6位", + REV_AT_EPOCH_历元时的圈数: "5位数字,如'13',表示卫星在历元时完成的轨道圈数", }; diff --git a/src/components/h-cesium-viewer/helper/_VIEWER_OPTIONS.ts b/src/components/h-cesium-viewer/helper/_VIEWER_OPTIONS.ts index d6939b2..4427653 100644 --- a/src/components/h-cesium-viewer/helper/_VIEWER_OPTIONS.ts +++ b/src/components/h-cesium-viewer/helper/_VIEWER_OPTIONS.ts @@ -6,7 +6,9 @@ export const VIEWER_OPTIONS_FN = (): Viewer.ConstructorOptions => { return { animation: true, // .cesium-viewer-animationContainer https://cesium.com/learn/ion-sdk/ref-doc/Animation.html baseLayer: Cesium.ImageryLayer.fromProviderAsync( - Cesium.TileMapServiceImageryProvider.fromUrl(Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII')), + Cesium.TileMapServiceImageryProvider.fromUrl( + Cesium.buildModuleUrl('Assets/Textures/NaturalEarthII'), + ), ), baseLayerPicker: false, fullscreenButton: !true, // 全屏按钮 diff --git a/src/components/h-cesium-viewer/helper/configureCesium.ts b/src/components/h-cesium-viewer/helper/configureCesium.ts index 6027b81..8b05df2 100644 --- a/src/components/h-cesium-viewer/helper/configureCesium.ts +++ b/src/components/h-cesium-viewer/helper/configureCesium.ts @@ -20,18 +20,30 @@ export function configureCesium() { // Animation 的时间日期格式化 Cesium.AnimationViewModel.defaultDateFormatter = function (date) { - const dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate()); + const dataZone8 = Cesium.JulianDate.addMinutes( + date, + minutes, + new Cesium.JulianDate(), + ); return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 10); }; Cesium.AnimationViewModel.defaultTimeFormatter = function (time) { - const dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate()); + const dataZone8 = Cesium.JulianDate.addMinutes( + time, + minutes, + new Cesium.JulianDate(), + ); return Cesium.JulianDate.toIso8601(dataZone8).slice(11, 19); }; // Timeline 的时间日期格式化 // @ts-expect-error node_modules/@cesium/widgets/Source/Timeline/Timeline.js Cesium.Timeline.prototype.makeLabel = function (time) { - const dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate()); + const dataZone8 = Cesium.JulianDate.addMinutes( + time, + minutes, + new Cesium.JulianDate(), + ); return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 19); }; } diff --git a/src/components/h-cesium-viewer/helper/configureMapTile.ts b/src/components/h-cesium-viewer/helper/configureMapTile.ts index 0b6c5cb..6cbcac9 100644 --- a/src/components/h-cesium-viewer/helper/configureMapTile.ts +++ b/src/components/h-cesium-viewer/helper/configureMapTile.ts @@ -19,8 +19,11 @@ export function configureMapTile(viewer: Cesium.Viewer) { tooltip: '高德地图', }); // 设置高德地图为默认图层 - viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift(customLayerViewModel); - const selectedViewModel = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[0]; + viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift( + customLayerViewModel, + ); + const selectedViewModel = + viewer.baseLayerPicker.viewModel.imageryProviderViewModels[0]; if (!selectedViewModel) { console.error('未找到默认底图'); return; diff --git a/src/components/h-cesium-viewer/helper/configureTimeLine.ts b/src/components/h-cesium-viewer/helper/configureTimeLine.ts index b989e32..e2b66ca 100644 --- a/src/components/h-cesium-viewer/helper/configureTimeLine.ts +++ b/src/components/h-cesium-viewer/helper/configureTimeLine.ts @@ -2,9 +2,16 @@ import * as Cesium from 'cesium'; const 默认场景的时间跨度 = 2 * 60 * 60; // 2小时 -export function configureTimeLine(viewer: Cesium.Viewer, totalSeconds = 默认场景的时间跨度) { +export function configureTimeLine( + viewer: Cesium.Viewer, + totalSeconds = 默认场景的时间跨度, +) { const start = Cesium.JulianDate.fromIso8601(new Date().toISOString()); - const stop = Cesium.JulianDate.addSeconds(start, totalSeconds, new Cesium.JulianDate()); + const stop = Cesium.JulianDate.addSeconds( + start, + totalSeconds, + new Cesium.JulianDate(), + ); // 设置时钟范围 viewer.clock.startTime = start.clone(); diff --git a/src/components/h-cesium-viewer/types.ts b/src/components/h-cesium-viewer/types.ts index 13a90ad..4b34db8 100644 --- a/src/components/h-cesium-viewer/types.ts +++ b/src/components/h-cesium-viewer/types.ts @@ -1,4 +1,7 @@ -import type { GroundStationOptions, SatelliteOptions } from './h-cesium-viewer-class'; +import type { + GroundStationOptions, + SatelliteOptions, +} from './h-cesium-viewer-class'; /** * 地面站状态接口 @@ -7,8 +10,8 @@ import type { GroundStationOptions, SatelliteOptions } from './h-cesium-viewer-c export interface GroundStationState { /** 地面站配置数组 */ groundStations: GroundStationOptions[]; - /** 选中的地面站 ID 数组 */ - selectedIds: string[]; + /** 选中的地面站 ID 集合 */ + selectedIds: Set; } /** @@ -18,6 +21,6 @@ export interface GroundStationState { export interface SatelliteState { /** 卫星配置数组 */ satellites: SatelliteOptions[]; - /** 选中的卫星 ID 数组 */ - selectedIds: string[]; + /** 选中的卫星 ID 集合 */ + selectedIds: Set; } diff --git a/src/components/h-cesium-viewer/useHCesiumViewerCls.ts b/src/components/h-cesium-viewer/useHCesiumViewerCls.ts index 16a4e90..0d6bbe1 100644 --- a/src/components/h-cesium-viewer/useHCesiumViewerCls.ts +++ b/src/components/h-cesium-viewer/useHCesiumViewerCls.ts @@ -1,5 +1,6 @@ // src/utils/useHCesiumViewerCls.ts -import { HCesiumViewerCls } from '@/components/h-cesium-viewer/h-cesium-viewer-class'; + +import { HCesiumViewerCls } from './h-cesium-viewer-class'; /** * 管理 HCesiumViewerCls 实例的生命周期。 diff --git a/src/components/h-cesium-viewer/useHCesiumViewerClsGroundStation.ts b/src/components/h-cesium-viewer/useHCesiumViewerClsGroundStation.ts index e9a2468..8d89a3b 100644 --- a/src/components/h-cesium-viewer/useHCesiumViewerClsGroundStation.ts +++ b/src/components/h-cesium-viewer/useHCesiumViewerClsGroundStation.ts @@ -1,17 +1,22 @@ // src/utils/useHCesiumViewerClsGroundStation.ts -import type { GroundStationOptions, HCesiumViewerCls } from '@/components/h-cesium-viewer/h-cesium-viewer-class'; + import type { MaybeRefOrGetter } from 'vue'; +import type { + GroundStationOptions, + HCesiumViewerCls, +} from './h-cesium-viewer-class'; + /** * 管理 Cesium Viewer 中的地面站实体,根据选中的 ID 列表进行同步。 * @param hCesiumViewerInst - HCesiumViewerCls 实例或其 getter。 * @param groundStationList - 包含所有可用地面站选项的数组或 getter。 - * @param selectedStationIds - 包含当前选中地面站 ID 的数组或 getter。 + * @param selectedStationIds - 包含当前选中地面站 ID 的 Set 或 getter。 */ export function useHCesiumViewerClsGroundStation( hCesiumViewerInst: MaybeRefOrGetter, groundStationList: MaybeRefOrGetter | undefined>, - selectedStationIds: MaybeRefOrGetter, + selectedStationIds: MaybeRefOrGetter | undefined>, ) { // 创建一个从 ID 到站点选项的映射,方便查找 const stationMap = computed(() => { @@ -31,9 +36,10 @@ export function useHCesiumViewerClsGroundStation( return; } - const selectedIds = toValue(selectedStationIds) ?? []; - const selectedIdsSet = new Set(selectedIds); // 需要显示的站点 ID - const currentEntityIds = new Set(viewerInstance.currentStationEntities.keys()); // 当前已显示的站点 ID + const selectedIdsSet = toValue(selectedStationIds) ?? new Set(); // 直接获取 Set,如果为 undefined 则创建空 Set + const currentEntityIds = new Set( + viewerInstance.currentStationEntities.keys(), + ); // 当前已显示的站点 ID // 1. 移除不再选中的站点 for (const entityId of currentEntityIds) { @@ -52,7 +58,9 @@ export function useHCesiumViewerClsGroundStation( viewerInstance.addGroundStation(stationToAdd); } else { // 如果在 groundStationList 中找不到对应的站点信息,发出警告 - consola.warn(`无法找到 ID 为 "${selectedId}" 的站点信息,无法添加到地图。`); + console.warn( + `无法找到 ID 为 "${selectedId}" 的站点信息,无法添加到地图。`, + ); } } } diff --git a/src/components/h-cesium-viewer/useHCesiumViewerClsSatellite.ts b/src/components/h-cesium-viewer/useHCesiumViewerClsSatellite.ts index 7dc943e..f21bb21 100644 --- a/src/components/h-cesium-viewer/useHCesiumViewerClsSatellite.ts +++ b/src/components/h-cesium-viewer/useHCesiumViewerClsSatellite.ts @@ -1,17 +1,22 @@ // src/components/h-cesium-viewer/useHCesiumViewerClsSatellite.ts -import type { HCesiumViewerCls, SatelliteOptions } from '@/components/h-cesium-viewer/h-cesium-viewer-class'; + import type { MaybeRefOrGetter } from 'vue'; +import type { + HCesiumViewerCls, + SatelliteOptions, +} from './h-cesium-viewer-class'; + /** * 管理 Cesium Viewer 中的卫星实体,根据选中的 ID 列表进行同步。 * @param hCesiumViewerInst - HCesiumViewerCls 实例或其 getter。 * @param satelliteList - 包含所有可用卫星选项的数组或 getter。 - * @param selectedSatelliteIds - 包含当前选中卫星 ID 的数组或 getter。 + * @param selectedSatelliteIds - 包含当前选中卫星 ID 的 Set 或 getter。 */ export function useHCesiumViewerClsSatellite( hCesiumViewerInst: MaybeRefOrGetter, satelliteList: MaybeRefOrGetter | undefined>, - selectedSatelliteIds: MaybeRefOrGetter, + selectedSatelliteIds: MaybeRefOrGetter | undefined>, ) { // 创建一个从 ID 到卫星选项的映射,方便查找 const satelliteMap = computed(() => { @@ -31,9 +36,10 @@ export function useHCesiumViewerClsSatellite( return; } - const selectedIds = toValue(selectedSatelliteIds) ?? []; - const selectedIdsSet = new Set(selectedIds); // 需要显示的卫星 ID - const currentEntityIds = new Set(viewerInstance.currentSatelliteEntities.keys()); // 当前已显示的卫星 ID + const selectedIdsSet = toValue(selectedSatelliteIds) ?? new Set(); // 直接获取 Set,如果为 undefined 则创建空 Set + const currentEntityIds = new Set( + viewerInstance.currentSatelliteEntities.keys(), + ); // 当前已显示的卫星 ID // 1. 移除不再选中的卫星 for (const entityId of currentEntityIds) { @@ -49,10 +55,15 @@ export function useHCesiumViewerClsSatellite( // 如果选中的 ID 对应的实体当前未显示,则添加 const satelliteToAdd = satelliteMap.value.get(selectedId); // 从映射中查找卫星信息 if (satelliteToAdd) { + console.debug( + `添加卫星 "${satelliteToAdd.id}" 到地图,TLE: ${satelliteToAdd.tle}`, + ); viewerInstance.addSatellite(satelliteToAdd); } else { // 如果在 satelliteList 中找不到对应的卫星信息,发出警告 - consola.warn(`无法找到 ID 为 "${selectedId}" 的卫星信息,无法添加到地图。`); + console.warn( + `无法找到 ID 为 "${selectedId}" 的卫星信息,无法添加到地图。`, + ); } } } diff --git a/src/pages/cesium-viewer.page.vue b/src/pages/cesium-viewer.page.vue index 86a68ac..007d030 100644 --- a/src/pages/cesium-viewer.page.vue +++ b/src/pages/cesium-viewer.page.vue @@ -9,7 +9,7 @@ import type { GroundStationState, SatelliteState } from '@/components/h-cesium-v // 地面站和选中状态 const groundStationState = reactive({ groundStations: [], - selectedIds: [], + selectedIds: new Set(), }); groundStationState.groundStations = [ { height: 50, id: 'gs-bj', latitude: 39.9042, longitude: 116.4074, name: '北京站' }, @@ -20,7 +20,7 @@ groundStationState.groundStations = [ // >>>>>>>>> 卫星状态管理 >>>>>>>>> const satelliteState = reactive({ satellites: [], - selectedIds: [], + selectedIds: new Set(), }); // 初始化卫星列表 @@ -51,6 +51,14 @@ const satelliteCheckboxOptions = computed(() => })), ); +// 为卫星 a-checkbox-group 创建计算属性,处理 Set 和 Array 的转换 +const selectedSatelliteIdsArray = computed({ + get: () => [...satelliteState.selectedIds], // 从 Set 转换为 Array + set: (val: string[]) => { + satelliteState.selectedIds = new Set(val); // 从 Array 转换回 Set + }, +}); + // <<<<<<<<< 卫星状态管理 <<<<<<<<< // 计算 Checkbox Group 的 options @@ -71,7 +79,7 @@ const addRandomStation = () => { longitude: randomLon, name: `随机站 ${randomId.slice(-4)}`, }); - groundStationState.selectedIds.push(randomId); // 同时将新站点 ID 添加到选中项 + groundStationState.selectedIds.add(randomId); // 同时将新站点 ID 添加到选中项 consola.info('添加随机站点:', groundStationState.groundStations.at(-1)); // 使用 .at() 访问最后一个元素 }; @@ -82,7 +90,7 @@ const removeLastStation = () => { if (removedStation) { consola.info('移除站点:', removedStation); // 同时从选中项中移除 - groundStationState.selectedIds = groundStationState.selectedIds.filter((id) => id !== removedStation.id); + groundStationState.selectedIds.delete(removedStation.id); } } }; @@ -90,9 +98,17 @@ const removeLastStation = () => { // 清空所有选中项 const clearAllStations = () => { groundStationState.groundStations = []; - groundStationState.selectedIds = []; // 清空选中项 + groundStationState.selectedIds.clear(); // 清空选中项 consola.info('清空所有站点'); }; + +// 为 a-checkbox-group 创建计算属性,处理 Set 和 Array 的转换 +const selectedStationIdsArray = computed({ + get: () => [...groundStationState.selectedIds], // 从 Set 转换为 Array + set: (val: string[]) => { + groundStationState.selectedIds = new Set(val); // 从 Array 转换回 Set + }, +});