From e27e44a3c3313b84804ee9cd0cb8c8dcd29d888b Mon Sep 17 00:00:00 2001 From: zc Date: Wed, 11 Mar 2026 10:56:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/weightManage/index.vue | 205 +++++++++++++++++++++++++++---- 1 file changed, 183 insertions(+), 22 deletions(-) diff --git a/src/views/weightManage/index.vue b/src/views/weightManage/index.vue index edcfc25..8d2141d 100644 --- a/src/views/weightManage/index.vue +++ b/src/views/weightManage/index.vue @@ -57,10 +57,10 @@
@@ -71,7 +71,38 @@
-
实时画面 相机1
+ +
+ + + +
+ + 加载中... +
+ + +
+ + 连接失败 + 重试 +
+ + +
+ + 未连接 + 连接 +
+ + +
+ LIVE +
+
实时画面 相机2
@@ -93,7 +124,7 @@
比对结果: @@ -247,18 +278,18 @@
上一步 {{ activeStep === 2 ? '完成' : '下一步' }} @@ -297,9 +328,16 @@ const formData = reactive({ // 摄像头状态 const cameraStatus = ref<'connected' | 'connecting' | 'disconnected' | 'error'>('disconnected') +const camera1Status = ref<'connected' | 'connecting' | 'disconnected' | 'error'>('disconnected') // 视频元素引用 const cameraVideo = ref(null) +// 相机1使用canvas元素 +const camera1Canvas = ref(null) + +// 相机1 WebSocket连接 +const camera1Ws = ref(null) +const camera1WsConnected = ref(false) // FLV播放器实例 let player: any = null @@ -519,20 +557,30 @@ const stopCamera = () => { // 监听步骤变化 watch(activeStep, (newVal) => { - if (newVal === 2) { + if (newVal === 1) { + // 进入扫码核验页面,启动相机1 + nextTick(() => { + initCamera1() + }) + } else if (newVal === 2) { // 进入称重登记页面,启动摄像头 nextTick(() => { initCamera() }) } else { - // 离开称重登记页面,停止摄像头 + // 离开相关页面,停止摄像头 stopCamera() + closeCamera1WebSocket() } }) // 组件挂载时 onMounted(async () => { await loadFlvJs() + // 如果当前是扫码核验页面,初始化相机1 + if (activeStep.value === 1) { + initCamera1() + } }) // 组件卸载时 @@ -759,6 +807,118 @@ const handleNext = async () => { } } +// 初始化相机1 WebSocket连接 +const initCamera1 = () => { + camera1Status.value = 'connecting' + + try { + const wsUrl = 'ws://localhost:6609/ws/camera' + camera1Ws.value = new WebSocket(wsUrl) + + camera1Ws.value.onopen = () => { + camera1Status.value = 'connected' + camera1WsConnected.value = true + Message.success('已和相机1建立连接') + } + + // 修改前端代码,处理黑白相机的视频流数据 + camera1Ws.value.onmessage = (event) => { + try { + if (camera1Canvas.value && event.data instanceof Blob) { + // 处理二进制图像数据 + const reader = new FileReader(); + reader.onload = (e) => { + if (e.target && e.target.result) { + const arrayBuffer = e.target.result; + const uint8Array = new Uint8Array(arrayBuffer); + + // 解析消息格式: [width(4 bytes)][height(4 bytes)][image data] + if (uint8Array.length < 8) { + console.error('相机1 WebSocket消息格式错误: 数据长度不足'); + return; + } + + // 读取宽度和高度(小端序) + const width = uint8Array[0] | (uint8Array[1] << 8) | (uint8Array[2] << 16) | (uint8Array[3] << 24); + const height = uint8Array[4] | (uint8Array[5] << 8) | (uint8Array[6] << 16) | (uint8Array[7] << 24); + + // 检查宽度和高度是否合理 + if (width <= 0 || height <= 0 || width > 4096 || height > 4096) { + console.error('相机1 WebSocket消息格式错误: 无效的图像尺寸'); + return; + } + + // 提取图像数据 + const imageDataStart = 8; + const imageDataLength = uint8Array.length - imageDataStart; + const imageData = uint8Array.subarray(imageDataStart); + + // 设置canvas尺寸 + camera1Canvas.value.width = width; + camera1Canvas.value.height = height; + + // 获取canvas上下文 + const ctx = camera1Canvas.value.getContext('2d'); + if (ctx) { + // 创建ImageData对象 + const canvasImageData = ctx.createImageData(width, height); + + // 对于黑白相机,数据是单通道灰度格式 + // 将单通道灰度数据转换为RGBA格式 + for (let i = 0, j = 0; i < imageData.length && j < canvasImageData.data.length; i++, j += 4) { + const gray = imageData[i]; + canvasImageData.data[j] = gray; // R + canvasImageData.data[j + 1] = gray; // G + canvasImageData.data[j + 2] = gray; // B + canvasImageData.data[j + 3] = 255; // A (不透明) + } + + // 将ImageData绘制到canvas上 + ctx.putImageData(canvasImageData, 0, 0); + } + } + }; + reader.readAsArrayBuffer(event.data); + } + } catch (error) { + console.error('相机1 WebSocket消息解析失败:', error) + } + } + + + camera1Ws.value.onclose = () => { + camera1Status.value = 'disconnected' + camera1WsConnected.value = false + } + + camera1Ws.value.onerror = (error) => { + console.error('相机1 WebSocket错误:', error) + camera1Status.value = 'error' + Message.error('相机1连接失败') + } + } catch (error) { + console.error('建立相机1 WebSocket连接失败:', error) + camera1Status.value = 'error' + Message.error('无法建立相机1连接') + } +} + +// 重新连接相机1 +const reconnectCamera1 = () => { + closeCamera1WebSocket() + setTimeout(() => initCamera1(), 1000) +} + +// 关闭相机1 WebSocket连接 +const closeCamera1WebSocket = () => { + if (camera1Ws.value) { + camera1Ws.value.close() + camera1Ws.value = null + camera1WsConnected.value = false + camera1Status.value = 'disconnected' + } +} + // 处理上一步 const handlePrevious = () => { if (activeStep.value > 1) { @@ -1009,6 +1169,7 @@ const closeWebSocket = () => { // 组件卸载时关闭WebSocket连接 onUnmounted(() => { closeWebSocket() + closeCamera1WebSocket() }) @@ -1428,4 +1589,4 @@ onUnmounted(() => { font-size: 14px; margin-right: 12px; } - + \ No newline at end of file