Files
Keenetic-Split-DNS/www/index.html
Андрей Бобырев bc9355fe40 Initial release: install, uninstall, SmartDNS, web UI
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 22:15:37 +03:00

203 lines
9.6 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="ru" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Keenetic Split DNS</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="auth-gate" class="auth-gate">
<div class="card auth-card">
<div class="card-header"><h3>Токен API</h3></div>
<p class="hint" style="margin-bottom:12px">Токен из <code>/opt/etc/keenetic-split-dns/token</code> (показан при установке)</p>
<div class="form-group">
<label>Bearer token</label>
<input type="password" id="auth-token-input" placeholder="вставьте токен">
</div>
<button class="btn btn-primary" id="auth-save" style="width:100%">Войти</button>
</div>
</div>
<div class="app">
<aside class="sidebar">
<div class="logo">
<div class="logo-icon"></div>
<div>
<h1>Split DNS</h1>
<span>SmartDNS · Keenetic</span>
</div>
</div>
<nav class="nav">
<button class="nav-item active" data-tab="dashboard">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
Обзор
</button>
<button class="nav-item" data-tab="upstreams">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4"/></svg>
Upstream
</button>
<button class="nav-item" data-tab="domains">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/></svg>
Домены
</button>
<button class="nav-item" data-tab="test">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/></svg>
Проверка
</button>
<button class="nav-item" data-tab="settings">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/></svg>
Настройки
</button>
</nav>
<div class="sidebar-footer">
<div>Конфиг: <code>/opt/etc/keenetic-split-dns/</code></div>
<div style="margin-top:6px">Порт: <code id="sidebar-port">3200</code></div>
</div>
</aside>
<div class="main">
<header class="topbar">
<div class="topbar-left">
<h2 id="page-title">Обзор</h2>
<p id="topbar-sub">Загрузка…</p>
</div>
<div class="topbar-actions">
<span class="badge badge-running badge-dot" id="status-badge">SmartDNS</span>
<button class="btn btn-icon" id="theme-btn" title="Тема">🌓</button>
<button class="btn btn-success" id="apply-top">Применить</button>
</div>
</header>
<div class="content">
<section class="panel active" id="panel-dashboard">
<div class="grid grid-4" style="margin-bottom:20px">
<div class="card">
<div class="card-header"><span class="stat-label">Статус</span><span class="stat-icon" style="background:var(--success-bg)"></span></div>
<div class="stat-value" id="stat-status" style="font-size:18px"></div>
<div class="stat-label" id="stat-pid">PID —</div>
</div>
<div class="card">
<div class="card-header"><span class="stat-label">Домены</span><span class="stat-icon" style="background:var(--info-bg)">🌐</span></div>
<div class="stat-value" id="stat-domains"></div>
<div class="stat-label">в списках split-DNS</div>
</div>
<div class="card">
<div class="card-header"><span class="stat-label">Upstream</span><span class="stat-icon" style="background:var(--warning-bg)">🔗</span></div>
<div class="stat-value" id="stat-upstreams"></div>
<div class="stat-label" id="stat-upstream-names"></div>
</div>
<div class="card">
<div class="card-header"><span class="stat-label">Веб-UI</span><span class="stat-icon" style="background:var(--accent-dim)">🖥</span></div>
<div class="stat-value" style="font-size:16px" id="stat-url"></div>
<div class="stat-label">только LAN</div>
</div>
</div>
<div class="card">
<div class="card-header"><h3>Журнал</h3></div>
<div id="log-container"><div class="log-line"><span class="log-time"></span> Загрузка…</div></div>
</div>
</section>
<section class="panel" id="panel-upstreams">
<div class="toolbar">
<button class="btn btn-primary" id="btn-add-upstream">+ Профиль upstream</button>
</div>
<div class="master-detail">
<div class="card">
<div class="card-header"><h3>Профили</h3></div>
<ul class="upstream-list" id="upstream-list"></ul>
</div>
<div class="card" id="upstream-detail">
<div class="card-header"><h3 id="upstream-detail-title">Выберите профиль</h3></div>
<div id="upstream-detail-body"><p class="hint">Слева — upstream, справа — домены группы с этой политикой.</p></div>
<div class="table-wrap" style="margin-top:16px" id="upstream-domains-wrap">
<table><thead><tr><th>Домен</th><th>Группа</th></tr></thead><tbody id="upstream-domains-tbody"></tbody></table>
</div>
</div>
</div>
</section>
<section class="panel" id="panel-domains">
<div class="toolbar">
<div class="search-box">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
<input type="search" placeholder="Поиск домена…" id="domain-search">
</div>
<button class="btn" id="btn-export-domains">Экспорт списка</button>
</div>
<div class="card" style="padding:0;overflow:hidden">
<div class="table-wrap" style="border:none">
<table id="domains-table">
<thead><tr><th>Домен</th><th>Группа</th><th>Upstream</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
</section>
<section class="panel" id="panel-test">
<div class="card">
<div class="card-header"><h3>Проверка DNS-запроса</h3></div>
<div class="toolbar" style="margin-bottom:0">
<div class="form-group" style="flex:1;margin:0">
<input type="text" id="test-domain" value="vk.com">
</div>
<select id="test-type">
<option>A</option>
<option>AAAA</option>
</select>
<button class="btn btn-primary" id="run-test">Выполнить</button>
</div>
<pre class="test-result" id="test-output"># Нажмите «Выполнить»</pre>
</div>
<div class="grid grid-3" style="margin-top:16px">
<div class="card">
<div class="stat-label">Быстрые тесты</div>
<div style="margin-top:10px;display:flex;flex-wrap:wrap;gap:6px">
<button class="btn btn-sm quick-test" data-d="yandex.ru">yandex.ru</button>
<button class="btn btn-sm quick-test" data-d="vk.com">vk.com</button>
<button class="btn btn-sm quick-test" data-d="google.com">google.com</button>
</div>
</div>
<div class="card">
<div class="stat-label">Время ответа</div>
<div class="stat-value" style="font-size:20px" id="test-latency"></div>
</div>
</div>
</section>
<section class="panel" id="panel-settings">
<div class="apply-banner">
<div>
<p><strong>Применить конфигурацию</strong> — YAML → SmartDNS + перезагрузка</p>
</div>
<button class="btn btn-primary" id="apply-settings">⚡ Применить</button>
</div>
<div class="grid grid-2">
<div class="card">
<div class="card-header"><h3>Токен API</h3></div>
<div class="form-group">
<label>Текущий токен (localStorage)</label>
<input type="password" id="settings-token">
</div>
<button class="btn" id="save-token">Сохранить токен</button>
</div>
<div class="card">
<div class="card-header"><h3>Конфиг YAML</h3></div>
<div class="form-group">
<textarea id="config-yaml" style="min-height:240px"></textarea>
</div>
<button class="btn btn-primary" id="save-config">Сохранить YAML</button>
</div>
</div>
</section>
</div>
</div>
</div>
<div class="toast" id="toast">✓ Готово</div>
<script src="app.js"></script>
</body>
</html>