feat(aiot): 截图持久化 + ROI 显示修复 + 告警图片代理

截图策略改为截一次持久化到 DB,打开 ROI 页面不再触发 Edge 截图:
- 新增 wvp_ai_camera_snapshot 表存储 cos_key
- AiScreenshotServiceImpl 回调时持久化 cos_key,图片代理增加 DB 回退
- 前端 getSnapUrl 直接返回代理 URL,force=true 才触发 Edge

RoiCanvas 修复:
- ResizeObserver 替代 nextTick 初始化 canvas
- 图片加载失败时仍初始化 canvas 以显示 ROI

告警图片代理:
- AiAlertController 新增 /image 端点通过 presign URL 代理 COS 图片
- 新增告警列表前端页面 alertList

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-03 16:56:26 +08:00
parent e140d4ceeb
commit 547dfdd5f4
16 changed files with 399 additions and 25 deletions

View File

@@ -57,16 +57,26 @@ export default {
snapUrl() {
this.loading = true
this.errorMsg = ''
this.$nextTick(() => this.initCanvas())
}
},
mounted() {
this.$nextTick(() => {
this.initCanvas()
window.addEventListener('resize', this.handleResize)
})
if (this.$refs.wrapper) {
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 +88,7 @@ export default {
onImageError() {
this.loading = false
this.errorMsg = '截图加载失败,请确认摄像头正在拉流'
this.$nextTick(() => this.initCanvas())
},
initCanvas() {
const canvas = this.$refs.canvas