摘要 :算法能跑通,只完成了 AI 视觉项目的 30%;剩下 70% 是「让人看得懂、用得上」。本文用一个可运行的单文件原型,拆解 AI 视觉识别平台的 6 大核心模块------态势总览、实时预览、事件中心、事件详情与处置、证据档案、检索分析,覆盖 KPI 体系、九宫格预览与检测框叠加、事件处置漏斗、合规化证据归档,以及以文搜图的多模态检索。全文零框架依赖,一个
index.html双击即开,所有图表用 CSS/SVG 手绘,代码可直接抄进你的项目。
关键词:AI 视觉 · 视频结构化 · 前端可视化 · 边缘计算 · 以文搜图 · 智慧园区 · 数据大屏
一、先看效果:10 张图速览
整套控制台共 6 个业务页面 + 1 个占位页,全部在同一个 index.html 里切换:
| 模块 | 一句话作用 |
|---|---|
| 态势总览 | 5 个 KPI + 趋势/分布/TOP5/健康度,30 秒判断"今天安不安全" |
| 实时预览 | 1/4/9 分屏 + PTZ 云台 + 检测框/轨迹/ROI 叠加 |
| 事件中心 | 多维筛选 + 事件列表 + 处置漏斗 + 处置效能 |
| 事件详情与处置 | 取证视频三联 + 结构化事件信息 + 闭环流程时间线 |
| 证据档案 | 证据包管理 + 存储策略 + 合规审计 + 导出日志 |
| 检索分析 | 以图搜图 / 以文搜图 / 条件检索,多模态向量检索 |
下面这张是整体分层架构,先看清楚数据从哪来到哪去:

