Commit Graph

4148 Commits

Author SHA1 Message Date
a879487551 修复:补充 Docker COS 凭证配置,修复截图代理 404 问题
- docker-compose.yml 添加 COS_SECRET_ID/KEY/REGION/BUCKET 环境变量透传
- docker/.env 填入腾讯云 COS 凭证和截图回调地址
- AiRoiController 移除多余 @GetMapping 注解,消除 Spring 双注解警告

根因:容器未传入 COS 凭证 → CosUtil 初始化跳过 → proxyScreenshotImage 返回 null → 404

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 11:03:20 +08:00
0750db2f44 修复:回退proxyScreenshotImage中同步触发截图逻辑,解决状态栏全红和图片损坏
proxyScreenshotImage是HEAD/GET快速响应接口,不应同步阻塞15秒等待边缘端截图。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 10:12:12 +08:00
cd6fea7a50 功能:预置车辆违停和车辆拥堵算法定义
PRESET_ALGORITHMS新增illegal_parking和vehicle_congestion,
target_class为car,truck,bus,motorcycle,包含完整paramSchema定义。
WVP启动时自动初始化到wvp_ai_algorithm表。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 16:54:49 +08:00
8ddb56008f 修复:proxyImage无持久化记录时自动触发截图,避免首次加载404
DB无cos_key记录时,自动调用requestScreenshot触发Edge截图,
等待结果持久化后再代理返回图片,解决ROI页面首次加载显示损坏图片。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 09:48:20 +08:00
5cfac62421 修复:截图降级路径持久化cos_key,解决"无持久化记录"导致图片损坏
回调超时走Redis降级时,之前只写了缓存没有持久化cos_key到DB,
导致后续proxyImage查DB返回null显示损坏图片。
提取persistCosKey()方法供回调和降级路径共用。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 09:40:51 +08:00
8f17ba9005 修复:设置默认截图回调URL,解决Edge回调WVP问题 2026-03-10 17:02:38 +08:00
d1c8eae5b8 修复:从回调URL解析cos_key + 状态栏位置修正
1. 修复cos_key持久化问题(根本原因)
   - handleCallback原来依赖内存中的pendingCosKeys获取cos_key
   - 问题:WVP重启或多实例部署时,pendingCosKeys中找不到requestId
   - 修复:新增extractCosKeyFromUrl方法,直接从回调URL解析cos_key
   - 降级:解析失败时仍尝试从pendingCosKeys获取

2. 前端状态栏位置修正
   - 正确位置:应用名 -> 流ID -> 拉流地址 -> 状态 -> ROI
   - 之前错误地放在了流ID和拉流地址之间

3. 前端状态检测优化
   - 修复导入顺序问题(useAppConfig应在顶部导入)
   - 移除不必要的access-token参数(/snap/image已免认证)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:50:10 +08:00
9e3a406c68 修复:截图代理下载验证 + HEAD请求支持 + 状态栏位置调整
后端修复:
1. proxyScreenshotImage 优化
   - 直接从DB获取cos_key生成presigned URL
   - 移除过期的Redis缓存URL优先逻辑(避免使用过期URL)
   - 添加JPEG魔数验证,确保返回有效图片数据
   - 空数据或无效数据返回null而非损坏数据

2. /snap/image 端点支持 HEAD 请求
   - HEAD请求只检查图片是否存在,返回Content-Length
   - GET请求返回完整图片数据
   - 用于前端快速检测截图可用性

前端修复:
1. 状态栏位置调整
   - 列顺序改为:应用名 -> 流ID -> 状态 -> 拉流地址 -> ROI

