227 lines
12 KiB
HTML
227 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>CoRE.Vision — Настройки</title>
|
||
<link rel="stylesheet" href="/static/style.css">
|
||
</head>
|
||
<body data-page="settings">
|
||
<header>
|
||
<div class="brand">CoRE<span>.Vision</span></div>
|
||
<div class="spacer"></div>
|
||
<div class="stats" id="sys-stats"></div>
|
||
<div class="clock" id="clock"></div>
|
||
</header>
|
||
|
||
<div class="layout">
|
||
<aside>
|
||
<a class="nav-item" href="/" data-nav="live"><span class="ico">▦</span>Live view</a>
|
||
<div class="subnav">
|
||
<a class="subitem" data-grid="2" href="/?grid=2">4</a>
|
||
<a class="subitem" data-grid="3" href="/?grid=3">9</a>
|
||
<a class="subitem" data-grid="4" href="/?grid=4">16</a>
|
||
<a class="subitem" data-grid="5" href="/?grid=5">25</a>
|
||
<a class="subitem" data-grid="6" href="/?grid=6">36</a>
|
||
<a class="subitem" data-grid="7" href="/?grid=7">49</a>
|
||
<a class="subitem" data-grid="8" href="/?grid=8">64</a>
|
||
</div>
|
||
<a class="nav-item" href="/archive" data-nav="archive"><span class="ico">🗄</span>Архив</a>
|
||
<div class="aside-spacer"></div>
|
||
<a class="nav-item active" href="/settings" data-nav="settings"><span class="ico">⚙</span>Настройки</a>
|
||
</aside>
|
||
|
||
<main class="settings-main">
|
||
<div class="tabs">
|
||
<button class="tab active" data-tab="cams" data-min-role="admin">Камеры</button>
|
||
<button class="tab" data-tab="layout">Раскладка</button>
|
||
<button class="tab" data-tab="users" data-min-role="superadmin">Пользователи</button>
|
||
<button class="tab" data-tab="general" data-min-role="operator">Система</button>
|
||
<button class="tab" data-tab="optim" data-min-role="superadmin">Доп настройки</button>
|
||
</div>
|
||
|
||
<!-- ВКЛАДКА 1: Камеры -->
|
||
<div class="tab-panel" data-panel="cams" data-min-role="admin">
|
||
<div class="card">
|
||
<div class="card-head">
|
||
<h2>Камеры — 64 слота</h2>
|
||
<div style="display:flex;gap:8px">
|
||
<button id="bulk-edit">Изменить</button>
|
||
<button id="bulk-cancel" hidden>Отмена</button>
|
||
<button id="add-cam">+ Добавить камеру</button>
|
||
<button id="clear-cams" class="danger" title="Удалить все камеры (архив не трогается)">Очистить все</button>
|
||
</div>
|
||
</div>
|
||
<table class="cams">
|
||
<thead>
|
||
<tr><th style="width:48px">ID</th><th>Камера</th><th>IP</th><th>Потоки</th><th>Статус</th><th></th></tr>
|
||
</thead>
|
||
<tbody id="cam-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ВКЛАДКА 2: Система -->
|
||
<div class="tab-panel" data-panel="general" data-min-role="operator" hidden>
|
||
<div class="wrap">
|
||
<div class="card" data-min-role="admin">
|
||
<h2>Запись</h2>
|
||
<label class="fl" style="font-size:13px;color:var(--text)">Размер сегмента</label>
|
||
<select id="segment-size" style="margin-top:6px;display:block">
|
||
<option value="60">1 минута</option>
|
||
<option value="120">2 минуты</option>
|
||
<option value="300">5 минут</option>
|
||
<option value="600">10 минут</option>
|
||
<option value="900">15 минут</option>
|
||
</select>
|
||
<div style="margin-top:12px"><button id="segment-save">Сохранить</button></div>
|
||
<div class="muted" id="segment-saved" style="margin-top:8px;font-size:12px"></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Плеер и перекодирование <span class="muted" style="font-weight:400;font-size:12px">— настройки этого браузера</span></h2>
|
||
<div class="muted" style="margin-top:-4px;margin-bottom:16px;font-size:12px">
|
||
Для каждого потока выберите способ воспроизведения: <b>как есть</b> —
|
||
поток отдаётся без обработки (ffmpeg -c copy), браузер декодирует HEVC сам
|
||
(нужна аппаратная поддержка); <b>встроенный плеер</b> — декодирует H.265
|
||
в браузере софтом (WASM hevc.js, в Web Worker), тянет и основной поток
|
||
(3200×1800, включая тайлы), и субпоток, без нагрузки на сервер (декод
|
||
нагружает CPU клиента); <b>WebCodecs (железо)</b> — аппаратный декод H.265 на GPU клиента,
|
||
тянет основной поток 3200×1800 при 0% CPU сервера (рекомендуется для
|
||
основного потока); <b>перекодировать</b> — сервер транскодирует в H.264 /
|
||
VP9 (нагрузка на CPU сервера, для слабых клиентов).
|
||
</div>
|
||
<!-- 3 независимых профиля: 1 поток / 2 поток / архив -->
|
||
<div class="tr-block" data-tr="1">
|
||
<h3>1 поток (основной)</h3>
|
||
<div class="seg-toggle">
|
||
<label><input type="radio" name="mode-1" value="native"><span>Как есть</span></label>
|
||
<label><input type="radio" name="mode-1" value="player"><span>Встроенный плеер</span></label>
|
||
<label><input type="radio" name="mode-1" value="webcodecs"><span>WebCodecs (железо)</span></label>
|
||
<label><input type="radio" name="mode-1" value="transcode"><span>Перекодировать</span></label>
|
||
</div>
|
||
<div class="tr-row"></div>
|
||
</div>
|
||
|
||
<div class="tr-block" data-tr="2">
|
||
<h3>2 поток (суб)</h3>
|
||
<div class="seg-toggle">
|
||
<label><input type="radio" name="mode-2" value="native"><span>Как есть</span></label>
|
||
<label><input type="radio" name="mode-2" value="player"><span>Встроенный плеер</span></label>
|
||
<label><input type="radio" name="mode-2" value="webcodecs"><span>WebCodecs (железо)</span></label>
|
||
<label><input type="radio" name="mode-2" value="transcode"><span>Перекодировать</span></label>
|
||
</div>
|
||
<div class="tr-row"></div>
|
||
</div>
|
||
|
||
<div class="tr-block" data-tr="a">
|
||
<h3>Архив</h3>
|
||
<div class="seg-toggle">
|
||
<label><input type="radio" name="mode-a" value="native"><span>Как есть</span></label>
|
||
<label><input type="radio" name="mode-a" value="player"><span>Встроенный плеер</span></label>
|
||
<label><input type="radio" name="mode-a" value="transcode"><span>Перекодировать</span></label>
|
||
</div>
|
||
<div class="tr-row"></div>
|
||
</div>
|
||
|
||
<div style="margin-top:16px"><button id="prefs-save">Сохранить</button></div>
|
||
<div class="muted" id="prefs-saved" style="margin-top:8px;font-size:12px">Сохраняется в этом браузере</div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Хранилище</h2>
|
||
<div class="kv" id="storage-kv"><div class="muted">загрузка…</div></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Система</h2>
|
||
<div class="kv" id="system-kv"><div class="muted">загрузка…</div></div>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Учётная запись</h2>
|
||
<div class="muted" id="me-info" style="margin-bottom:10px;font-size:13px"></div>
|
||
<button id="logout">Выйти из системы</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ВКЛАДКА: Раскладка (назначение камер по ячейкам, этот браузер) -->
|
||
<div class="tab-panel" data-panel="layout" hidden>
|
||
<div class="card">
|
||
<div class="card-head">
|
||
<h2>Настройка раскладки</h2>
|
||
<div style="display:flex;align-items:center;gap:10px">
|
||
<label class="muted">Раскладка:</label>
|
||
<select id="layout-dim">
|
||
<option value="2">4 (2×2)</option>
|
||
<option value="3">9 (3×3)</option>
|
||
<option value="4">16 (4×4)</option>
|
||
<option value="5">25 (5×5)</option>
|
||
<option value="6">36 (6×6)</option>
|
||
<option value="7">49 (7×7)</option>
|
||
<option value="8">64 (8×8)</option>
|
||
</select>
|
||
<button id="layout-save">Сохранить</button>
|
||
</div>
|
||
</div>
|
||
<div class="muted" style="margin-bottom:12px">Назначьте камеру в каждую ячейку раскладки. Сохраняется в этом браузере.</div>
|
||
<div id="layout-grid" class="layout-grid"></div>
|
||
<div class="muted" id="layout-saved" style="margin-top:12px;font-size:12px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ВКЛАДКА: Доп настройки (только суперадмин) -->
|
||
<div class="tab-panel" data-panel="optim" data-min-role="superadmin" hidden>
|
||
<div class="wrap">
|
||
<div class="card">
|
||
<h2>Live view <span class="muted" style="font-weight:400;font-size:12px">— общая политика для всех клиентов</span></h2>
|
||
<label class="toggle" style="color:var(--text)">
|
||
<input type="checkbox" id="single-main">
|
||
Не более одного основного потока в режиме Live view
|
||
</label>
|
||
<div class="muted" style="margin-top:8px;font-size:12px">
|
||
Включено по умолчанию. Основной (HD) поток можно держать одновременно
|
||
только в одной ячейке — при переключении другой ячейки на «1»
|
||
предыдущая вернётся на субпоток. Снижает нагрузку на сеть и камеры.
|
||
</div>
|
||
<label class="toggle" style="color:var(--text);margin-top:18px">
|
||
<input type="checkbox" id="mode-16plus">
|
||
Режим 16+
|
||
</label>
|
||
<div class="muted" style="margin-top:8px;font-size:12px">
|
||
По умолчанию в Live view доступно не более 16 камер (сетки до 4×4).
|
||
Включите «16+», чтобы открыть раскладки 25 / 36 / 49 / 64.
|
||
</div>
|
||
<div class="muted" style="margin-top:12px;font-size:12px">
|
||
<b>Менять может только суперадмин с подтверждением пароля.</b>
|
||
</div>
|
||
<div style="margin-top:14px"><button id="optim-save">Сохранить</button></div>
|
||
<div class="muted" id="optim-saved" style="margin-top:8px;font-size:12px">Смена требует пароль</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ВКЛАДКА 4: Пользователи (только суперадмин) -->
|
||
<div class="tab-panel" data-panel="users" data-min-role="superadmin" hidden>
|
||
<div class="card">
|
||
<div class="card-head">
|
||
<h2>Пользователи и роли</h2>
|
||
<button id="add-user">+ Добавить пользователя</button>
|
||
</div>
|
||
<table class="cams">
|
||
<thead>
|
||
<tr><th>Логин</th><th style="width:160px">Роль</th><th style="width:220px">Пароль</th><th style="width:120px"></th></tr>
|
||
</thead>
|
||
<tbody id="user-rows"></tbody>
|
||
</table>
|
||
<div class="muted" id="users-msg" style="margin-top:10px;font-size:12px"></div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
|
||
<script src="/static/app.js"></script>
|
||
</body>
|
||
</html>
|