2026-10-03 16:12:25 +08:00
<!doctype html>
< html lang = "zh-CN" >
< head >
< meta charset = "utf-8" >< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< title > 赵府智家 · 视觉</ title >< link rel = "stylesheet" href = "/style.css" >
< script defer src = "/vendor/hls.min.js" ></ script >< script defer src = "/app.js" ></ script >
</ head >
< body >
< aside class = "sidebar" >
< a class = "brand" href = "/" >< span class = "brand-icon" > ◉</ span >< span > 赵府智家< small > VISION / 本地视觉系统</ small ></ span ></ a >
< div class = "nav-label" > 工作空间</ div >
< nav aria-label = "主导航" >
< button data-page = "live" class = "active" > ◫ < span > 实时画面</ span ></ button >
< button data-page = "playback" > ◷ < span > 录像回放</ span ></ button >
< button data-page = "objects" > ▣ < span > 摄像头对象</ span ></ button >< button data-page = "recorders" > ▤ < span > 录像机</ span ></ button >< button data-page = "cameras" > ◫ < span > 镜头通道</ span ></ button >
< button data-page = "sites" > ⌂ < span > 空间档案</ span ></ button >
< button data-page = "storage" > ▤ < span > 录像与存储</ span ></ button >
</ nav >
< div class = "side-note" >< span class = "dot" ></ span > 自有部署 · 本地存储< p > 按空间组织画面< br > 让每一段记录有处可寻</ p ></ div >
< button id = "logout" class = "quiet" > 退出登录</ button >
</ aside >
< main >
< header >< div >< div class = "eyebrow" > ZHAOFU HOME / VISION</ div >< h1 id = "page-title" > 实时画面</ h1 >< p id = "page-note" > 从一个空间,看到每一个位置。</ p ></ div >< div class = "header-status" >< span id = "service-status" class = "badge" > 等待连接</ span >< span id = "clock" ></ span ></ div ></ header >
< div id = "banner" class = "banner" hidden ></ div >
< section class = "metrics" >< div >< span > 摄像头</ span >< strong id = "metric-all" > —</ strong ></ div >< div >< span > 已接通码流</ span >< strong id = "metric-ready" > —</ strong ></ div >< div >< span > 录像占用</ span >< strong id = "metric-used" > —</ strong ></ div >< div >< span > 空间档案</ span >< strong id = "metric-sites" > —</ strong ></ div ></ section >
< div class = "filter-row" >< label > 空间范围 < select id = "site-filter" >< option value = "" > 全部空间</ option ></ select ></ label >< span id = "filter-caption" > 家庭与公司,分别管理</ span >< button id = "refresh" class = "quiet" > ↻ 刷新状态</ button ></ div >
2026-10-03 16:49:48 +08:00
< section id = "page-live" class = "page" >< div class = "section-head" >< h2 > 现场画面 < small > LIVE VIEW</ small ></ h2 >< div >< label > 清晰度 < select id = "quality" >< option value = "compat" > 兼容 · 流畅画面</ option >< option value = "sub" > 原始 · 子码流</ option >< option value = "main" > 清晰 · 主码流</ option ></ select ></ label >< button data-action = "new-camera" > + 添加镜头通道</ button ></ div ></ div >< div id = "live-grid" class = "live-grid" ></ div ></ section >
2026-10-03 16:12:25 +08:00
< section id = "page-playback" class = "page" hidden >
< div class = "section-head" >< h2 > 回到那一刻 < small > PLAYBACK</ small ></ h2 ></ div >
< div class = "panel playback-controls" >< label > 摄像头< select id = "play-camera" ></ select ></ label >< label > 录像来源< select id = "archive-source" >< option value = "recorder" > 录像机原有录像</ option >< option value = "local" > 小电脑本机录像</ option ></ select ></ label >< label > 日期< input id = "play-date" type = "date" ></ label >< button id = "query-recordings" > 查找录像</ button >< span id = "play-info" > 选择日期,查看实际录像时段</ span ></ div >
< div class = "video-panel" >< video id = "play-video" controls playsinline ></ video >< div id = "play-empty" class = "video-empty" > 选择一个有录像的时间段</ div ></ div >
< div class = "panel" >< div class = "timeline-head" >< strong > 当日时间轴</ strong >< span >< i class = "legend" ></ i > 有录像的时段 · 点击定位</ span ></ div >< canvas id = "timeline" height = "76" aria-label = "录像时间轴" ></ canvas >< div class = "time-labels" >< span > 00:00</ span >< span > 06:00</ span >< span > 12:00</ span >< span > 18:00</ span >< span > 24:00</ span ></ div >< div class = "seek-row" >< label > 定位时间 < input id = "seek-time" type = "time" step = "1" value = "12:00:00" ></ label >< button id = "seek-button" class = "secondary" > 定位播放</ button >< a id = "download" class = "button secondary" hidden > 下载当前片段</ a ></ div ></ div >
< div id = "recording-list" class = "recording-list" ></ div >
</ section >
< section id = "page-cameras" class = "page" hidden >< div class = "section-head" >< h2 > 镜头通道 < small > CHANNELS</ small ></ h2 >< button data-action = "new-camera" > + 添加镜头通道</ button ></ div >< div class = "panel discovery" >< div >< strong > 发现局域网设备</ strong >< p > 探测 RTSP 服务,添加后用设备账号连接。</ p ></ div >< input id = "scan-network" placeholder = "例如 192.168.1.0/24" aria-label = "局域网网段" >< button id = "scan-button" class = "secondary" > 开始探测</ button ></ div >< div id = "scan-result" ></ div >< div id = "camera-list" ></ div ></ section >
< section id = "page-objects" class = "page" hidden >< div class = "section-head" >< h2 > 摄像头对象 < small > CAMERA ASSETS</ small ></ h2 >< button data-action = "new-asset" > + 新建摄像头对象</ button ></ div >< p class = "description" > 一台实体摄像头对应一个对象,双镜头在对象下建立两个镜头通道;每个镜头分别有主码流和子码流。</ p >< div id = "asset-list" class = "site-grid" ></ div ></ section >
< section id = "page-recorders" class = "page" hidden >< div class = "section-head" >< h2 > 录像机 < small > RECORDERS</ small ></ h2 >< button data-action = "new-recorder" > + 添加录像机</ button ></ div >< p class = "description" > 统一保存录像机地址与账号,镜头通道关联录像机。实时取流使用 RTSP;读取录像机已有历史录像,需要该型号的回放接口适配。</ p >< div id = "recorder-list" class = "site-grid" ></ div ></ section >
< section id = "page-sites" class = "page" hidden >< div class = "section-head" >< h2 > 空间档案 < small > PLACES</ small ></ h2 >< button data-action = "new-site" > + 新建空间</ button ></ div >< p class = "description" > 为家庭、公司或其他场所建立地址档案,再关联摄像头。地区、小区、楼栋和门牌都是独立属性。</ p >< div id = "site-list" class = "site-grid" ></ div ></ section >
2026-10-03 16:49:48 +08:00
< section id = "page-storage" class = "page" hidden >< div class = "section-head" >< h2 > 录像与存储 < small > STORAGE</ small ></ h2 ></ div >< div class = "storage-grid" >< form id = "storage-form" class = "panel" >< h3 > 录像保留策略</ h3 >< label > 保留天数< input name = "retentionDays" type = "number" min = "1" max = "365" required ></ label >< label > 录像容量上限(GB) < input name = "maxGB" type = "number" min = "5" max = "100000" required ></ label >< label > 磁盘预留空间(GB) < input name = "reserveGB" type = "number" min = "2" max = "1000" required ></ label >< p class = "description" > 超过保留天数的录像会自动删除。达到容量上限或预留空间不足时暂停录像;调整策略后自动恢复。容量每 20 秒检查一次,可能有少量超出。</ p >< button type = "submit" > 保存策略</ button >< span class = "form-error" ></ span ></ form >< div class = "panel" >< h3 > 运行状态</ h3 >< dl id = "storage-status" ></ dl >< p class = "description" > 开启摄像头的“持续录像”后,服务会保存主码流。预览默认使用 H.264 兼容画面(最高 768×432、10 帧/秒)。原始码流与本机录像保留设备编码。</ p >< h3 > 最近操作</ h3 >< div id = "audit-list" ></ div ></ div ></ div ></ section >
2026-10-03 16:12:25 +08:00
< footer >< span > 赵府智家 · 视觉系统</ span >< span id = "version" > 独立部署 / 数据自有</ span ></ footer >
</ main >
< dialog id = "auth-dialog" >< form id = "auth-form" >< span class = "eyebrow" > WELCOME HOME</ span >< h2 id = "auth-title" > 欢迎回来</ h2 >< p id = "auth-note" > 输入管理密码,进入视觉工作空间。</ p >< label id = "setup-code-label" hidden > 初始化码< input name = "code" autocomplete = "off" ></ label >< label > 管理员密码< input name = "password" type = "password" minlength = "10" maxlength = "128" required autocomplete = "current-password" ></ label >< p class = "form-error" ></ p >< button type = "submit" class = "wide" > 进入系统</ button ></ form ></ dialog >
< dialog id = "site-dialog" >< form id = "site-form" >< div class = "dialog-heading" >< h2 > 空间档案</ h2 >< button type = "button" class = "quiet" data-close = "site-dialog" > 关闭</ button ></ div >< input name = "id" type = "hidden" >< div class = "form-grid" >< label > 空间名称 *< input name = "name" required maxlength = "100" placeholder = "例如:莱阳老家" ></ label >< label > 用途< select name = "kind" >< option value = "home" > 家庭</ option >< option value = "company" > 公司</ option >< option value = "other" > 其他</ option ></ select ></ label >< label > 所属家庭 / 单位< input name = "owner" maxlength = "100" ></ label >< label > 省 / 直辖市< input name = "province" maxlength = "100" ></ label >< label > 城市< input name = "city" maxlength = "100" ></ label >< label > 区 / 县< input name = "district" maxlength = "100" ></ label >< label > 街道 / 乡镇< input name = "street" maxlength = "100" ></ label >< label > 小区 / 园区 / 村< input name = "community" maxlength = "100" ></ label >< label > 楼栋< input name = "building" maxlength = "100" placeholder = "例如:3 号楼" ></ label >< label > 单元< input name = "unit" maxlength = "100" ></ label >< label > 楼层< input name = "floor" maxlength = "100" ></ label >< label > 门牌号< input name = "door" maxlength = "100" placeholder = "例如:502" ></ label >< label class = "full" > 详细地址< input name = "address" maxlength = "240" ></ label >< label class = "full" > 备注< input name = "note" maxlength = "240" ></ label ></ div >< p class = "form-error" ></ p >< div class = "dialog-footer" >< button type = "submit" > 保存空间</ button ></ div ></ form ></ dialog >
2026-10-03 16:16:23 +08:00
< dialog id = "camera-dialog" >< form id = "camera-form" >< div class = "dialog-heading" >< h2 > 镜头通道配置</ h2 >< button type = "button" class = "quiet" data-close = "camera-dialog" > 关闭</ button ></ div >< input name = "id" type = "hidden" >< div class = "form-grid" >< label class = "full" > 所属摄像头对象 *< select name = "assetId" required ></ select ></ label >< label > 接入方式< select name = "sourceKind" >< option value = "recorder" > 通过录像机</ option >< option value = "direct" > 直接连接摄像头</ option ></ select ></ label >< label > 关联录像机< select name = "recorderId" >< option value = "" > 请选择</ option ></ select ></ label >< label > 录像机通道编号< input name = "channelNumber" maxlength = "30" placeholder = "按录像机实际通道填写" ></ label >< label > 录像存储设备< select name = "archiveRecorderId" >< option value = "" > 尚未绑定</ option ></ select ></ label >< label > 历史录像主要保存于< select name = "archiveSource" >< option value = "recorder" > 录像机</ option >< option value = "local" > 本机</ option ></ select ></ label >< label > 镜头 / 通道名称 *< input name = "name" required maxlength = "120" placeholder = "例如:大门口" ></ label >< label > 所属空间 *< select name = "siteId" required ></ select ></ label >< label > 安装位置< input name = "point" maxlength = "120" placeholder = "例如:院门外侧" ></ label >< label > 品牌 / 型号< input name = "model" maxlength = "120" ></ label >< label > 设备 IP *< input name = "host" required placeholder = "局域网 IPv4 地址" ></ label >< label > RTSP 端口< input name = "port" type = "number" value = "554" min = "1" max = "65535" required ></ label >< label > 设备用户名< input name = "username" maxlength = "120" autocomplete = "off" ></ label >< label > 设备密码< input name = "password" type = "password" maxlength = "256" autocomplete = "new-password" placeholder = "编辑时留空,保留原密码" ></ label >< div class = "full" >< button id = "onvif-read" type = "button" class = "secondary" > 读取 ONVIF 镜头配置</ button >< p class = "description" > 直接接入摄像头时,可读取设备实际提供的媒体配置。默认 ONVIF HTTP 端口为 80。</ p >< div id = "onvif-result" ></ div ></ div >< label class = "full" > 常见码流路径< select id = "path-preset" >< option value = "custom" > 手动填写</ option >< option value = "tplink" > TP-Link 单镜头</ option >< option value = "hikvision" > 海康威视 / 兼容路径 · 通道 1</ option >< option value = "dahua" > 大华 / 兼容路径 · 通道 1</ option ></ select ></ label >< label class = "full" > 主码流路径 *< input name = "mainPath" required maxlength = "500" value = "/stream1" ></ label >< label class = "full" > 子码流路径 *< input name = "subPath" required maxlength = "500" value = "/stream2" ></ label >< label class = "check" >< input name = "enabled" type = "checkbox" checked > 启用连接</ label >< label class = "check" >< input name = "record" type = "checkbox" > 在小电脑额外保存录像(可选)</ label ></ div >< p class = "description" > 账号和密码只保存在本机受限数据目录。RTSP 服务响应代表设备可达,实际码流接通后才显示在线。路径预设需要与设备型号、通道一致。</ p >< p class = "form-error" ></ p >< div class = "dialog-footer" >< button type = "submit" > 保存设备</ button ></ div ></ form ></ dialog >
2026-10-03 16:12:25 +08:00
< dialog id = "asset-dialog" >< form id = "asset-form" >< div class = "dialog-heading" >< h2 > 摄像头对象</ h2 >< button type = "button" class = "quiet" data-close = "asset-dialog" > 关闭</ button ></ div >< input name = "id" type = "hidden" >< div class = "form-grid" >< label > 对象名称 *< input name = "name" required maxlength = "120" placeholder = "例如:院门双镜头摄像头" ></ label >< label > 所属空间 *< select name = "siteId" required ></ select ></ label >< label > 品牌< input name = "brand" maxlength = "120" ></ label >< label > 型号< input name = "model" maxlength = "120" ></ label >< label > 序列号< input name = "serial" maxlength = "120" ></ label >< label > 物理镜头数< input name = "lensCount" type = "number" value = "2" min = "1" max = "16" required ></ label >< label > 安装位置< input name = "point" maxlength = "120" ></ label >< label > 备注< input name = "note" maxlength = "120" ></ label ></ div >< p class = "form-error" ></ p >< div class = "dialog-footer" >< button type = "submit" > 保存对象</ button ></ div ></ form ></ dialog >
< dialog id = "recorder-dialog" >< form id = "recorder-form" >< div class = "dialog-heading" >< h2 > 录像机配置</ h2 >< button type = "button" class = "quiet" data-close = "recorder-dialog" > 关闭</ button ></ div >< input name = "id" type = "hidden" >< div class = "form-grid" >< label > 录像机名称 *< input name = "name" required maxlength = "120" ></ label >< label > 所属空间 *< select name = "siteId" required ></ select ></ label >< label > 品牌< input name = "brand" maxlength = "120" ></ label >< label > 型号< input name = "model" maxlength = "120" ></ label >< label > 录像机 IP *< input name = "host" required ></ label >< label > RTSP 端口< input name = "port" type = "number" value = "554" min = "1" max = "65535" required ></ label >< label > 登录用户名< input name = "username" maxlength = "120" autocomplete = "off" ></ label >< label > 设备密码< input name = "password" type = "password" maxlength = "256" placeholder = "留空保留原密码" autocomplete = "new-password" ></ label >< label class = "full" > 接入驱动< select name = "driver" >< option value = "generic-rtsp" > 通用 RTSP / 手动通道路径</ option >< option value = "hikvision-rtsp" > 海康 / 兼容型号 RTSP 路径</ option >< option value = "tplink-rtsp" > TP-Link RTSP 路径</ option >< option value = "dahua-rtsp" > 大华 / 兼容型号 RTSP 路径</ option ></ select ></ label ></ div >< p class = "description" > 驱动在当前版本提供路径模板。录像机历史录像检索、回放及通道自动导入,需要型号确认后接入,当前尚未实现。</ p >< p class = "form-error" ></ p >< div class = "dialog-footer" >< button type = "submit" > 保存录像机</ button ></ div ></ form ></ dialog >
< div id = "toast" role = "status" hidden ></ div >
</ body >
</ html >