2. 状态检测优化
   - 使用 HEAD 请求替代 GET,避免下载完整图片
   - 使用 fetch API 直接发送 HEAD 请求

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:29:03 +08:00
7b10b43e34 重构:camera_code生成逻辑抽取为CameraCodeUtil工具类
将StreamProxyServiceImpl和AiConfigServiceImpl中重复的URL解析+
camera_code生成代码统一到CameraCodeUtil.generate(),消除重复代码。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:53:29 +08:00
22ee2b92ee 优化:摄像头编码策略改为基于RTSP流IP生成可读ID
camera_code 从随机UUID改为 cam_{IP下划线分隔}_{4位随机} 格式,
如 cam_192_168_1_100_a3f1,提升可读性和可追溯性。
同步更新新增摄像头和启动回填两处生成逻辑。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:43:10 +08:00
08c67b1101 Revert "refactor: 摄像头管理页面移除状态栏、拉流和导出按钮"
This reverts commit fbfe2f9032.
2026-03-10 11:13:59 +08:00
fbfe2f9032 refactor: 摄像头管理页面移除状态栏、拉流和导出按钮
- 删除"状态"列(拉流中/未拉流)
- 删除操作栏中"拉流"和"导出"按钮,仅保留ROI配置
- 删除搜索栏中"拉流状态"筛选
- 清理无用的import和方法(toggleStream/handleExport)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:48:45 +08:00
827daebcf4 文档:创建 CLAUDE.md 开发指南
新增内容:
- 项目概述和生产部署信息
- 本地开发和 Docker 部署命令
- 架构概览(核心模块、配置文件)
- AIoT 关键接口说明(配置管理、ROI、截图、视频播放)
- 数据库表结构说明
- 开发工作流指引
- 常见问题排查
- Git 提交规范

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 16:27:38 +08:00
f0466e84d4 perf(aiot): 截图优化 — DB兜底 + 缓存TTL增到30分钟
问题:Redis缓存5分钟过期后,每次都重新触发Edge截图(15秒)

优化:
- Redis缓存TTL从5分钟增到30分钟(COS presigned URL有效1小时)
- Redis未命中时先查DB的cos_key,用CosUtil生成新presigned URL
- 只有DB也没有记录(首次截图)才触发Edge

效果:
- 首次截图:仍需触发Edge(不可避免)
- 后续访问:30分钟内走Redis缓存(毫秒级)
- 30分钟后:走DB → COS presign(秒级,无需Edge)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:10:26 +08:00
90e9c1c896 feat(aiot): 告警图片代理 + 告警列表页面
后端:
- IAiAlertService / AiAlertServiceImpl: 新增 proxyAlertImage()
  支持 COS object key(通过 CosUtil 生成 presigned URL)和完整 URL
- AiAlertController: 新增 GET /api/ai/alert/image 图片代理端点
- WebSecurityConfig: 白名单加 /api/ai/alert/image

前端:
- 新建 aiAlert.js API(列表查询、删除、统计、图片 URL 构造)
- 新建 alertList/index.vue 告警列表页面
  · 分页表格 + 类型/时间筛选
  · 缩略图通过 WVP 图片代理显示
  · 详情弹窗 + 删除功能
- router/index.js: 添加告警记录路由

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:12:19 +08:00
80f0275216 fix(aiot): ROI 显示修复 + 前端截图策略优化
- 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 <noreply@anthropic.com>
2026-03-03 20:09:55 +08:00
650894b4e4 feat(aiot): 截图持久化 — cos_key 存入 DB,proxyImage 支持 DB 兜底
- 新建 wvp_ai_camera_snapshot 表(camera_code → cos_key 映射)
- 新建 AiCameraSnapshotMapper(getCosKey / upsert)
- AiScreenshotServiceImpl: handleCallback 成功后将 cos_key 写入 DB
- AiScreenshotServiceImpl: proxyScreenshotImage 增加 DB 兜底路径
  Redis 缓存(5min) → DB(永久) → CosUtil 生成 presigned URL → 下载
- AiRoiController: Cache-Control 从 60s 增大到 300s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:08:47 +08:00
bdd69ce268 feat(aiot): 集成腾讯云 COS Java SDK,WVP 直接生成 presigned URL
- pom.xml 新增 cos_api 5.6.227 依赖
- 新建 CosUtil 工具类(读取 ai.cos.* 配置,初始化 COSClient,生成预签名 URL)
- application-dev.yml / application-docker.yml 增加 ai.cos 配置段

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:06:57 +08:00
86518ab163 Revert "feat(aiot): 截图持久化 + ROI 显示修复 + 告警图片代理"
This reverts commit 547dfdd5f4.
2026-03-03 17:04:23 +08:00
547dfdd5f4 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>
2026-03-03 16:56:26 +08:00
e140d4ceeb fix(aiot): 修复 backfill-device-id 被全局响应拦截器误转型导致 500
GlobalResponseAdvice:65 对 LinkedHashMap 中的 "status" 键强转 Integer,
但 backfill 端点放入的是字符串 "success",触发 ClassCastException。

