From 80f027521688461fe7512af845b8025d633537e8 Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Tue, 3 Mar 2026 20:09:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(aiot):=20ROI=20=E6=98=BE=E7=A4=BA=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20+=20=E5=89=8D=E7=AB=AF=E6=88=AA=E5=9B=BE=E7=AD=96?= =?UTF-8?q?=E7=95=A5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - aiRoi.js: getSnapUrl 改为直接返回 /snap/image 代理 URL, 非 force 模式不再触发 Edge 截图(从 DB 读持久化截图) - roiConfig.vue: fetchSnap 适配新 API(直接使用返回的 URL) - RoiCanvas.vue: · 添加 ResizeObserver 确保容器尺寸变化时重新初始化 canvas · onImageError 兜底初始化 canvas(截图失败仍可绘制/查看 ROI) · snapUrl watcher 触发 canvas 重初始化 Co-Authored-By: Claude Opus 4.6 --- web/src/api/aiRoi.js | 20 ++++++++++++++----- web/src/views/cameraConfig/roiConfig.vue | 16 ++------------- .../views/roiConfig/components/RoiCanvas.vue | 19 +++++++++++++++++- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/web/src/api/aiRoi.js b/web/src/api/aiRoi.js index 6898efdf2..a3bcbc032 100644 --- a/web/src/api/aiRoi.js +++ b/web/src/api/aiRoi.js @@ -64,9 +64,19 @@ export function updateAlgoParams(data) { } export function getSnapUrl(cameraCode, force = false) { - return request({ - method: 'get', - url: '/api/ai/roi/snap', - params: { cameraCode, force } - }) + if (force) { + // force 模式:先触发 Edge 截图(更新 DB),再返回代理 URL + return request({ + method: 'get', + url: '/api/ai/roi/snap', + params: { cameraCode, force: true } + }).then(() => { + return '/api/ai/roi/snap/image?cameraCode=' + encodeURIComponent(cameraCode) + '&t=' + Date.now() + }).catch(() => { + // 截图请求失败也返回代理 URL(可能 DB 有旧数据) + return '/api/ai/roi/snap/image?cameraCode=' + encodeURIComponent(cameraCode) + '&t=' + Date.now() + }) + } + // 非 force:直接返回代理 URL(从 DB 读取持久化截图,不触发 Edge) + return Promise.resolve('/api/ai/roi/snap/image?cameraCode=' + encodeURIComponent(cameraCode)) } diff --git a/web/src/views/cameraConfig/roiConfig.vue b/web/src/views/cameraConfig/roiConfig.vue index 48bc24e3d..a3dfc0711 100644 --- a/web/src/views/cameraConfig/roiConfig.vue +++ b/web/src/views/cameraConfig/roiConfig.vue @@ -150,20 +150,8 @@ export default { fetchSnap(force = false) { if (!this.cameraId) return this.snapLoading = true - getSnapUrl(this.cameraId, force).then(res => { - const data = res.data || res - if (data.status === 'ok' && data.url) { - // 添加时间戳防止浏览器缓存旧截图 - const url = data.url - this.snapUrl = url + (url.includes('?') ? '&' : '?') + '_t=' + Date.now() - if (data.stale) { - this.$message.warning('截图为缓存数据,边缘设备可能离线') - } - } else if (data.status === 'timeout') { - this.$message.warning(data.message || '边缘设备响应超时') - } else { - this.$message.error(data.message || '截图失败') - } + getSnapUrl(this.cameraId, force).then(url => { + this.snapUrl = url }).catch(() => { this.$message.error('截图请求失败,请检查网络') }).finally(() => { diff --git a/web/src/views/roiConfig/components/RoiCanvas.vue b/web/src/views/roiConfig/components/RoiCanvas.vue index 2bece4a42..a732b97f1 100644 --- a/web/src/views/roiConfig/components/RoiCanvas.vue +++ b/web/src/views/roiConfig/components/RoiCanvas.vue @@ -43,7 +43,8 @@ export default { currentPoint: null, polygonPoints: [], loading: true, - errorMsg: '' + errorMsg: '', + resizeObserver: null } }, watch: { @@ -57,16 +58,30 @@ export default { snapUrl() { this.loading = true this.errorMsg = '' + this.$nextTick(() => this.initCanvas()) } }, mounted() { this.$nextTick(() => { this.initCanvas() + // ResizeObserver 确保容器尺寸变化时重新初始化 canvas + if (this.$refs.wrapper && typeof ResizeObserver !== 'undefined') { + this.resizeObserver = new ResizeObserver(() => { + if (this.$refs.wrapper && this.$refs.wrapper.clientWidth > 0) { + this.initCanvas() + } + }) + this.resizeObserver.observe(this.$refs.wrapper) + } window.addEventListener('resize', this.handleResize) }) }, beforeDestroy() { window.removeEventListener('resize', this.handleResize) + if (this.resizeObserver) { + this.resizeObserver.disconnect() + this.resizeObserver = null + } }, methods: { onImageLoad() { @@ -78,6 +93,8 @@ export default { onImageError() { this.loading = false this.errorMsg = '截图加载失败,请确认摄像头正在拉流' + // 关键:截图失败也初始化 canvas,使 ROI 区域可见可操作 + this.$nextTick(() => this.initCanvas()) }, initCanvas() { const canvas = this.$refs.canvas