二、为什么"算法跑通了",界面还是没法用?
做过视觉项目的同学都踩过这个坑:模型 mAP 做到 0.9+,交付给客户却换来一句"我看不懂这个界面"。问题通常不在算法,而在信息组织的三层断裂:
- 原始告警太多,没有收敛:1,286 路视频一天产生 342 条事件,不做分级合并,值班人员 10 分钟就麻木了;
- 只有告警,没有证据:安全事件要追责、要保险理赔,缺了原始帧/标注帧/短视频三联,事件就是"死"的;
- 只有查询,没有检索:事后复盘时只知道"大概上午有个穿红马甲的人从北门进去",传统按时间翻录像要翻几个小时。
所以前端要解决的是三件事:降噪(把 342 条压成 27 条待处置)、留证(一次事件一个证据包)、回溯(用一句话把视频捞出来)。下面按模块拆。
三、设计系统:一套 CSS 变量撑起整站
不做设计系统的大屏,改一个颜色要动 200 处。这里把颜色、圆角、阴影、侧边栏宽度全部收敛到 :root,并且语义化命名 (--red 而不是 #DC2626),业务里只写 var(--red),主题切换只要换一层变量:
:root{
--bg:#F5F7FB; --card:#FFFFFF; --border:#EEF1F7;
--primary:#4C6FFF; --primary-soft:#EEF2FF; --primary-line:#DDE5FF;
--purple:#7A5AF8; --purple-soft:#F1ECFF;
--red:#DC2626; --red-soft:#FEECEC;
--orange:#EA580C; --orange-soft:#FFF1E8;
--amber:#D97706; --amber-soft:#FEF3E2;
--green:#16A34A; --green-soft:#E7F6EC;
--text:#1E293B; --text2:#334155; --muted:#64748B; --light:#94A3B8;
--radius:12px; --radius-sm:8px; --radius-pill:999px;
--shadow:0 1px 2px rgba(16,24,40,.04),0 1px 3px rgba(16,24,40,.06);
--nav-w:220px; --topbar-h:64px;
--font:"Noto Sans SC","Microsoft YaHei",-apple-system,sans-serif;
/* 数字单独用等宽字体,KPI 跳动时不会左右抖 */
--num:"Sarasa Gothic SC",ui-monospace,SFMono-Regular,Menlo,monospace;
}
三个值得抄的细节:
-soft配套色 :每个主色都配一个浅色底(--red-soft),标签/图标底色直接用,不用手写rgba();- 数字用等宽字体变量
--num:KPI 每秒刷新时,非等宽字体数字宽度变化会导致整行"呼吸抖动"; - 语义色 = 业务等级 :
--red紧急 /--orange高 /--amber中 /--blue低,代码里不出现"颜色",只出现"等级"。
四、模块拆解
4.1 态势总览:5 个 KPI 定义"今天安不安全"

KPI 不是越多越好,这张卡片组只保留 5 个能直接驱动动作的指标:

| KPI | 值 | 环比 | 为什么是它 |
|---|---|---|---|
| 接入路数 | 1,286 路 | ▲2.3% | 规模底盘,扩容/计费依据 |
| 设备在线率 | 98.6% | ▲0.4% | 低于阈值说明"盲区"出现,算法再准也没用 |
| 今日事件 | 342 | ▼5.1% | 总量趋势,判断整改是否有效 |
| 待处置 | 27 | ▲8 | 唯一需要立刻点进去的数字 |
| 事件闭环率 | 95.2% | ▲1.2% | 考核运营质量,不是考核算法 |
配图区用四象限解决"看趋势 / 看当下 / 看分布 / 看瓶颈":
- 左上 事件趋势·近 7 日(折线 + 实时标记)
- 右上 实时告警流(滚动列表,紧急/高/中/低四级色标)
- 左下 事件类型分布(环形图):未戴安全帽 22%、区域入侵 20%、烟火检测 18%、人员倒地 15%、违章停车 14%、人车计数 11%
- 右下 高发点位 TOP5:2 号车间北门 42 → 园区西路 35 → 周界东 28 → 仓库 A 区 21 → 办公楼前 15
设计要点:TOP5 点位其实是"整改优先级清单"。它和类型分布做交叉分析才有价值------比如"2 号车间北门 + 未戴安全帽"双高,答案不是加摄像头,而是在门口装个语音提示喇叭。
底部再加两块运维视角:算法健康度 (YOLOv8 96% / ByteTrack 92% / 烟火检测 94% / VLM 90% / Grounding DINO 88%)与边缘节点负载表 。节点表里"边缘节点-周界B"是离线状态(CPU/GPU 显示 ---),这种「空值要有专门的占位形态」是很容易被忽略的细节:
<tr>
<td class="id-cell">边缘节点-周界B</td>
<td>10.30.1.11</td>
<td>64</td>
<td>---</td><td>---</td>
<td><span class="tag tag-gray">离线</span></td>
</tr>
4.2 实时预览:九宫格 + 检测框叠加 + PTZ

这是全站技术含量最高的一屏,核心是视频层与算法层的解耦 :<img> 只负责画面,检测框是绝对定位的 <div>,坐标用百分比而不是像素------这样 1 分屏、4 分屏、9 分屏切换时,框不用重算。

<div class="grid9" id="grid9">
<div class="tile">
<img src="assets/cam3.png"/>
<div class="osd-tl">CH03 仓库A区</div>
<div class="osd-time">11:42:10</div>
<!-- 检测框:百分比坐标,跟着容器自适应 -->
<div class="box" style="left:46%;top:30%;width:28%;height:40%;border-color:#EA580C">
<span class="bl" style="background:#EA580C">烟雾 0.88</span>
</div>
</div>
...
</div>
.grid9{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);gap:12px;}
.tile{position:relative;border-radius:9px;overflow:hidden;background:#0B1220;}
.tile img{width:100%;height:100%;object-fit:cover;display:block;}
.tile .osd-tl{position:absolute;top:8px;left:8px;background:rgba(8,12,20,.55);color:#fff;
font-size:11px;padding:3px 7px;border-radius:5px;backdrop-filter:blur(2px);}
.tile .box{position:absolute;border:2px solid;border-radius:3px;}
.tile .box .bl{position:absolute;top:-18px;left:-2px;font-size:10px;font-weight:600;
padding:1px 5px;border-radius:3px;white-space:nowrap;}
几个工程经验:
- OSD 用半透明深色底 +
backdrop-filter:blur,避免白色文字压在亮画面上看不清; - 检测框颜色跟事件等级走,一眼就能在 9 路画面里定位异常(红=紧急、橙=高、琥珀=中、蓝=低);
- 信号丢失要有"空态",而不是破图或黑屏。用统一占位块 + 图标 + 文案,运维才知道是"设备掉线"而不是"页面崩了";
- 右上角叠加快切换开关(检测框 / 轨迹 / ROI / 标签),轨迹密集时一键关掉,性能与可读性都能救回来。
右侧 PTZ 用圆形方向盘(上下左右 + 中间 Home)+ 变倍滑杆,同时展示当前通道的分辨率 2560×1440 / 码率 4.0 Mbps / 帧率 25 fps / 编码 H.265------排查"卡顿是谁的锅"时,这四个数缺一不可。
4.3 事件中心:把 342 条压成 27 条

筛选区给了 5 个维度(关键词 / 时间范围 / 点位 / 类型 / 等级 / 状态),顶部再用 Tab 做频道的快速切换:全部 342 · 待处置 27 · 今日 342 · 误报 19。这里"待处置 27"就是值班人员的真实工作量,也是这一屏唯一需要被点开的入口。
右侧的事件处置漏斗是整个平台最有价值的一张图------它把"算法准不准"和"运营到不到位"分开了:

触发 342 → AI识别 338 → 告警推送 320 → 人工确认 305 → 闭环 290
| 环节 | 损耗 | 暴露的问题 |
|---|---|---|
| 触发 → AI识别 | -4 | 算法侧漏检/去重收敛 |
| AI识别 → 告警推送 | -18 | 推送链路问题(MQTT 掉线、Webhook 超时、免打扰时段) |
| 告警推送 → 人工确认 | -15 | 值班响应问题,人不够或告警太吵 |
| 人工确认 → 闭环 | -15 | 现场处置能力问题 |
注意漏斗旁边那行小字:闭环率 = 已闭环事件 / 全部事件;平均处置时长仅统计已闭环事件 。口径不写清楚,95.2% 这个数就会被误读成"算法准确率 95.2%"。任何比率型指标,都要在界面上写清分母------这是大屏设计中最容易被审计挑出来的问题。
4.4 事件详情与处置:一屏完成"看证据 + 定责任 + 留痕"

点开一条紧急事件,页面要回答三个问题:
① 到底发生了什么? 用「标注帧 / 原始帧 / 短视频」三联视图。标注帧证明算法看到了什么,原始帧保留真实性,短视频呈现过程------三者缺一,证据链就不完整。
② 机器怎么判的? 结构化事件信息表格把"黑盒"摊开:
| 字段 | 值 |
|---|---|
| 事件类型 | 烟火检测 |
| 发生点位 | 仓库A区 |
| 触发时间 | 2026-09-11 11:42:08 |
| 算法模型 | 烟火检测 v3.2 |
| 置信度 | 0.88 |
| 关联设备 | CH03 / 边缘节点-园区A |
| 推送方式 | MQTT + Webhook |
③ 后来怎么样了? 用时间线展示闭环流程(事件触发 → AI 识别与分级 → 告警推送 → 人工确认 → 现场处置 → 闭环归档),未完成节点显式标注"待处理 / 未开始"。底部三个动作按钮:确认有效 / 标记误报 / 派单------"标记误报"必须存在,它是模型迭代的负样本来源(本例当天 19 条误报,误报率 5.6%,全部可回流训练)。
4.5 证据档案:留存策略写进界面

这一屏面向合规与审计。顶部 4 个指标:证据包总数 18,426(本周 +312)、存储总量 6.8 TB、证据完整率 100%、存储可用率 99.98%。
中间把留存与合规策略直接展示,而不是藏在配置里:
| 项 | 值 |
|---|---|
| 原始视频留存 | 90 天 |
| 证据包留存 | 永久 |
| 加密方式 | AES-256 |
| 合规标准 | GB/T 28181 |
| 审计日志 | 已开启 |
右侧两块是审计最关心的:证据构成 (视频 57% / 图片 22% / 结构化 21%,用于容量规划)与导出日志 (谁、什么时候、导了哪个包)。导出是高危操作,必须逐条留痕------EP-20260911-0342 张伟 · 11:50 导出 这种粒度才够。
4.6 检索分析:用一句话把视频捞出来

传统安防检索是"选摄像头 → 拖时间轴 → 人肉看"。多模态向量检索把它变成一句自然语言:
穿红色马甲的作业人员出现在 2 号车间北门
返回按相似度排序的命中片段(共 46 条):0.94 红色马甲 · CH02 2号车间北门 11:39、0.91 红色马甲 · CH02 10:12、0.87 疑似目标 · CH01 09:40、0.83 疑似目标 · CH05 08:55。
右侧把检索参数显式化 :检索方式(以文搜图)、目标描述、范围点位、时间范围、向量模型 VLM-Embed v2 、相似度阈值 0.80。阈值一定要露给用户------它直接决定"宁可漏还是宁可多",是个业务决策而不是技术参数。三种模式(以图搜图 / 以文搜图 / 条件检索)用 Tab 切换,覆盖"我有照片 / 我只记得描述 / 我知道时间和点位"三类场景。
五、关键代码实现
5.1 单页多屏:不用路由库,30 行搞定
所有页面都是 <section class="screen">,用 data-screen 声明目标,切换就是增删一个 .active:
function showScreen(id, name, crumb){
document.querySelectorAll('.screen').forEach(s=>s.classList.remove('active'));
document.getElementById(id).classList.add('active');
document.getElementById('pageTitle').textContent = name;
document.getElementById('crumb').textContent = crumb;
document.querySelectorAll('.nav-item').forEach(n=>n.classList.remove('active'));
var activeNav = document.querySelector('.nav-item[data-screen="'+id+'"]');
if(activeNav) activeNav.classList.add('active');
document.querySelector('.content').scrollTop = 0;
}
document.querySelectorAll('.nav-item').forEach(function(item){
item.addEventListener('click', function(){
var sc = item.getAttribute('data-screen');
if(sc === 'coming'){ /* 建设中模块:复用同一个占位页,只换标题 */ return; }
var titles = {s1:['态势总览','首页 / 态势总览'], s2:['实时预览','首页 / 视频监控 / 实时预览'],
s3:['事件中心','首页 / 事件处置 / 事件中心'], s5:['证据档案','首页 / 事件处置 / 证据档案'],
s6:['检索分析','首页 / 事件处置 / 检索分析']};
showScreen(sc, titles[sc][0], titles[sc][1]);
});
});
好处是:DOM 一次性渲染完,切换零成本、零白屏,非常适合演示与内网部署;后续接真实数据,只要把每个 screen 的渲染函数注册进去即可。
5.2 不引图表库:环形图就是 6 个 <circle>
用 stroke-dasharray + stroke-dashoffset 做扇区,周长 2πr ≈ 289(r=46),每段长度 = 占比 × 289:
<svg viewBox="0 0 120 120" width="120" height="120">
<circle cx="60" cy="60" r="46" fill="none" stroke="#EEF1F7" stroke-width="16"/>
<circle cx="60" cy="60" r="46" fill="none" stroke="#4C6FFF" stroke-width="16"
stroke-dasharray="28 261" stroke-dashoffset="0" transform="rotate(-90 60 60)"/>
<circle cx="60" cy="60" r="46" fill="none" stroke="#EA580C" stroke-width="16"
stroke-dasharray="24 265" stroke-dashoffset="-28" transform="rotate(-90 60 60)"/>
<!-- 后续扇区:dashoffset 累计减去前一段长度 -->
</svg>
漏斗图更省,纯 div + 宽度百分比:
<div class="funnel">
<div class="fn-row"><span class="fn-label">触发</span>
<div class="fn-bar" style="width:100%;background:#4C6FFF">342</div></div>
<div class="fn-row"><span class="fn-label">AI识别</span>
<div class="fn-bar" style="width:90%;background:#5B79F0">338</div></div>
<div class="fn-row"><span class="fn-label">告警推送</span>
<div class="fn-bar" style="width:82%;background:#7A5AF8">320</div></div>
<div class="fn-row"><span class="fn-label">人工确认</span>
<div class="fn-bar" style="width:74%;background:#D97706">305</div></div>
</div>
横向柱状(高发点位 TOP5)与健康度柱状同理,用 .r-track + .r-fill、.h-bar 两层 div。整套控制台零第三方 JS、零 ECharts,首屏无请求、离线可用,内网交付时这一点非常加分。
5.3 状态标签:一套语义色走天下
.tag{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:6px;font-size:11px;font-weight:600;}
.tag-red{background:var(--red-soft);color:var(--red);} /* 紧急 */
.tag-orange{background:var(--orange-soft);color:var(--orange);} /* 高 */
.tag-amber{background:var(--amber-soft);color:var(--amber);} /* 中 */
.tag-blue{background:var(--primary-soft);color:var(--primary);} /* 低 */
.tag-green{background:var(--green-soft);color:var(--green);} /* 已闭环 */
.tag-gray{background:#EEF1F7;color:var(--muted);} /* 离线/失效 */
六、接真实后端:这些口子要提前留好
原型跑的是静态数据,接生产时按下面对齐即可(建议 REST + WebSocket + MQTT 三通道分工):
| 能力 | 建议方案 | 说明 |
|---|---|---|
| 视频流预览 | GB/T 28181 / RTSP → WebRTC 或 HLS | 别直接播 RTSP,浏览器不支持;低延迟用 WebRTC |
| 实时告警流 | WebSocket 推送 | 告警流要求秒级,轮询会拖垮服务端 |
| 事件查询/派单 | REST(GET /events、POST /events/{id}/dispatch) |
筛选条件全部走 query string |
| 设备/节点状态 | REST 轮询 + WebSocket 变更推送 | 心跳 30s,离线判定 3 次丢失 |
| 边缘节点上报 | MQTT(结构化事件 JSON) | 边缘侧弱网,MQTT 比 HTTP 稳 |
| 第三方系统联动 | Webhook | 派单到工单系统、钉钉/企微 |
| 以文搜图 | POST /search/text → 向量库(VLM-Embed v2) |
阈值由前端传入,默认 0.80 |
| 证据包下载 | 带签名的临时 URL | 每次下载写审计日志 |
数据结构上,一条事件建议至少包含:eventId / cameraId / nodeId / type / level / confidence / model / ts / status / evidenceId,前端的所有筛选、漏斗、闭环率都从这几个字段算出来,别让前端做二次推断。
七、踩过的坑与优化建议
- 9 路视频同屏会卡:优先降码率走子码流(主码流 2560×1440 只在 1 分屏时用),非焦点画面降到 10 fps;
- 检测框坐标用百分比而不是像素,否则一分屏/九分屏切换要重算,还容易错位;
- 密集轨迹要能一键关闭:ByteTrack 在人流密集处会画出上百条轨迹,既挡画面又耗 CPU;
- 比率指标必须写清口径,闭环率、准确率、在线率旁边都要有注释行;
- 空态/离线态单独设计,破图和"0"比"------"更容易被误判成系统故障;
- 数字用等宽字体,实时刷新时不抖动;
- 告警分级要能配置:同一个"未戴安全帽"在车间是"中"、在危化品仓库就该是"紧急",等级规则不要写死在前端。
八、总结
这套控制台的核心不是"好看",而是把 AI 视觉项目里最容易被忽略的三件事做扎实:
- 降噪:342 条原始事件 → 27 条待处置,让值班的人有精力处理;
- 留证:标注帧 / 原始帧 / 短视频 + 结构化信息 + 闭环时间线,形成可审计的证据链;
- 回溯:以文搜图把"翻录像几小时"压缩成"一句话几秒钟"。
技术上,纯 HTML/CSS/JS + CSS 变量 + SVG 手绘图表,零依赖、单文件、可离线,既适合快速做方案评审,也能作为生产项目的前端骨架直接长上去。
后续可扩展:① 接入真实 WebRTC 流与 PTZ 控制协议;② 事件地图(GIS 一张图)与点位的空间联动;③ 模型效果评测页(漏报/误报回流与版本对比);④ 任务布防的时段化策略(白天/夜间/节假日不同算法)。
如果这篇对你有帮助,欢迎点赞 + 收藏 + 关注。你在做视觉平台时遇到过哪些"算法很强但界面没人用"的场景?评论区聊聊,我把典型问题整理成续篇。
如果对您有所帮助,请点赞打赏支持!
技术合作交流q+++q:2401315930
最后分享一下地图下载器设计及下载地址:
链接:https://pan.baidu.com/s/1RZX7JpTpxES-G7GiaVUxOw
提取码:61cn
地图下载器代码结构设计及功能实现_地图下载管理器解析-CSDN博客



