From 1d552a3bad95caae4af15322df28e6240b797693 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Thu, 13 Aug 2026 15:32:06 +0800
Subject: [PATCH] feat: app视频封面图

---
 packages/utils/map/DrawPolygon.js |   91 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/packages/utils/map/DrawPolygon.js b/packages/utils/map/DrawPolygon.js
index 80c3518..f337484 100644
--- a/packages/utils/map/DrawPolygon.js
+++ b/packages/utils/map/DrawPolygon.js
@@ -2,6 +2,7 @@
 import * as turf from '@turf/turf'
 import { ElMessage } from 'element-plus'
 import { flyVisual, getPointPositionsHeight } from './index'
+import { MapTooltip } from './MapTooltip'
 
 /**
  * 多边形绘制与编辑工具类
@@ -13,7 +14,10 @@
  *  - 外部订阅/通知机制
  */
 export class DrawPolygon {
-	constructor() {
+	constructor(options = {}) {
+		// 设备覆盖范围列表(经纬度 + 5000m半径)
+		this.deviceList = options.deviceList || []
+		this.coverageRadius = 5000
 		// 图斑预览模式标记
 		this.isPureSpotPreview = false
 		// 是否删除测区
@@ -57,12 +61,17 @@
 		this.handleLeftUp = this.handleLeftUp.bind(this)
 		this.handleMouseMove = this.handleMouseMove.bind(this)
 		this.handleLeftClick = this.handleLeftClick.bind(this)
+		this.handleDoubleClick = this.handleDoubleClick.bind(this)
 		this.handleRightClick = this.handleRightClick.bind(this)
 
 		this.delPolygon = this.delPolygon.bind(this)
 		this.delPoint = this.delPoint.bind(this)
 		// 外部订阅者
 		this.listeners = []
+		// 绘制提示 tooltip
+		this.drawingTooltip = null
+		// 防止双击时第二次点击添加重复的点
+		this._lastClickTime = 0
 	}
 
 	// 实体命名常量
@@ -123,6 +132,7 @@
 	// 开始绘制
 	startDrawing() {
 		this.drawingMode = true
+		this._lastClickTime = 0
 		this.curPolygon = new Cesium.PolygonHierarchy()
 
 		// 如果还没有 DataSource,就新建一个
@@ -395,6 +405,19 @@
 	handleLeftUp() {
 		if (!(this.editingMode && this.curPolygon?.positions && this.draggedEntity)) return
 
+		// 检查松手位置是否在设备覆盖范围内
+		if (this.isDragging && !this.isWithinDeviceCoverage(this.curPolygon.positions[this.draggedEntity?.customData.ind])) {
+			ElMessage.warning('该位置不在设备覆盖范围内,请在设备5公里范围内绘制')
+			// 回弹到拖拽前的位置
+			this.draggedEntity.position = this.currentDragPointPosition
+			this.curPolygon.positions[this.draggedEntity?.customData.ind] = this.currentDragPointPosition
+			this.isDragging = false
+			this.draggedEntity = null
+			this.enableMapControl()
+			this.rebuildMidPoints()
+			return
+		}
+
 		if (this.currentDragPointIsValid && this.isDragging) {
 			// 更新点位置
 			this.draggedEntity.position = this.currentDragPointPosition
@@ -430,6 +453,11 @@
 
 		const cartesian = this.viewer.scene.pickPosition(movement.endPosition)
 		if (!cartesian) return
+
+		// 更新绘制提示 tooltip 位置
+		if (this.drawingMode && this.drawingTooltip) {
+			this.drawingTooltip.move(movement.endPosition)
+		}
 
 		// 编辑模式下,拖拽点实时更新
 		if (this.editingMode && this.draggedEntity?.customData) {
@@ -503,9 +531,22 @@
 			return
 		}
 
+		// 防止双击时第二次点击添加重复的点(双击触发顺序:click → click → dblclick)
+		const now = Date.now()
+		if (this._lastClickTime && (now - this._lastClickTime) < 300) {
+			return
+		}
+		this._lastClickTime = now
+
 		// 添加新的点
 		const cartesian = this.viewer.scene.pickPosition(click.position)
 		if (!cartesian) return
+
+		// 检查点击位置是否在设备覆盖范围内
+		if (!this.isWithinDeviceCoverage(cartesian)) {
+			ElMessage.warning('该位置不在设备覆盖范围内,请在设备5公里范围内绘制')
+			return
+		}
 
 		let arr = [...this.curPolygon.positions]
 		arr.pop()
@@ -516,6 +557,14 @@
 		}
 
 		this.addPosition(cartesian)
+	}
+
+	// 鼠标双击(完成绘制)
+	handleDoubleClick() {
+		if (!this.drawingMode) return
+		// 双击时第一次 LEFT_CLICK 已经添加了一个点,所以至少需要 4 个点(3个有效点 + 1个跟踪点)
+		if (this.curPolygon.positions.length < 4) return
+		this.finishDrawing()
 	}
 
 	// 鼠标右键点击(弹出菜单)
@@ -579,6 +628,11 @@
 	finishDrawing() {
 		this.curPolygon.positions.pop()
 
+		// 隐藏绘制提示
+		if (this.drawingTooltip) {
+			this.drawingTooltip.hide()
+		}
+
 		if (this.curPolygon.positions.length >= 3) {
 			this.drawingMode = false
 			this.editingMode = true
@@ -607,6 +661,11 @@
 		this.removeMenuPopup()
 		this.notify('getPolygonPositions', [])
 		this.startDrawing()
+
+		// 重新显示绘制提示
+		if (this.drawingTooltip) {
+			this.drawingTooltip.show('左键点击绘制,双击结束绘制')
+		}
 	}
 	// 删除图斑
 	delSpot() {
@@ -644,7 +703,7 @@
 
 		const menuItems =
 			type === 'polygon'
-				? [{ title: '删除测区', class: 'del-planar-polygon' }]
+				? [{ title: '删除范围', class: 'del-planar-polygon' }]
 				: [{ title: '删除端点', class: 'del-planar-point' }]
 
 		menuItems.forEach(item => {
@@ -708,6 +767,20 @@
 
 		return intersections.features.length === 0
 	}
+
+	// 检查位置是否在任意设备的覆盖范围内(5km)
+	isWithinDeviceCoverage(cartesian) {
+		if (!this.deviceList || this.deviceList.length === 0) return true
+		const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
+		const clickPoint = turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)])
+		return this.deviceList
+			.filter(item => item.latitude)
+			.some(item => {
+				const rangePoint = turf.point([item.longitude, item.latitude])
+				const distance = turf.distance(rangePoint, clickPoint, { units: 'kilometers' })
+				return distance <= 5
+			})
+	}
 	// 初始化已有多边形
 	async initPolygon(viewer, positions, isPurePreview = false) {
 		this.initHandler(viewer)
@@ -760,6 +833,12 @@
 		this.viewer = viewer
 		this.startDrawing()
 
+		// 初始化绘制提示 tooltip
+		if (!this.drawingTooltip) {
+			this.drawingTooltip = new MapTooltip(viewer)
+			this.drawingTooltip.show('左键点击绘制,双击结束绘制')
+		}
+
 		if (!this.handler) {
 			this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
 
@@ -769,6 +848,7 @@
 				[Cesium.ScreenSpaceEventType.LEFT_UP, this.handleLeftUp],
 				[Cesium.ScreenSpaceEventType.MOUSE_MOVE, this.handleMouseMove],
 				[Cesium.ScreenSpaceEventType.LEFT_CLICK, this.handleLeftClick],
+				[Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK, this.handleDoubleClick],
 				[Cesium.ScreenSpaceEventType.RIGHT_CLICK, this.handleRightClick],
 			]
 
@@ -786,6 +866,7 @@
 				Cesium.ScreenSpaceEventType.LEFT_UP,
 				Cesium.ScreenSpaceEventType.MOUSE_MOVE,
 				Cesium.ScreenSpaceEventType.LEFT_CLICK,
+				Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK,
 				Cesium.ScreenSpaceEventType.RIGHT_CLICK,
 			]
 
@@ -807,5 +888,11 @@
 		this.removeEntities()
 		this.removeHandler()
 		this.enableMapControl()
+
+		// 销毁绘制提示 tooltip
+		if (this.drawingTooltip) {
+			this.drawingTooltip.destroy()
+			this.drawingTooltip = null
+		}
 	}
 }

--
Gitblit v1.9.3