/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}
摘要:算法能跑通,只完成了 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+,交付给客户却换来一句"我看不懂这个界面"。问题通常不在算法,而在信息组织的三层断裂:
所以前端要解决的是三件事:降噪(把 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 个能直接驱动动作的指标:

| 接入路数 | 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;}
几个工程经验:
右侧 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,前端的所有筛选、漏斗、闭环率都从这几个字段算出来,别让前端做二次推断。
七、踩过的坑与优化建议
八、总结
这套控制台的核心不是"好看",而是把 AI 视觉项目里最容易被忽略的三件事做扎实:
- 降噪:342 条原始事件 → 27 条待处置,让值班的人有精力处理;
- 留证:标注帧 / 原始帧 / 短视频 + 结构化信息 + 闭环时间线,形成可审计的证据链;
- 回溯:以文搜图把"翻录像几小时"压缩成"一句话几秒钟"。
技术上,纯 HTML/CSS/JS + CSS 变量 + SVG 手绘图表,零依赖、单文件、可离线,既适合快速做方案评审,也能作为生产项目的前端骨架直接长上去。
后续可扩展:① 接入真实 WebRTC 流与 PTZ 控制协议;② 事件地图(GIS 一张图)与点位的空间联动;③ 模型效果评测页(漏报/误报回流与版本对比);④ 任务布防的时段化策略(白天/夜间/节假日不同算法)。
如果这篇对你有帮助,欢迎点赞 + 收藏 + 关注。你在做视觉平台时遇到过哪些"算法很强但界面没人用"的场景?评论区聊聊,我把典型问题整理成续篇。
如果对您有所帮助,请点赞打赏支持!
技术合作交流q+++q:2401315930
最后分享一下地图下载器设计及下载地址:
链接:https://pan.baidu.com/s/1RZX7JpTpxES-G7GiaVUxOw 提取码:61cn
地图下载器代码结构设计及功能实现_地图下载管理器解析-CSDN博客





