ctf-ad-mirror-tool-rust/web/index.html

106 lines
9.8 KiB
HTML
Raw Permalink 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>Proxy Manager</title>
<link href="/vendor/bootstrap.min.css" rel="stylesheet">
<link href="/vendor/fontawesome.min.css" rel="stylesheet">
<link href="/app.css" rel="stylesheet">
<script src="/app.js" defer></script>
</head>
<body>
<div class="container mt-2">
<div id="alert" class="alert alert-danger alert-dismissible fade show" role="alert" hidden><span id="alert-message"></span><button id="dismiss-alert" type="button" class="btn-close btn-close-white" aria-label="Закрыть сообщение"></button></div>
<div id="login" class="row justify-content-center align-items-center login-row" hidden>
<div class="col-md-6 col-lg-4"><div class="service-card text-center login-card">
<div class="mb-4"><h2 class="login-heading">Proxy</h2><p class="login-caption">Введите пароль</p></div>
<form id="login-form">
<div class="mb-4"><input type="password" class="input-modern w-100 login-password" id="password" name="password" placeholder="Пароль" aria-label="Пароль" autocomplete="current-password" required></div>
<p id="login-error" class="form-error" role="alert"></p><button id="login-button" type="submit" class="add-button w-100">Войти</button>
</form>
</div></div>
</div>
<div id="header" class="d-flex justify-content-between align-items-center header-row" hidden>
<h1 class="section-title">Mirror Tool</h1>
<div class="header-actions">
<button id="help" class="refresh-button" title="Настройка / ForcAD" aria-label="Настройка / ForcAD"><i class="fas fa-circle-info" aria-hidden="true"></i></button>
<button id="manage-teams" class="refresh-button" title="Команды" aria-label="Команды"><i class="fas fa-users" aria-hidden="true"></i></button>
<button id="refresh" class="refresh-button" title="Обновить" aria-label="Обновить"><i class="fas fa-sync-alt" aria-hidden="true"></i></button>
<button id="logout" class="logout-button" title="Выход" aria-label="Выход"><i class="fas fa-sign-out-alt" aria-hidden="true"></i></button>
<button id="add-service" class="add-button" title="Добавить прокси" aria-label="Добавить прокси"><i class="fas fa-plus" aria-hidden="true"></i></button>
</div>
</div>
<div id="dashboard" class="main-dashboard" hidden><div id="service-board" class="task-board board-scroll"></div></div>
</div>
<dialog id="addCustomModal" class="legacy-modal" aria-labelledby="add-title">
<div class="modal-dialog"><div class="modal-content">
<div class="modal-header"><h5 class="modal-title" id="add-title">Добавить прокси</h5><button type="button" class="btn-close btn-close-white" data-close="addCustomModal" aria-label="Закрыть"></button></div>
<form id="customProxyForm">
<div class="modal-body">
<div class="mb-3"><label for="customName" class="form-label">Название</label><input type="text" class="input-modern w-100" id="customName" placeholder="Название сервиса" maxlength="128" required></div>
<div class="mb-3"><label for="customPort" class="form-label">Порт</label><input type="number" step="1" inputmode="numeric" class="input-modern w-100" id="customPort" min="1" max="65535" placeholder="8080" required></div>
<div class="mb-3"><label for="customIp" class="form-label">IP (опционально)</label><input type="text" class="input-modern w-100" id="customIp" placeholder="192.168.1.100" autocomplete="off"></div>
<p id="custom-error" class="form-error" role="alert"></p>
</div>
<div class="modal-footer"><button type="button" class="add-button cancel-button" data-close="addCustomModal">Отмена</button><button type="submit" class="add-button">Добавить</button></div>
</form>
</div></div>
</dialog>
<dialog id="settingsModal" class="legacy-modal" aria-labelledby="settings-title">
<div class="modal-dialog"><div class="modal-content">
<div class="modal-header"><h5 class="modal-title" id="settings-title">Настройки сервиса</h5><button type="button" class="btn-close btn-close-white" data-close="settingsModal" aria-label="Закрыть"></button></div>
<form id="settings-form">
<div class="modal-body">
<div class="mb-3"><label for="service-name" class="form-label">Название</label><input id="service-name" class="input-modern w-100" maxlength="128" required></div>
<div class="mb-3"><label for="service-listen" class="form-label">Адрес и порт прокси</label><input id="service-listen" class="input-modern w-100" required></div>
<div class="mb-3"><label for="service-port" class="form-label">Порт сервиса команды</label><input id="service-port" type="number" step="1" inputmode="numeric" min="1" max="65535" class="input-modern w-100" required></div>
<div class="mb-3"><label for="service-policy" class="form-label">При медленной реплике</label><select id="service-policy" class="input-modern w-100"><option value="isolate">Отключить реплику, сохранить скорость primary</option><option value="strict">Ждать реплику, замедлить общий поток</option></select></div>
<p id="settings-error" class="form-error" role="alert"></p>
</div>
<div class="modal-footer"><button type="button" class="add-button cancel-button" data-close="settingsModal">Отмена</button><button type="submit" class="add-button">Сохранить</button></div>
</form>
</div></div>
</dialog>
<dialog id="teamsModal" class="legacy-modal" aria-labelledby="teams-title">
<div class="modal-dialog"><div class="modal-content">
<div class="modal-header"><h5 class="modal-title" id="teams-title">Команды</h5><button type="button" class="btn-close btn-close-white" data-close="teamsModal" aria-label="Закрыть"></button></div>
<form id="team-form">
<div class="modal-body">
<div class="mb-3"><label for="team-choice" class="form-label">Команда</label><select id="team-choice" class="input-modern w-100"><option value="">Новая команда</option></select></div>
<div class="mb-3"><label for="team-name" class="form-label">Название команды</label><input id="team-name" class="input-modern w-100" maxlength="128" required></div>
<div class="mb-3"><label for="team-address" class="form-label">IP команды</label><input id="team-address" class="input-modern w-100" placeholder="192.0.2.10 или ::1" autocomplete="off" required aria-describedby="team-hint"></div>
<p id="team-hint" class="form-hint">Для ForcAD укажите точное название из scoreboard. IP существующей команды неизменяемый — для другого адреса добавьте новую.</p>
<p id="team-error" class="form-error" role="alert"></p>
<p id="team-result" class="form-hint" role="status"></p>
</div>
<div class="modal-footer"><button type="button" class="add-button cancel-button" data-close="teamsModal">Закрыть</button><button type="submit" class="add-button">Сохранить команду</button></div>
</form>
</div></div>
</dialog>
<dialog id="helpModal" class="legacy-modal" aria-labelledby="help-title">
<div class="modal-dialog"><div class="modal-content">
<div class="modal-header"><h5 class="modal-title" id="help-title">Настройка / ForcAD</h5><button type="button" class="btn-close btn-close-white" data-close="helpModal" aria-label="Закрыть"></button></div>
<div class="modal-body help-body">
<p id="board-status" role="status"></p><p id="board-error" class="form-error"></p>
<h6>Конфигурация</h6>
<p>Файл задаётся при запуске: <code>--config mirror.toml</code>. Команды и сервисы из панели сохраняются в <code>[web].state_file</code>; относительный путь считается от каталога TOML. Если state-файл уже существует, топология загружается из него.</p>
<h6>Подключение ForcAD</h6>
<p>В начало TOML, перед секциями, добавьте IP своей команды. Затем добавьте секцию scoreboard:</p>
<pre>main_team_ip = "192.0.2.10"
[scoreboard]
kind = "forcad"
url = "http://scoreboard.example:8080"
poll_interval_ms = 3000
stale_after_ms = 15000</pre>
<p>Адрес замените на URL вашей игры. Имена команд и сервисов должны совпадать с scoreboard. После правки TOML перезапустите процесс. Настройки маршрутов из панели применяются сразу.</p>
<h6>Управление маршрутами</h6>
<p>Кружок выбирает primary, строка — реплику. Робот включает автоматический выбор из назначенных реплик. Новые соединения используют новый маршрут; открытые остаются на прежнем.</p>
<p>Название сервиса открывает настройки портов и режима реплик. При <code>isolate</code> медленная реплика отключается; при <code>strict</code> общий поток ждёт её.</p>
</div>
</div></div>
</dialog>
</body>
</html>