From 5f74876ca8bba9f22158d45857dd4596353b158e Mon Sep 17 00:00:00 2001 From: ctw <1051735452@qq.com> Date: Mon, 9 Feb 2026 16:55:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E4=BD=93=E9=98=B2=E6=8A=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/cesiumMap/index.vue | 127 +++++++++++++++++++++++++++------ 1 file changed, 107 insertions(+), 20 deletions(-) diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue index aa317d2..a2de587 100644 --- a/ruoyi-ui/src/views/cesiumMap/index.vue +++ b/ruoyi-ui/src/views/cesiumMap/index.vue @@ -216,7 +216,11 @@ export default { PLATFORM_ROTATE_HANDLE_OFFSET_DEG: 0.0009, PLATFORM_DRAG_THRESHOLD_PX: 10, DESIRED_BOX_HALF_PX: 58, - DESIRED_ROTATE_OFFSET_PX: 50 + DESIRED_ROTATE_OFFSET_PX: 50, + // 实体点击防抖,避免双击误触导致相机高度剧烈变化 + entityClickDebounceTimer: null, + lastEntityClickTime: 0, + cameraStateBeforeEntityClick: null } }, components: { @@ -1704,6 +1708,15 @@ export default { } this.loadOfflineMap() this.setup2DConstraints() + // 移除 Cesium 自带的双击缩放,使双击实体/空白均无任何效果 + try { + const handler = this.viewer.screenSpaceEventHandler || (this.viewer.cesiumWidget && this.viewer.cesiumWidget.screenSpaceEventHandler) + if (handler) { + handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK) + } + } catch (e) { + // 部分版本可能无此 action,忽略 + } // 初始视野:中国中心(仅中国瓦片时无需世界瓦片,国外区域会无瓦片显示为空白) this.viewer.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(116.3974, 39.9093, 12000000), @@ -1721,7 +1734,7 @@ export default { this.initMouseCoordinates() console.log('Cesium离线二维地图已加载') - // 1. 定义全局拾取处理器 + // 1. 定义全局拾取处理器(含防抖,避免双击误触导致相机高度剧烈变化) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); this.handler.setInputAction((click) => { // 隐藏右键菜单 @@ -1735,31 +1748,69 @@ export default { const idStr = (entity && entity.id) ? entity.id : ''; if (idStr && (idStr.endsWith('-rotate-handle') || idStr.indexOf('-scale-') !== -1)) return; const platformIconData = this.allEntities.find(e => e.type === 'platformIcon' && e.entity === entity); - if (platformIconData) return; - - // --- 修正后的安全日志 --- - console.log(">>> [点击检测] 实体ID:", entity.id); // 获取属性时必须传入当前仿真时间 const now = Cesium.JulianDate.now(); const props = entity.properties ? entity.properties.getValue(now) : null; - - console.log(">>> [点击检测] 业务数据详情:", props); - - if (props && props.isMissionWaypoint) { - const dbId = props.dbId; - const routeId = props.routeId; - console.log(`>>> [地图触发] 点击了点 ${dbId}, 属于航线 ${routeId}`); - // 关键:把航线 ID 也传给父组件 - this.$emit('open-waypoint-dialog', dbId, routeId); - } else if (props && props.isMissionRouteLine) { - const routeId = props.routeId; - console.log(`>>> [地图触发] 点击了航线 ${routeId}`); - // 触发航线编辑弹窗事件 - this.$emit('open-route-dialog', routeId); + const isWaypoint = props && props.isMissionWaypoint; + const isRouteLine = props && props.isMissionRouteLine; + const isPlatformIcon = !!platformIconData; + // 仅对航线、航点、平台图标做防抖与相机保存(其它实体不处理) + if (!isWaypoint && !isRouteLine && !isPlatformIcon) return; + + const nowMs = Date.now(); + // 防抖:若与上次点击间隔过短,视为双击,仅清除定时器不触发弹窗 + if (nowMs - this.lastEntityClickTime < 300) { + if (this.entityClickDebounceTimer) { + clearTimeout(this.entityClickDebounceTimer); + this.entityClickDebounceTimer = null; + } + this.lastEntityClickTime = 0; + return; + } + this.lastEntityClickTime = nowMs; + this.saveCameraStateBeforeEntityClick(); + + if (this.entityClickDebounceTimer) clearTimeout(this.entityClickDebounceTimer); + const dbId = isWaypoint ? props.dbId : null; + const routeId = isWaypoint ? props.routeId : (isRouteLine ? props.routeId : null); + if (isWaypoint || isRouteLine) { + this.entityClickDebounceTimer = setTimeout(() => { + this.entityClickDebounceTimer = null; + this.lastEntityClickTime = 0; + if (isWaypoint) { + console.log(`>>> [地图触发] 点击了点 ${dbId}, 属于航线 ${routeId}`); + this.$emit('open-waypoint-dialog', dbId, routeId); + } else if (isRouteLine) { + console.log(`>>> [地图触发] 点击了航线 ${routeId}`); + this.$emit('open-route-dialog', routeId); + } + }, 250); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); + + // 双击实体时恢复相机,避免误触导致地图放大过多 + this.handler.setInputAction((click) => { + if (this.isDrawing) return; + const pickedObject = this.viewer.scene.pick(click.position); + if (!Cesium.defined(pickedObject) || !pickedObject.id) return; + const entity = pickedObject.id; + const idStr = (entity && entity.id) ? entity.id : ''; + if (idStr && (idStr.endsWith('-rotate-handle') || idStr.indexOf('-scale-') !== -1)) return; + const platformIconData = this.allEntities.find(e => e.type === 'platformIcon' && e.entity === entity); + const now = Cesium.JulianDate.now(); + const props = entity.properties ? entity.properties.getValue(now) : null; + const isEntity = platformIconData || (props && (props.isMissionWaypoint || props.isMissionRouteLine)); + if (isEntity && this.cameraStateBeforeEntityClick) { + this.restoreCameraStateAfterEntityDoubleClick(); + if (this.entityClickDebounceTimer) { + clearTimeout(this.entityClickDebounceTimer); + this.entityClickDebounceTimer = null; + } + this.lastEntityClickTime = 0; + } + }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); } catch (error) { console.error('地图错误:', error) // 如果Cesium加载失败,显示错误信息 @@ -2140,6 +2191,32 @@ export default { controller.enableLook = false scene.screenSpaceCameraController.maximumPitch = 0 scene.screenSpaceCameraController.minimumPitch = 0 + // 限制最小相机高度,防止双击时地图放大过多(单位:米) + controller.minimumZoomDistance = 2000 + }, + /** 在可能触发缩放的实体点击前保存相机状态,供双击时恢复 */ + saveCameraStateBeforeEntityClick() { + if (!this.viewer || !this.viewer.camera) return + const cam = this.viewer.camera + const carto = cam.positionCartographic + this.cameraStateBeforeEntityClick = { + longitude: carto.longitude, + latitude: carto.latitude, + height: carto.height, + heading: cam.heading, + pitch: cam.pitch, + roll: cam.roll + } + }, + /** 双击实体后恢复相机,避免误触导致地图放大过多 */ + restoreCameraStateAfterEntityDoubleClick() { + if (!this.viewer || !this.viewer.camera || !this.cameraStateBeforeEntityClick) return + const s = this.cameraStateBeforeEntityClick + this.viewer.camera.setView({ + destination: Cesium.Cartesian3.fromRadians(s.longitude, s.latitude, s.height), + orientation: { heading: s.heading, pitch: s.pitch, roll: s.roll } + }) + this.cameraStateBeforeEntityClick = null }, loadOfflineMap() { this.viewer.imageryLayers.removeAll() @@ -4862,6 +4939,16 @@ export default { destroyViewer() { this.stopDrawing() this.clearAll(false) + if (this.entityClickDebounceTimer) { + clearTimeout(this.entityClickDebounceTimer) + this.entityClickDebounceTimer = null + } + this.lastEntityClickTime = 0 + this.cameraStateBeforeEntityClick = null + if (this.handler) { + this.handler.destroy() + this.handler = null + } if (this.pointMovementHandler) { this.pointMovementHandler.destroy()