diff --git a/src/views/iot/tplink/camera/components/CameraPreviewForm.vue b/src/views/iot/tplink/camera/components/CameraPreviewForm.vue index f1328f8..ff67911 100644 --- a/src/views/iot/tplink/camera/components/CameraPreviewForm.vue +++ b/src/views/iot/tplink/camera/components/CameraPreviewForm.vue @@ -2,7 +2,10 @@ -
+
@@ -460,18 +463,18 @@ function zoomInOut(type) { } } -/** - * 控制球机 - */ -function moveCtrl(direction, startOrNot, speed) { - let params = { - "deviceIndex": formData.deviceIndex, - "direction": direction, - "startOrNot": startOrNot, - "speed": speed, - }; - motionCtrl(params); -} +// /** +// * 控制球机 +// */ +// function moveCtrl(direction, startOrNot, speed) { +// let params = { +// "deviceIndex": formData.deviceIndex, +// "direction": direction, +// "startOrNot": startOrNot, +// "speed": speed, +// }; +// motionCtrl(params); +// } function delayExecute(fn, args, delay) { setTimeout(() => { @@ -490,6 +493,345 @@ function destroy() { } } +//控制画面移动 +const isDragging = ref(false) // 是否正在拖动 +const dragStartPos = ref({ x: 0, y: 0 }) // 拖动开始位置 +const dragTimer = ref(null) // 拖动计时器 +const moveDirection = ref(null) // 移动方向 +const moveCalled = ref(false) // 是否已调用move方法 +const lastMousePos = ref({ x: 0, y: 0 }) // 最后一次鼠标位置 +const moveSamples = ref>([]) // 移动采样点 +const moveStartTime = ref(0) // 移动开始时间 +const zoomTimer = ref(null) // 滚轮计时器 +const isZooming = ref(false) // 是否正在缩放 +const zoomDirection = ref(null) // 缩放方向 +const lastWheelTime = ref(0) // 最后滚轮时间 + +/** + * 控制球机移动 + */ +function moveCtrl(direction, startOrNot, speed) { + if (!formData.deviceIndex) return; + + let params = { + "deviceIndex": formData.deviceIndex, + "direction": direction, + "startOrNot": startOrNot, + "speed": speed, + }; + motionCtrl(params); + + if (startOrNot === 1) { + const directions = { + 1: '上', + 3: '左', + 5: '右', + 7: '下', + 9: '缩小', + 10: '放大', + 11: '对焦' + }; + const action = startOrNot === 1 ? '开始' : '停止'; + } +} + +/** + * 鼠标在摄像头上按下 + */ +function onCameraMouseDown(e: MouseEvent) { + // 只响应左键 + if (e.button !== 0) return + + isDragging.value = true + moveCalled.value = false + moveDirection.value = null + moveSamples.value = [] // 清空采样点 + moveStartTime.value = Date.now() + + // 记录起点位置 + const startPos = { + x: e.clientX, + y: e.clientY, + t: Date.now() + } + dragStartPos.value = { x: startPos.x, y: startPos.y } + lastMousePos.value = { x: e.clientX, y: e.clientY } // 记录当前鼠标位置 + moveSamples.value.push(startPos) // 记录第一个采样点 + + // 设置0.5秒计时器 + if (dragTimer.value) { + clearTimeout(dragTimer.value) + } + dragTimer.value = setTimeout(() => { + if (isDragging.value && !moveCalled.value && moveSamples.value.length > 1) { + determineMoveDirection() + } + }, 500) +} + +/** + * 鼠标在摄像头上移动 + */ +function onCameraMouseMove(e: MouseEvent) { + if (!isDragging.value) { + return + } + + // 记录当前鼠标位置 + lastMousePos.value = { x: e.clientX, y: e.clientY } + + // 记录当前移动点 + const currentPos = { + x: e.clientX, + y: e.clientY, + t: Date.now() + } + moveSamples.value.push(currentPos) + + // 只保留最近20个点 + if (moveSamples.value.length > 20) { + moveSamples.value = moveSamples.value.slice(-20) + } + + + // 如果已经调用过move,就不重复调用 + if (moveCalled.value) { + return + } + + // 计算移动距离 + const moveX = e.clientX - dragStartPos.value.x + const moveY = e.clientY - dragStartPos.value.y + const distance = Math.sqrt(moveX * moveX + moveY * moveY) + + + // 判断是否移动足够距离(防止微小抖动误判) + const minMove = 5 // 最小移动距离 + if (distance < minMove) { + return + } + + // 清除计时器 + if (dragTimer.value) { + clearTimeout(dragTimer.value) + dragTimer.value = null + } + + // 根据方向调用移动 + determineMoveDirection() +} + +/** + * 判断移动方向 + */ +function determineMoveDirection() { + if (!isDragging.value || moveCalled.value) { + return + } + + // 获取起点和当前鼠标位置 + const startPos = dragStartPos.value + const endPos = lastMousePos.value + + const deltaX = endPos.x - startPos.x + const deltaY = endPos.y - startPos.y + const absDeltaX = Math.abs(deltaX) + const absDeltaY = Math.abs(deltaY) + + + // 设置角度阈值(判断斜对角方向) + const angleThreshold = Math.PI / 6 // 30度 + + // 计算角度 + const angle = Math.atan2(deltaY, deltaX) + const absAngle = Math.abs(angle) + + + let direction: number + + // 判断8个方向 + if (absDeltaX < 5 && absDeltaY < 5) { + // 移动距离太小,不处理 + return + } + + // 判断方向 + if (absAngle < angleThreshold) { + // 右: 0度附近 + direction = 5 + } else if (absAngle > Math.PI - angleThreshold) { + // 左: ±180度附近 + direction = 3 + } else if (angle > 0) { + // 下半部分 + if (absAngle < Math.PI / 2 - angleThreshold) { + // 右下: 45度附近 + direction = 8 + } else if (absAngle > Math.PI / 2 + angleThreshold) { + // 左下: 135度附近 + direction = 6 + } else { + // 下: 90度附近 + direction = 7 + } + } else { + // 上半部分 + if (absAngle < Math.PI / 2 - angleThreshold) { + // 右上: -45度附近 + direction = 2 + } else if (absAngle > Math.PI / 2 + angleThreshold) { + // 左上: -135度附近 + direction = 0 + } else { + // 上: -90度附近 + direction = 1 + } + } + + // 记录方向 + moveDirection.value = direction + moveCalled.value = true + + // 调用开始移动 + moveCtrl(direction, 1, 1) +} + +/** + * 鼠标在摄像头上松开 + */ +function onCameraMouseUp(e: MouseEvent) { + if (!isDragging.value) return + + // 清除计时器 + if (dragTimer.value) { + clearTimeout(dragTimer.value) + dragTimer.value = null + } + + // 如果有正在进行的移动,调用结束 + if (moveDirection.value !== null) { + moveCtrl(moveDirection.value, 0, 1) + } else { + } + + // 记录数据用于分析 + if (moveSamples.value.length > 0) { + const firstPoint = moveSamples.value[0] + const lastPoint = moveSamples.value[moveSamples.value.length - 1] + const totalDistance = Math.sqrt( + Math.pow(lastPoint.x - firstPoint.x, 2) + + Math.pow(lastPoint.y - firstPoint.y, 2) + ) + } + + // 重置状态 + isDragging.value = false + moveCalled.value = false + moveDirection.value = null + moveSamples.value = [] +} + +/** + * 鼠标滚轮事件 + */ +function onCameraWheel(e: WheelEvent) { + // 防止页面滚动 + e.preventDefault() + + const now = Date.now() + const deltaY = e.deltaY // 滚轮滚动量 + + console.log("🔄 滚轮滚动:", deltaY) + + // 判断滚轮方向 + // deltaY > 0: 向下滚动(缩小) + // deltaY < 0: 向上滚动(放大) + const direction = deltaY > 0 ? 9 : 10 + + // 如果正在缩放,先结束之前的缩放 + if (isZooming.value) { + // 如果方向相同,继续当前缩放 + if (zoomDirection.value === direction) { + // 重置1秒计时器 + if (zoomTimer.value) { + clearTimeout(zoomTimer.value) + } + zoomTimer.value = setTimeout(() => { + endZoom() + }, 1000) + lastWheelTime.value = now + return + } else { + // 方向改变,先结束当前缩放 + endZoom() + } + } + + // 开始新的缩放 + startZoom(direction) +} + +/** + * 开始缩放 + */ +function startZoom(direction: number) { + console.log("🔍 开始缩放:", direction === 9 ? '缩小' : '放大') + + isZooming.value = true + zoomDirection.value = direction + + // 调用开始缩放 + moveCtrl(direction, 1, 1) + + // 设置1秒后自动结束 + if (zoomTimer.value) { + clearTimeout(zoomTimer.value) + } + zoomTimer.value = setTimeout(() => { + endZoom() + }, 1000) + + lastWheelTime.value = Date.now() +} + +/** + * 结束缩放 + */ +function endZoom() { + if (isZooming.value && zoomDirection.value !== null) { + console.log("🛑 结束缩放:", zoomDirection.value === 9 ? '缩小' : '放大') + moveCtrl(zoomDirection.value, 0, 1) + } + + // 重置状态 + isZooming.value = false + zoomDirection.value = null + + if (zoomTimer.value) { + clearTimeout(zoomTimer.value) + zoomTimer.value = null + } +} + +/** + * 清理滚轮计时器 + */ +function clearZoomTimer() { + if (zoomTimer.value) { + clearTimeout(zoomTimer.value) + zoomTimer.value = null + } + isZooming.value = false + zoomDirection.value = null +} + +/** + * 鼠标离开摄像头区域 + */ +function onCameraMouseLeave(e: MouseEvent) { + onCameraMouseUp(e) +} + defineExpose({ edit, destroy diff --git a/src/views/system/dict/dict.data.ts b/src/views/system/dict/dict.data.ts index 473ae79..44757b8 100644 --- a/src/views/system/dict/dict.data.ts +++ b/src/views/system/dict/dict.data.ts @@ -95,6 +95,11 @@ export const dictItemColumns: BasicColumn[] = [ dataIndex: 'itemValue', width: 80, }, + { + title: '描述', + dataIndex: 'description', + width: 100, + }, { title: '字典颜色', dataIndex: 'itemColor',