Files
yolo/frontend/index.html

180 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#0b1117" />
<title>燧安 · 火灾预防管理平台</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div class="platform-shell">
<aside class="sidebar" id="sidebar">
<div class="brand">
<div class="brand-mark" aria-hidden="true"></div>
<div>
<strong>燧安</strong>
<span>火灾预防管理平台</span>
</div>
</div>
<nav class="main-nav" aria-label="主导航">
<button class="nav-item is-active" type="button" data-view="overview"><span class="nav-icon"></span><span>系统总览</span></button>
<button class="nav-item" type="button" data-view="inspection"><span class="nav-icon"></span><span>视频巡检</span></button>
<button class="nav-item" type="button" data-view="events"><span class="nav-icon">!</span><span>告警中心</span><span class="nav-count" id="pendingNavCount">0</span></button>
<button class="nav-item" type="button" data-view="risks"><span class="nav-icon"></span><span>风险台账</span></button>
<button class="nav-item" type="button" data-view="channels"><span class="nav-icon"></span><span>通知通道</span></button>
<button class="nav-item" type="button" data-view="settings"><span class="nav-icon"></span><span>系统设置</span></button>
</nav>
<div class="sidebar-footer">
<div class="system-indicator"><span id="sidebarStatusDot" class="status-dot"></span><div><strong id="sidebarStatus">连接中</strong><span>智能视觉预警服务</span></div></div>
<span class="version">YOLO11S · v0.1.0</span>
</div>
</aside>
<main class="main-area">
<header class="topbar">
<div class="topbar-left">
<button id="menuButton" class="icon-button menu-button" type="button" aria-label="展开导航"></button>
<div>
<p class="breadcrumb">消防安全 / <span id="viewBreadcrumb">系统总览</span></p>
<h1 id="viewTitle">系统总览</h1>
</div>
</div>
<div class="topbar-actions">
<div class="clock-block"><span>当前时间</span><strong id="currentClock">--:--:--</strong></div>
<span id="globalStatus" class="status-chip status-checking">服务检查中</span>
<button class="icon-button" type="button" data-view-jump="events" aria-label="查看告警"><span id="notificationDot" class="notification-dot" hidden></span></button>
</div>
</header>
<div class="content-area">
<section class="view is-active" id="view-overview" data-view-panel="overview">
<div class="hero-strip">
<div>
<p class="section-kicker">FIRE PREVENTION COMMAND CENTER</p>
<h2>今日消防安全态势</h2>
<p id="overviewMessage">正在汇总模型、告警与通知通道状态。</p>
</div>
<button class="primary-button" type="button" data-view-jump="inspection">开始视频巡检</button>
</div>
<div class="stat-grid">
<article class="stat-card"><div class="stat-head"><span>今日告警</span><span class="stat-symbol warning">!</span></div><strong id="todayEventCount">0</strong><small>系统产生的有效告警事件</small></article>
<article class="stat-card"><div class="stat-head"><span>待处置事件</span><span class="stat-symbol danger"></span></div><strong id="pendingEventCount">0</strong><small>需要值班人员确认处理</small></article>
<article class="stat-card"><div class="stat-head"><span>模型状态</span><span class="stat-symbol success"></span></div><strong id="modelStatusValue" class="text-value">检查中</strong><small id="modelStatusDetail">正在读取权重状态</small></article>
<article class="stat-card"><div class="stat-head"><span>通知通道</span><span class="stat-symbol info"></span></div><strong id="channelCount">0</strong><small id="channelSummary">尚未启用机器人</small></article>
</div>
<div class="overview-grid">
<article class="panel trend-panel">
<div class="panel-header"><div><p class="section-kicker">ALERT TREND</p><h3>近期告警趋势</h3></div><div class="legend"><span><i class="legend-fire"></i>火焰</span><span><i class="legend-smoke"></i>烟雾</span></div></div>
<div id="trendChart" class="trend-chart" role="img" aria-label="近期火焰和烟雾告警趋势"></div>
</article>
<article class="panel readiness-panel">
<div class="panel-header"><div><p class="section-kicker">SYSTEM READINESS</p><h3>系统就绪度</h3></div></div>
<div class="readiness-list">
<div class="readiness-item"><span>模型权重</span><strong id="readyWeights">检查中</strong></div>
<div class="readiness-item"><span>检测服务</span><strong id="readyApi">检查中</strong></div>
<div class="readiness-item"><span>企业微信</span><strong id="readyWechat">未配置</strong></div>
<div class="readiness-item"><span>飞书机器人</span><strong id="readyFeishu">未配置</strong></div>
</div>
</article>
</div>
<article class="panel recent-panel">
<div class="panel-header"><div><p class="section-kicker">RECENT EVENTS</p><h3>最近告警事件</h3></div><button class="text-button" type="button" data-view-jump="events">查看全部 →</button></div>
<div id="recentEventList" class="event-list empty-list"><p>暂无告警事件。开始视频巡检后,满足连续帧条件的告警会显示在这里。</p></div>
</article>
</section>
<section class="view" id="view-inspection" data-view-panel="inspection">
<div class="page-intro"><div><p class="section-kicker">VIDEO INSPECTION</p><h2>智能视频巡检</h2><p>选择本地监控视频,系统将按设定间隔抽帧并进行烟雾、火焰识别。</p></div><span id="inspectionStatus" class="status-chip status-idle">等待视频</span></div>
<div class="inspection-grid">
<article class="panel video-panel">
<div class="video-toolbar"><div><strong id="sourceLabel">未选择视频</strong><span id="videoMeta">支持 MP4、WebM 等浏览器可播放格式</span></div><span id="videoClock">00:00 / 00:00</span></div>
<div class="media-stage">
<video id="videoPreview" controls muted playsinline hidden></video>
<div id="emptyState" class="empty-state"><div class="upload-emblem"></div><strong>导入监控视频</strong><span>视频在浏览器本地播放,仅将抽取帧发送至检测服务</span></div>
<canvas id="overlayCanvas" aria-hidden="true"></canvas>
<div id="loadingState" class="loading-state" hidden><span class="spinner"></span>正在分析视频帧</div>
</div>
<div class="video-actions">
<label class="file-button"><input id="videoInput" type="file" accept="video/*" /><span>选择视频</span></label>
<button id="runDetectionButton" class="primary-button" type="button" disabled>开始连续检测</button>
<button id="clearButton" class="secondary-button" type="button">清除</button>
</div>
</article>
<div class="inspection-side">
<article class="panel detection-summary">
<div class="panel-header"><div><p class="section-kicker">LIVE RESULT</p><h3>实时检测摘要</h3></div><span id="lastUpdated" class="micro-copy">尚未检测</span></div>
<div class="detection-metrics">
<div><span>烟雾目标</span><strong id="smokeCount">0</strong></div>
<div><span>火焰目标</span><strong id="fireCount">0</strong></div>
<div><span>最高置信度</span><strong id="maxConfidence">--</strong></div>
<div><span>风险等级</span><strong id="riskStatus">待机</strong></div>
</div>
<div id="alertStatus" class="alert-status">机器人告警状态:检查中</div>
<div id="detectionList" class="detection-list"><p class="empty-copy">暂无检测结果</p></div>
</article>
<article class="panel inspection-settings">
<div class="panel-header"><div><p class="section-kicker">STRATEGY</p><h3>巡检策略</h3></div></div>
<label class="field-row"><span>检测间隔</span><select id="intervalSelect"><option value="500">0.5 秒</option><option value="1000" selected>1 秒</option><option value="2000">2 秒</option></select></label>
<div class="strategy-row"><span>连续确认帧</span><strong id="confirmFramesValue">3 帧</strong></div>
<div class="strategy-row"><span>告警冷却</span><strong id="cooldownValue">60 秒</strong></div>
<div class="strategy-note">连续检测到目标后才会生成告警事件,并按火焰、烟雾分别执行冷却。</div>
</article>
</div>
</div>
</section>
<section class="view" id="view-events" data-view-panel="events">
<div class="page-intro"><div><p class="section-kicker">ALERT CENTER</p><h2>告警事件管理</h2><p>集中查看、确认和关闭视频巡检产生的火灾风险事件。</p></div><button id="refreshEventsButton" class="secondary-button" type="button">刷新事件</button></div>
<div class="event-stat-row"><div><span>全部事件</span><strong id="allEventsCount">0</strong></div><div><span>待处置</span><strong id="pendingEventsCount">0</strong></div><div><span>已确认</span><strong id="ackEventsCount">0</strong></div><div><span>已解决</span><strong id="resolvedEventsCount">0</strong></div></div>
<article class="panel event-table-panel">
<div class="table-toolbar"><div class="filter-group" role="group" aria-label="事件状态筛选"><button type="button" class="filter-button is-active" data-event-filter="">全部</button><button type="button" class="filter-button" data-event-filter="pending">待处置</button><button type="button" class="filter-button" data-event-filter="acknowledged">已确认</button><button type="button" class="filter-button" data-event-filter="resolved">已解决</button></div><span id="eventTableMeta">0 条记录</span></div>
<div class="table-wrap"><table class="event-table"><thead><tr><th>事件编号</th><th>时间</th><th>类型</th><th>置信度</th><th>通知通道</th><th>状态</th><th>操作</th></tr></thead><tbody id="eventTableBody"><tr><td colspan="7" class="empty-cell">暂无告警事件</td></tr></tbody></table></div>
</article>
</section>
<section class="view" id="view-risks" data-view-panel="risks">
<div class="page-intro"><div><p class="section-kicker">RISK REGISTER</p><h2>风险台账</h2><p>从模型阈值、告警策略和处置状态评估当前风险治理情况。</p></div></div>
<div class="risk-grid">
<article class="panel risk-card"><span class="risk-level high">高风险</span><h3>未处置告警事件</h3><strong id="riskPendingValue">0</strong><p>待值班人员确认的火焰或烟雾事件。</p><button class="text-button" type="button" data-view-jump="events">进入告警中心 →</button></article>
<article class="panel risk-card"><span class="risk-level medium">策略风险</span><h3>告警通知覆盖</h3><strong id="riskChannelValue">0 / 2</strong><p>建议至少启用一个机器人通知通道。</p><button class="text-button" type="button" data-view-jump="channels">检查通知通道 →</button></article>
<article class="panel risk-card"><span class="risk-level low">模型策略</span><h3>检测置信度阈值</h3><strong id="riskConfidenceValue">--</strong><p>阈值过低会增加误报,过高可能遗漏早期烟雾。</p><button class="text-button" type="button" data-view-jump="settings">查看系统参数 →</button></article>
</div>
<article class="panel checklist-panel"><div class="panel-header"><div><p class="section-kicker">PREVENTION CHECKLIST</p><h3>火灾预防工作清单</h3></div></div><div class="checklist"><label><input type="checkbox" />视频监控覆盖重点区域</label><label><input type="checkbox" />告警机器人可正常接收消息</label><label><input type="checkbox" />值班人员明确事件处置流程</label><label><input type="checkbox" />模型权重与阈值定期复核</label><label><input type="checkbox" />消防通道和设备状态已巡查</label><label><input type="checkbox" />告警事件完成闭环记录</label></div></article>
</section>
<section class="view" id="view-channels" data-view-panel="channels">
<div class="page-intro"><div><p class="section-kicker">NOTIFICATION CHANNELS</p><h2>通知通道</h2><p>管理告警触达方式。敏感凭据保存在服务端本地环境文件中。</p></div></div>
<div class="channel-grid">
<article class="panel channel-card"><div class="channel-logo wechat-logo"></div><div class="channel-content"><div><h3>企业微信群机器人</h3><span id="wechatChannelBadge" class="channel-badge">未配置</span></div><p>告警时发送 Markdown 消息与带检测框截图。</p><code>WECHAT_WEBHOOK_URL</code></div></article>
<article class="panel channel-card"><div class="channel-logo feishu-logo"></div><div class="channel-content"><div><h3>飞书自定义机器人</h3><span id="feishuChannelBadge" class="channel-badge">未配置</span></div><p>告警时发送红色交互卡片,支持签名校验。</p><code>FEISHU_WEBHOOK_URL / FEISHU_SECRET</code></div></article>
</div>
<article class="panel config-guide"><div class="panel-header"><div><p class="section-kicker">CONFIGURATION</p><h3>配置说明</h3></div></div><ol><li>在企业微信或飞书群中添加自定义机器人并复制 Webhook。</li><li>将 Webhook 填入项目根目录 <code>.env</code> 对应字段。</li><li>飞书开启签名校验时,同时填写 <code>FEISHU_SECRET</code></li><li>重启后端服务,平台将自动显示通道启用状态。</li></ol></article>
</section>
<section class="view" id="view-settings" data-view-panel="settings">
<div class="page-intro"><div><p class="section-kicker">SYSTEM SETTINGS</p><h2>系统设置</h2><p>查看当前生效的模型和告警参数。配置修改后需重启服务。</p></div></div>
<div class="settings-grid">
<article class="panel settings-card"><div class="panel-header"><div><p class="section-kicker">MODEL</p><h3>模型配置</h3></div></div><dl><div><dt>权重文件</dt><dd id="settingWeights">--</dd></div><div><dt>输入尺寸</dt><dd id="settingImageSize">--</dd></div><div><dt>置信度阈值</dt><dd id="settingConfidence">--</dd></div><div><dt>IOU 阈值</dt><dd id="settingIou">--</dd></div></dl></article>
<article class="panel settings-card"><div class="panel-header"><div><p class="section-kicker">ALERT POLICY</p><h3>告警策略</h3></div></div><dl><div><dt>连续确认</dt><dd id="settingConfirmFrames">--</dd></div><div><dt>分类冷却</dt><dd id="settingCooldown">--</dd></div><div><dt>事件存储</dt><dd>进程内最近 500 条</dd></div><div><dt>视频处理</dt><dd>浏览器本地抽帧</dd></div></dl></article>
</div>
<article class="panel env-panel"><div class="panel-header"><div><p class="section-kicker">ENVIRONMENT</p><h3>环境变量参考</h3></div></div><pre><code>YOLO_WEIGHTS=...
YOLO_DEVICE=0
YOLO_IMGSZ=768
YOLO_CONF=0.40
YOLO_IOU=0.45
ALERT_CONFIRM_FRAMES=3
ALERT_COOLDOWN_SECONDS=60</code></pre></article>
</section>
</div>
</main>
</div>
<div id="toastRegion" class="toast-region" aria-live="polite"></div>
<script src="./app.js" type="module"></script>
</body>
</html>