- backfill 返回 Map 的键从 "status" 改为 "result" 避免冲突
- GlobalResponseAdvice 增加 instanceof Integer 类型检查,防止其他端点踩坑

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:28:39 +08:00
1093c61ca5 feat(aiot): 新增边缘设备分页/统计端点,修复 backfill 类型转换错误
- AiEdgeDeviceController 新增 /page、/get、/statistics 端点供前端直调
- AiEdgeDeviceMapper 新增 queryPage、countByStatus、countAll 方法
- AiEdgeDeviceServiceImpl 使用 PageHelper 实现分页查询和统计
- 修复 backfill-device-id 的 String→Integer ClassCastException:
  renameDeviceId 改为 renameByDeviceId,用 device_id 定位行

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:48:58 +08:00
28c7bb7947 fix(aiot): 修复告警 SQL 引用不存在的 gb_name 列
- queryByAlertId/queryList 的 COALESCE 去掉 sp.gb_name(该列属于
  device_channel 表,不在 stream_proxy 表中),改用 sp.name
- 新增轻量 countByAlertId 方法,save() 去重改用 COUNT 查询
  避免触发带 JOIN 的复杂 SQL

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:27:02 +08:00
3a2c480e05 fix(aiot): 缩小 Edge 白名单通配范围,限定具体模块
从 /api/ai/**/edge/** 改为按模块显式列出:
- /api/ai/alert/edge/**  告警上报
- /api/ai/device/edge/** 设备心跳(预留)
避免过宽通配带来的安全隐患。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:23:04 +08:00
1bbcac4b4d refactor(aiot): Edge 白名单改为通配符,免逐个添加
/api/ai/**/edge/** 覆盖所有 Edge 设备回调端点,
今后新增 Edge 端点无需再改白名单。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:22:23 +08:00
5137f4e496 fix(aiot): Edge 告警上报端点加入鉴权白名单
/api/ai/alert/edge/report 和 /api/ai/alert/edge/resolve
是 Edge 设备回调端点,无法携带登录凭证,需免鉴权。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:18:32 +08:00
8982e7e9b5 feat(aiot): 新增 Edge 告警上报和 resolve HTTP 端点
- POST /api/ai/alert/edge/report: 接收 Edge 告警,映射字段后入库
- POST /api/ai/alert/edge/resolve: 接收告警结束事件,更新持续时长
- AiAlertMapper 新增 updateDuration 方法

解决 Edge alarm_upload_worker 无法上报告警的问题。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:58:22 +08:00
d3c400de64 feat(aiot): 截图请求携带 rtsp_url,支持无 ROI 摄像头按需截图
截图 XADD 到 Redis Stream 时,通过 StreamProxyMapper 查询摄像头的
rtsp_url 并附带到请求中,供 Edge 对无 ROI(无常驻流)的摄像头
临时连接 RTSP 抓帧,解决"先截图才能画 ROI"的鸡生蛋问题。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:38:51 +08:00
2a8e9c7b82 feat(aiot): 启动时自动回填 camera_code 并修复 ROI 旧格式引用
解决 stream_proxy 表 camera_code 为 NULL 导致配置推送时跳过摄像头的问题:
- @PostConstruct 启动时自动为 camera_code 为空的记录生成 cam_xxx 编码
- 自动将 ROI 表中 app/stream 格式的 camera_id 替换为对应的 camera_code
- StreamProxyMapper 新增 selectWithNullCameraCode/updateCameraCode 方法
- AiRoiMapper 新增 updateCameraId/queryWithLegacyCameraId 方法

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:16:03 +08:00
6f61b0c9bf fix(aiot): 修复配置推送 rtsp_url 为空的问题
- selectByCameraCode 返回 null 时跳过该摄像头,不再推送空 rtsp_url
- ZLM 回退 URL 改用 proxy 的 app/stream 构建,修复原先用 camera_code 格式导致的无效路径
- 行为与 buildPayloadFromFlat (HTTP推送) 保持一致

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:58:56 +08:00
28692d10a5 fix: 配置推送时增强 rtsp_url 日志和校验
当摄像头没有有效的 RTSP 地址时:
1. 添加详细的警告日志,说明可能的原因(stream_proxy 表或媒体服务器配置)
2. 添加 rtsp_url_valid 标志位,方便 Edge 端调试

这有助于排查为什么推送配置后 Edge 无法连接视频流。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:22:06 +08:00
d2434927fe fix: PostConstruct 导入改为 jakarta.annotation(Java 17+)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:14:31 +08:00
be6d1c74de fix: 启动时统一 ROI 表 device_id,解决配置推送不到 Edge 的问题
添加 @PostConstruct normalizeDeviceIds(),WVP 启动时自动将所有 ROI
的 device_id 统一为默认边缘设备 ID,确保 writeDeviceAggregatedConfig
能正确查询到关联摄像头,Redis key 和 Stream 事件的 device_id 与 Edge
端 EDGE_DEVICE_ID 一致。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:05:51 +08:00
98ffac671c fix(aiot): pushConfig增加device_id回退逻辑,修复配置推送不到达Edge
问题:ROI表device_id为空时,writeDeviceAggregatedConfig被跳过,
Redis Stream事件不发送,Edge永远收不到配置更新,但前端仍显示推送成功。

修复:
- pushConfig/pushAllConfig中device_id为空时回退查询edge设备表,
  再回退到硬编码默认值"edge"
- 返回值新增redis_sync字段,push_status准确反映实际同步结果
- 新增getDefaultDeviceId()方法

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 15:47:58 +08:00
6ca8a38fae fix(aiot): 前端截图刷新添加cache-busting防止浏览器缓存
给COS预签名URL附加_t=timestamp参数,确保每次刷新截图时
浏览器不使用缓存的旧图片。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 15:47:48 +08:00
c586f8e77a fix(aiot): snap端点改用302重定向到COS公共URL
<img>标签请求snap时,直接302重定向到COS公共URL,
浏览器自动跟随重定向加载图片。用sendRedirect绕过
GlobalResponseAdvice的WVPResult包装,避免byte[]类型转换错误。
同时GlobalResponseAdvice增加byte[]排除以防其他场景。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 15:22:53 +08:00
2b0a682b3f fix(aiot): 改用COS公共URL+修复GlobalResponseAdvice排除byte[]
1. requestScreenshot直接返回COS公共URL(不再返回代理路径)
2. GlobalResponseAdvice排除byte[]类型响应,避免图片代理被包装成WVPResult
3. handleCallback先写缓存再complete Future(保留之前的竞态修复)

COS Bucket已开启公有读,无需签名URL,直接用公共地址即可在<img>中显示。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 15:16:29 +08:00
83041e9490 fix(aiot): 修复截图代理两个bug:竞态条件+URL双重编码
1. handleCallback先写Redis缓存再complete Future,
   避免等待线程被唤醒后读取缓存为空的竞态条件
2. RestTemplate使用URI.create()传入预签名URL,
   避免对已编码的%3B等字符做二次编码导致COS 403

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:56:30 +08:00
c932c1c7a2 fix(aiot): snap端点支持图片直接返回,兼容前端<img>标签直接加载
前端将snap API URL直接设为<img src>,浏览器以Accept: image/*请求,
但原接口返回JSON导致图片无法显示。现通过检测Accept头自动判断:
- image/*请求:触发截图后直接返回JPEG字节流
- JSON请求:返回原有JSON格式

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:38:15 +08:00
b47d01fc30 feat(aiot): 截图图片改为WVP服务端代理,解决浏览器直连COS跨域问题
前端<img>直接加载COS预签名URL会遇到ERR_CONNECTION_CLOSED,
改为WVP服务端代理:新增/api/ai/roi/snap/image端点,
WVP从Redis读取缓存的COS URL后在服务端下载图片返回给前端,
前端只做同源请求,彻底避免CORS问题。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:22:53 +08:00
4aae7ee459 fix(aiot): pushAllConfig补充Redis聚合配置写入+修正截图回调地址
pushAllConfig原来只做HTTP推送,不写Redis,导致Edge在
CONFIG_SYNC_MODE=REDIS模式下无法通过Stream接收全量配置。
现在推送后对每个deviceId调用writeDeviceAggregatedConfig,
写入device:{id}:config并发布device_config_stream事件。
同时修正application-dev.yml中截图回调地址。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 11:31:05 +08:00
f9bf85f9fa fix: 截图回调接口加入鉴权白名单 2026-02-28 10:11:35 +08:00
19aa6971d5 feat: 截图响应改为HTTP回调 2026-02-28 10:02:55 +08:00
3a601b37e6 feat(aiot): Edge截图方案替代ZLM截图,支持COS URL返回
- 新增 IAiScreenshotService 接口和实现:通过 Redis Stream 请求 Edge
  截图,轮询等待结果,支持 5 分钟缓存和 force 刷新
- AiRoiController.getSnap() 从 ZLM 二进制截图改为返回 JSON(含 COS URL)
- 前端 aiRoi.js 新增 getSnapUrl 方法
- roiConfig.vue 改为异步加载截图,增加 loading 状态和错误提示

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:25:32 +08:00
152af7ec90 fix(stream-proxy): 修复int类型比较错误,使用!=替代equals 2026-02-25 14:35:48 +08:00
e06f851561 fix(aiot): 删除updateAlgoParams方法中的重复代码片段 2026-02-25 14:34:48 +08:00
1ff341a676 feat(stream-proxy): 摄像头列表按应用名+流ID排序,同应用分组显示 2026-02-25 14:20:52 +08:00
933a585242 feat(stream-proxy): 添加应用名修改时的唯一性验证
修改内容:
- update() 方法中添加 app+stream 唯一性检查
- 检测用户是否修改了 app 或 stream 字段
- 如果修改后与其他记录冲突,抛出友好的错误提示
- 错误消息:"应用名 [xxx] 下的流ID [yyy] 已存在"

场景示例:
原记录:大堂/001
用户修改为:停车场/001
系统检查:停车场下是否已有 001
- 如果已存在 → 抛出错误提示
- 如果不存在 → 允许修改

防止问题:
- 避免修改应用名后产生重复的 app+stream 组合
- 保持数据库唯一约束的完整性
- 提供清晰的用户反馈
2026-02-25 13:50:24 +08:00
8a540d59ba fix(aiot): 修复自动推送参数错误 - 使用deviceId而不是cameraId
问题:
- 自动推送配置时传入错误的参数:cameraId(如:cam_xxx)
- 但 writeDeviceAggregatedConfig() 期望的是 deviceId(如:edge-001)
- 导致Edge端收不到配置更新通知,仍然显示"有ROI但未找到配置"

根本原因:
- writeDeviceAggregatedConfig(deviceId, action) 方法:
  - 参数deviceId指的是Edge设备ID(edge-001)
  - 通过deviceId查询该设备下的所有摄像头
  - 发送Redis Stream通知:device_id=deviceId
- Edge端监听 device_id="edge-001" 的消息
- 但我们传入的是 cameraId="cam_xxx",导致通知发送到错误的频道

错误调用链:
save() → writeDeviceAggregatedConfig(cameraId, "UPDATE") 
       → Redis Stream: device_id="cam_xxx" 
       → Edge监听 device_id="edge-001"  收不到!

修复方案:
- 所有自动推送调用改为使用 roi.getDeviceId()
- 修复的方法:save(), delete(), bindAlgo(), unbindAlgo(), updateAlgoParams()
- 添加device_id为空的警告日志
- 日志中同时显示camera_id和device_id,便于调试

正确调用链:
save() → writeDeviceAggregatedConfig(deviceId, "UPDATE") 
       → Redis Stream: device_id="edge-001" 
       → Edge监听 device_id="edge-001"  正常接收!

影响:
- 现在自动推送会正确工作,无需手动推送
- Edge端能实时接收配置更新
- 新增/修改ROI后立即生效
2026-02-25 13:39:35 +08:00
4dff9b58f5 fix(stream-proxy): 保留用户输入的应用名,不强制覆盖为camera_code
问题:
- 新增摄像头时,应用名列显示为 camera_code(如:cam_dfc6e351b486)
- 而不是用户输入的应用名(如:大堂、停车场)

根本原因:
- StreamProxyServiceImpl.add() 方法中,第168行强制覆盖了用户输入
- streamProxy.setApp(cameraCode) 将用户输入的app替换为自动生成的cameraCode

修复方案:
- 删除强制覆盖逻辑,保留用户输入的应用名
- camera_code 和 app 各司其职:
  - camera_code: 系统内部唯一标识(ROI关联)
  - app: 用户可读的场景名(大堂、停车场、入口等)

影响:
- 用户输入的应用名现在会正确保存和显示
- 不影响 camera_code 的生成和使用
- app/stream 组合唯一约束依然有效
2026-02-25 13:31:23 +08:00