Files
alpine-router/public/index.html
2026-04-13 12:40:49 +03:00

169 lines
6.1 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">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AlpineRouter</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<div class="header-left">
<svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
<h1>AlpineRouter</h1>
</div>
<div class="header-right">
<span id="hostname" class="hostname"></span>
<button class="btn btn-ghost" id="refreshBtn" title="Обновить">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
<path d="M3 3v5h5"/>
</svg>
Обновить
</button>
</div>
</header>
<div id="pendingBanner" class="pending-banner hidden">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">
<circle cx="12" cy="12" r="10"/><path d="M12 8v4l3 3"/>
</svg>
<span>Есть несохранённые изменения: <strong id="pendingList"></strong></span>
<div class="banner-actions">
<button class="btn btn-success" id="applyBtn">Применить</button>
<button class="btn btn-ghost" id="discardAllBtn">Отменить всё</button>
</div>
</div>
<nav class="tab-nav">
<a href="/" class="tab-link active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
Интерфейсы
</a>
<a href="/dhcp.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
DHCP сервер
</a>
<a href="/clients.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<circle cx="9" cy="7" r="4"/><path d="M3 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2"/>
<path d="M16 3.13a4 4 0 0 1 0 7.75M21 21v-2a4 4 0 0 0-3-3.87"/>
</svg>
Клиенты
</a>
<a href="/firewall.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
<path d="M9 12l2 2 4-4"/>
</svg>
Файрвол
</a>
<a href="/proxy.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/>
</svg>
Прокси
</a>
</nav>
<main>
<div id="loading" class="loading">
<div class="spinner"></div>
<span>Загрузка...</span>
</div>
<div id="ifaceGrid" class="iface-grid hidden"></div>
</main>
<!-- Config Modal -->
<div id="modal" class="modal hidden" role="dialog" aria-modal="true">
<div class="modal-backdrop" id="modalBackdrop"></div>
<div class="modal-box">
<div class="modal-header">
<h2 id="modalTitle">Настройка интерфейса</h2>
<button class="btn-icon" id="closeModal" title="Закрыть"></button>
</div>
<form id="configForm" autocomplete="off">
<!-- VLAN ID — shown only for VLAN interfaces -->
<div id="vlanIdSection" class="hidden">
<div class="form-row">
<label for="cfgVLANId">VLAN ID <span class="form-hint-inline">(14094)</span></label>
<input type="number" id="cfgVLANId" min="1" max="4094" placeholder="100">
</div>
<div class="form-divider"></div>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="cfgAuto">
<span>Автозапуск (auto)</span>
</label>
</div>
<div class="form-row">
<label>Режим</label>
<div class="segmented" id="modeSwitch">
<button type="button" class="seg-btn active" data-mode="dhcp">DHCP</button>
<button type="button" class="seg-btn" data-mode="static">Статический</button>
</div>
</div>
<div id="staticFields" class="hidden">
<div class="form-row">
<label for="cfgAddress">IP-адрес</label>
<input type="text" id="cfgAddress" placeholder="192.168.1.100" pattern="[\d\.]+">
</div>
<div class="form-row">
<label for="cfgNetmask">Маска сети</label>
<input type="text" id="cfgNetmask" placeholder="255.255.255.0">
</div>
<div class="form-row">
<label for="cfgGateway">Шлюз</label>
<input type="text" id="cfgGateway" placeholder="192.168.1.1">
</div>
<div class="form-row">
<label for="cfgDNS">DNS (через пробел)</label>
<input type="text" id="cfgDNS" placeholder="8.8.8.8 8.8.4.4">
</div>
</div>
<div id="natSection" class="hidden">
<div class="form-divider"></div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="cfgNAT">
<span>NAT / Masquerade — выход клиентов в интернет</span>
</label>
</div>
<div id="natNotInstalled" class="form-hint hidden">
⚠ nftables не установлен — выполните: <code>apk add nftables</code>
</div>
</div>
</form>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancelConfigBtn">Отмена</button>
<button class="btn btn-primary" id="saveConfigBtn">Сохранить</button>
</div>
</div>
</div>
<!-- Notification toast -->
<div id="toast" class="toast hidden"></div>
<script src="app.js"></script>
</body>
</html>