This commit is contained in:
2026-05-30 00:08:59 +05:00
commit d3afd698b6
52 changed files with 8150 additions and 0 deletions
+225
View File
@@ -0,0 +1,225 @@
<!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>
</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>