diff --git a/src/views/equipmentList/list.vue b/src/views/equipmentList/list.vue index c56aee4..72e4f43 100644 --- a/src/views/equipmentList/list.vue +++ b/src/views/equipmentList/list.vue @@ -382,9 +382,7 @@ const resetMonitorDraw = () => { }; const handleSee = async (row?: any) => { console.log('1111111111111111', row, row.drawArea); - //将row.drawArea从字符串转为对象 - const drawArea = JSON.parse(row.drawArea); - console.log('222222222222', drawArea); + reset(); resetMonitorDraw(); seeSee.value = row?.isDrawArea === 1 ? 1 : 0; @@ -398,11 +396,89 @@ const handleSee = async (row?: any) => { // 等待 DOM 更新后初始化 Hls await nextTick(); initHls(); - if (drawArea) { - monitorDrawCollecting.value = true; + + // 如果有 drawArea,直接使用它显示矩形区域,不允许点击绘制 + if (row?.drawArea) { + try { + // 将 drawArea 从字符串转为对象 + const drawArea = typeof row.drawArea === 'string' ? JSON.parse(row.drawArea) : row.drawArea; + console.log('[查看监控] 解析后的 drawArea:', drawArea); + + if (drawArea && drawArea.x1 !== undefined && drawArea.y1 !== undefined && drawArea.x2 !== undefined && drawArea.y2 !== undefined) { + // 等待视频加载完成 + await nextTick(); + const video = monitorVideoRef.value; + + // 如果视频已加载,立即显示矩形 + if (video && video.videoWidth > 0 && video.videoHeight > 0) { + displayDrawArea(drawArea, video); + } else if (video) { + // 如果视频还未加载,等待 loadedmetadata 事件 + video.addEventListener( + 'loadedmetadata', + () => { + displayDrawArea(drawArea, video); + }, + { once: true } + ); + } + } + } catch (error) { + console.error('[查看监控] 解析 drawArea 失败:', error); + } } }; +// 提取显示报警区域的逻辑为独立函数 +const displayDrawArea = (drawArea: any, video: HTMLVideoElement) => { + const VW = video.videoWidth; + const VH = video.videoHeight; + if (!VW || !VH) return; + + // 计算视频原始像素坐标(x 是距离右侧的千分比,y 是距离顶部的千分比) + const x1Video = VW - (drawArea.x1 / 1000) * VW; + const y1Video = (drawArea.y1 / 1000) * VH; + const x2Video = VW - (drawArea.x2 / 1000) * VW; + const y2Video = (drawArea.y2 / 1000) * VH; + + const rect = video.getBoundingClientRect(); + const dw = rect.width; + const dh = rect.height; + if (dw <= 0 || dh <= 0) return; + + const scale = Math.min(dw / VW, dh / VH); + const contentW = VW * scale; + const contentH = VH * scale; + const offsetX = (dw - contentW) / 2; + const offsetY = (dh - contentH) / 2; + + const x1Px = offsetX + x1Video * scale; + const y1Px = offsetY + y1Video * scale; + const x2Px = offsetX + x2Video * scale; + const y2Px = offsetY + y2Video * scale; + + const left = Math.min(x1Px, x2Px); + const top = Math.min(y1Px, y2Px); + const width = Math.max(Math.abs(x2Px - x1Px), 2); + const height = Math.max(Math.abs(y2Px - y1Px), 2); + + monitorRectPx.value = { left, top, width, height }; + monitorDrawCollecting.value = false; // 禁止点击绘制 + + // 同时添加到 payload 用于保存 + payload.value = [ + { + deviceId: form.value.id, + x1: drawArea.x1, + y1: drawArea.y1, + x2: drawArea.x2, + y2: drawArea.y2 + } + ]; + + console.log('[查看监控] 已加载已有报警区域', payload.value); +}; + const handleMonitorDialogClose = (done: () => void) => { // 卸载 Hls 与清理 video destroyHls(); @@ -487,13 +563,15 @@ const onMonitorDrawClick = (e: MouseEvent) => { const point2RightPctOfWidth = ((VW - v2.vx) / VW) * 1000; const point2TopPctOfHeight = (v2.vy / VH) * 1000; + const clamp = (value: number) => Math.max(0, Math.min(1000, Math.round(value))); + // 添加新的报警区域到数组 const newArea: AlarmAreaData = { deviceId: form.value.id, - x1: Math.round(point1RightPctOfWidth), - y1: Math.round(point1TopPctOfHeight), - x2: Math.round(point2RightPctOfWidth), - y2: Math.round(point2TopPctOfHeight) + x1: clamp(point1RightPctOfWidth), + y1: clamp(point1TopPctOfHeight), + x2: clamp(point2RightPctOfWidth), + y2: clamp(point2TopPctOfHeight) }; payload.value.push(newArea); console.log('[监控区域] 两点千分比坐标', newArea); @@ -510,6 +588,7 @@ const clearImage = () => { // 清除绘制的矩形图案 monitorRectPx.value = null; monitorDrawPoints.value = []; + monitorDrawCollecting.value = false; // 重置为不允许点击绘制状态 }; const saveImage = async () => {