mirror of
https://github.com/andrey271192/vps_monitoring.git
synced 2026-09-20 11:55:34 +00:00
Encode router names in Keenetic API calls and return an error when delete targets a missing device. Co-authored-by: Cursor <cursoragent@cursor.com>
607 lines
31 KiB
HTML
607 lines
31 KiB
HTML
<!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>VPS Monitoring</title>
|
||
<link rel="stylesheet" href="/static/css/style.css">
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.min.css">
|
||
<script src="/static/js/theme.js"></script>
|
||
<script src="/static/js/i18n.js"></script>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<div class="header-left">
|
||
<h1 id="pageTitle">🖥 VPS Monitoring</h1>
|
||
</div>
|
||
<div class="header-right">
|
||
<button class="lang-btn" id="langBtn" onclick="toggleLang()">RU</button>
|
||
<button class="btn-icon" id="themeToggleBtn" onclick="toggleTheme()" title="Theme">🌙</button>
|
||
<button class="btn-icon" onclick="refreshAll()" title="Refresh">🔄</button>
|
||
<button class="btn-icon" onclick="showInstructions()" title="Instructions">📖</button>
|
||
<button class="btn-icon" onclick="showNotificationSettings()" title="Notifications">🔔</button>
|
||
<button class="btn-icon" onclick="showSettings()" title="Settings">⚙️</button>
|
||
<button class="btn-icon" onclick="logout()" title="Logout">🚪</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main>
|
||
<div class="stats-bar">
|
||
<div class="stat-item" id="stat-total">
|
||
<span class="stat-label" data-i18n="total">Всего</span>
|
||
<span class="stat-value" id="total-count">0</span>
|
||
</div>
|
||
<div class="stat-item online" id="stat-online">
|
||
<span class="stat-label" data-i18n="online">Online</span>
|
||
<span class="stat-value" id="online-count">0</span>
|
||
</div>
|
||
<div class="stat-item offline" id="stat-offline">
|
||
<span class="stat-label" data-i18n="offline">Offline</span>
|
||
<span class="stat-value" id="offline-count">0</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tabs -->
|
||
<div class="tabs">
|
||
<button class="tab active" id="tab-servers" onclick="switchTab('servers')">🖥 VPS</button>
|
||
<button class="tab" id="tab-pc" onclick="switchTab('pc')">💻 PC</button>
|
||
<button class="tab" id="tab-synology" onclick="switchTab('synology')">📦 Synology</button>
|
||
<button class="tab" id="tab-ha" onclick="switchTab('ha')">🏠 Home Assistant</button>
|
||
<button class="tab" id="tab-keenetic" onclick="switchTab('keenetic')">📡 Keenetic</button>
|
||
</div>
|
||
|
||
<!-- Servers Tab -->
|
||
<div id="panel-servers">
|
||
<div class="toolbar">
|
||
<button class="btn-primary" id="addServerBtn" onclick="showAddServer()">+ Добавить сервер</button>
|
||
</div>
|
||
<div class="servers-grid" id="servers-grid"></div>
|
||
</div>
|
||
|
||
<!-- PC Tab -->
|
||
<div id="panel-pc" style="display:none">
|
||
<div class="toolbar">
|
||
<button class="btn-primary" onclick="showPCDownload()">📥 Скачать агент</button>
|
||
<button class="btn-secondary" onclick="showPCSetup()">📋 Инструкция</button>
|
||
<button class="btn-secondary" onclick="loadPCs()">🔄 Обновить</button>
|
||
</div>
|
||
<div class="servers-grid" id="pc-grid"></div>
|
||
</div>
|
||
|
||
<!-- Synology Tab -->
|
||
<div id="panel-synology" style="display:none">
|
||
<div class="toolbar">
|
||
<button class="btn-primary" onclick="showAddSynology()">+ Добавить NAS</button>
|
||
<button class="btn-secondary" onclick="refreshAllSynology()">🔄 Обновить все</button>
|
||
<button class="btn-secondary" onclick="showSynTunnel()">🔗 Туннель</button>
|
||
</div>
|
||
<div class="servers-grid" id="synology-grid"></div>
|
||
</div>
|
||
|
||
<!-- Home Assistant Tab -->
|
||
<div id="panel-ha" style="display:none">
|
||
<div class="toolbar">
|
||
<button class="btn-primary" onclick="showAddHA()">+ Добавить HA</button>
|
||
<button class="btn-secondary" onclick="refreshAllHA()">🔄 Обновить все</button>
|
||
</div>
|
||
<div class="servers-grid" id="ha-grid"></div>
|
||
</div>
|
||
<!-- Keenetic Tab -->
|
||
<div id="panel-keenetic" style="display:none">
|
||
<div class="toolbar">
|
||
<button class="btn-primary" onclick="showAddKeenetic()">+ Добавить роутер</button>
|
||
<button class="btn-secondary" onclick="showBulkAddKeenetic()">📋 Массовое добавление</button>
|
||
<button class="btn-secondary" onclick="showImportKeenetic()">📥 Импорт таблицы</button>
|
||
<button class="btn-secondary" onclick="refreshAllKeenetic()">🔄 Обновить все</button>
|
||
</div>
|
||
<div class="servers-grid" id="keenetic-grid"></div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Add Server Modal -->
|
||
<div class="modal" id="addServerModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 data-i18n="addServer">Добавить сервер</h2>
|
||
<button class="btn-close" onclick="closeModal('addServerModal')">×</button>
|
||
</div>
|
||
<form id="addServerForm">
|
||
<div class="form-group">
|
||
<label data-i18n="serverName">Название</label>
|
||
<input type="text" name="name" required placeholder="My Server">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="host">IP / Host</label>
|
||
<input type="text" name="host" required placeholder="192.168.1.1">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="sshPort">Порт SSH</label>
|
||
<input type="number" name="port" value="22">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="sshLogin">Логин</label>
|
||
<input type="text" name="username" value="root">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="sshPassword">Пароль</label>
|
||
<input type="password" name="password" placeholder="SSH Password">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="description">Описание</label>
|
||
<input type="text" name="description" placeholder="">
|
||
</div>
|
||
<button type="submit" class="btn-primary" data-i18n="add">Добавить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Add Synology Modal -->
|
||
<div class="modal" id="addSynologyModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>📦 Добавить Synology NAS</h2>
|
||
<button class="btn-close" onclick="closeModal('addSynologyModal')">×</button>
|
||
</div>
|
||
<form id="addSynologyForm">
|
||
<div class="form-group">
|
||
<label>Название</label>
|
||
<input type="text" name="name" required placeholder="My NAS">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>IP / Host</label>
|
||
<input type="text" name="host" required placeholder="192.168.1.50">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Порт DSM</label>
|
||
<input type="number" name="port" value="5000">
|
||
</div>
|
||
<div class="form-group" style="display:flex;align-items:center;gap:8px">
|
||
<input type="checkbox" name="https" id="syn-https" style="width:auto">
|
||
<label for="syn-https" style="margin:0">HTTPS</label>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Логин DSM</label>
|
||
<input type="text" name="username" required placeholder="admin">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Пароль DSM</label>
|
||
<input type="password" name="password" required>
|
||
</div>
|
||
<button type="submit" class="btn-primary">Добавить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Add HA Modal -->
|
||
<div class="modal" id="addHAModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>🏠 Добавить Home Assistant</h2>
|
||
<button class="btn-close" onclick="closeModal('addHAModal')">×</button>
|
||
</div>
|
||
<form id="addHAForm">
|
||
<div class="form-group">
|
||
<label>Название</label>
|
||
<input type="text" name="name" required placeholder="Home">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>URL</label>
|
||
<input type="text" name="url" required placeholder="http://192.168.1.100:8123">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Long-Lived Access Token</label>
|
||
<textarea name="token" required rows="3" placeholder="Профиль → Безопасность → Долгоживущие токены доступа" style="resize:vertical"></textarea>
|
||
</div>
|
||
<button type="submit" class="btn-primary">Добавить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Add Keenetic Modal -->
|
||
<div class="modal" id="addKeeneticModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>📡 Добавить Keenetic</h2>
|
||
<button class="btn-close" onclick="closeModal('addKeeneticModal')">×</button>
|
||
</div>
|
||
<form id="addKeeneticForm">
|
||
<div class="form-group">
|
||
<label>Название</label>
|
||
<input type="text" name="name" required placeholder="Home Router">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Хост / Keenetic URL</label>
|
||
<input type="text" name="host" required placeholder="loftliliana.netcraze.pro или https://...">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>AnyDesk ID</label>
|
||
<input type="text" name="anydesk" placeholder="1020687391">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Логин</label>
|
||
<input type="text" name="login" value="admin">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Пароль</label>
|
||
<input type="password" name="password" required>
|
||
</div>
|
||
<button type="submit" class="btn-primary">Добавить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bulk Add Keenetic Modal -->
|
||
<div class="modal" id="bulkAddKeeneticModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>📋 Массовое добавление роутеров</h2>
|
||
<button class="btn-close" onclick="closeModal('bulkAddKeeneticModal')">×</button>
|
||
</div>
|
||
<form id="bulkAddKeeneticForm">
|
||
<div class="form-group">
|
||
<label>Домены (по одному на строку)</label>
|
||
<textarea name="domains" rows="10" required placeholder="vimpel.netcraze.link
|
||
home.netcraze.link
|
||
office.netcraze.link" style="width:100%;font-family:monospace;font-size:13px;resize:vertical"></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Логин (общий для всех)</label>
|
||
<input type="text" name="login" value="admin">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Пароль (общий для всех)</label>
|
||
<input type="password" name="password" required>
|
||
</div>
|
||
<button type="submit" class="btn-primary" style="width:100%">Добавить все</button>
|
||
</form>
|
||
<div id="bulkAddResult" style="display:none;margin-top:12px;padding:12px;border-radius:8px;background:var(--bg-primary);font-size:13px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Import Keenetic Modal -->
|
||
<div class="modal" id="importKeeneticModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>📥 Импорт из таблицы</h2>
|
||
<button class="btn-close" onclick="closeModal('importKeeneticModal')">×</button>
|
||
</div>
|
||
<form id="importKeeneticForm">
|
||
<p style="font-size:13px;opacity:0.8;margin-bottom:12px">Вставьте строки из Excel: колонки Address, Keenetic, AnyDesk (Tab-разделитель)</p>
|
||
<div class="form-group">
|
||
<textarea name="tsv" rows="12" required placeholder="Address Keenetic AnyDesk
|
||
loftliliana https://loftliliana.netcraze.pro 1020687391" style="width:100%;font-family:monospace;font-size:12px"></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Логин (общий)</label>
|
||
<input type="text" name="login" value="admin">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Пароль (общий)</label>
|
||
<input type="password" name="password" required>
|
||
</div>
|
||
<button type="submit" class="btn-primary" style="width:100%">Импортировать</button>
|
||
</form>
|
||
<div id="importKeeneticResult" style="display:none;margin-top:12px;padding:12px;border-radius:8px;background:var(--bg-primary);font-size:13px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Keenetic Detail Modal -->
|
||
<div class="modal" id="keeneticDetailModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2 id="keeneticDetailTitle">📡 Router</h2>
|
||
<button class="btn-close" onclick="closeModal('keeneticDetailModal')">×</button>
|
||
</div>
|
||
<div id="keeneticDetailBody"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PC Download Modal -->
|
||
<div class="modal" id="pcDownloadModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2>📥 Скачать агент для ПК</h2>
|
||
<button class="btn-close" onclick="closeModal('pcDownloadModal')">×</button>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Имя компьютера (агента)</label>
|
||
<input type="text" id="pc-agent-name" placeholder="MyPC" value="">
|
||
</div>
|
||
<button class="btn-primary" onclick="generatePCCommand()" style="margin-bottom:16px">🔧 Сгенерировать команду</button>
|
||
<div id="pc-generated-cmd" style="display:none">
|
||
<div class="instr-card">
|
||
<h4>📋 Команда установки (PowerShell от Администратора)</h4>
|
||
<code id="pc-gen-code" style="cursor:pointer" onclick="copyToClipboard(this.textContent)" title="Нажмите чтобы скопировать"></code>
|
||
<p style="margin-top:8px;font-size:11px;color:var(--text-secondary)">Нажмите на команду чтобы скопировать</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Notification Settings Modal -->
|
||
<div class="modal" id="notifyModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2>🔔 Настройки уведомлений</h2>
|
||
<button class="btn-close" onclick="closeModal('notifyModal')">×</button>
|
||
</div>
|
||
|
||
<!-- Channel configs -->
|
||
<h3>📨 Каналы доставки</h3>
|
||
<div class="notify-channels">
|
||
<div class="instr-card">
|
||
<h4>📱 Telegram</h4>
|
||
<p style="font-size:12px;color:var(--text-secondary)">Настраивается в Настройках (⚙️) — Bot Token и Chat ID</p>
|
||
<div id="tg-status" style="margin-top:8px"></div>
|
||
<button class="btn-sm" onclick="testNotification('telegram')" style="margin-top:8px">🧪 Тест</button>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>📧 Email (SMTP)</h4>
|
||
<div class="form-group" style="margin-top:8px">
|
||
<label>SMTP сервер</label>
|
||
<input type="text" id="n-smtp-host" placeholder="smtp.gmail.com">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Порт</label>
|
||
<input type="number" id="n-smtp-port" value="587">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Email (логин)</label>
|
||
<input type="text" id="n-smtp-user" placeholder="user@gmail.com">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Пароль приложения</label>
|
||
<input type="password" id="n-smtp-pass" placeholder="App Password">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Получатель</label>
|
||
<input type="text" id="n-email-to" placeholder="alerts@example.com">
|
||
</div>
|
||
<button class="btn-sm" onclick="testNotification('email')" style="margin-top:4px">🧪 Тест</button>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>💬 WhatsApp (CallMeBot)</h4>
|
||
<p style="font-size:12px;color:var(--text-secondary);margin-bottom:8px">
|
||
1. Отправьте "I allow callmebot to send me messages" на <b>+34 644 71 85 23</b> в WhatsApp<br>
|
||
2. Получите apikey в ответном сообщении<br>
|
||
3. Введите данные ниже
|
||
</p>
|
||
<div class="form-group">
|
||
<label>Телефон (с кодом страны)</label>
|
||
<input type="text" id="n-wa-phone" placeholder="+79001234567">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>API Key</label>
|
||
<input type="text" id="n-wa-apikey" placeholder="От CallMeBot">
|
||
</div>
|
||
<button class="btn-sm" onclick="testNotification('whatsapp')" style="margin-top:4px">🧪 Тест</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Per-category toggles -->
|
||
<h3>📊 Какие уведомления отправлять</h3>
|
||
<div class="notify-matrix">
|
||
<table class="notify-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Категория</th>
|
||
<th>📱 Telegram</th>
|
||
<th>📧 Email</th>
|
||
<th>💬 WhatsApp</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>🖥 Серверы</td>
|
||
<td><input type="checkbox" id="n-servers-tg" checked></td>
|
||
<td><input type="checkbox" id="n-servers-email"></td>
|
||
<td><input type="checkbox" id="n-servers-wa"></td>
|
||
</tr>
|
||
<tr>
|
||
<td>💻 ПК</td>
|
||
<td><input type="checkbox" id="n-pc-tg" checked></td>
|
||
<td><input type="checkbox" id="n-pc-email"></td>
|
||
<td><input type="checkbox" id="n-pc-wa"></td>
|
||
</tr>
|
||
<tr>
|
||
<td>📦 Synology</td>
|
||
<td><input type="checkbox" id="n-synology-tg" checked></td>
|
||
<td><input type="checkbox" id="n-synology-email"></td>
|
||
<td><input type="checkbox" id="n-synology-wa"></td>
|
||
</tr>
|
||
<tr>
|
||
<td>🏠 Home Assistant</td>
|
||
<td><input type="checkbox" id="n-ha-tg" checked></td>
|
||
<td><input type="checkbox" id="n-ha-email"></td>
|
||
<td><input type="checkbox" id="n-ha-wa"></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<button class="btn-primary" onclick="saveNotificationSettings()" style="margin-top:20px">💾 Сохранить</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Settings Modal -->
|
||
<div class="modal" id="settingsModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 data-i18n="settings">Настройки</h2>
|
||
<button class="btn-close" onclick="closeModal('settingsModal')">×</button>
|
||
</div>
|
||
<form id="settingsForm">
|
||
<h3 data-i18n="auth">Авторизация</h3>
|
||
<div class="form-group">
|
||
<label data-i18n="username">Логин</label>
|
||
<input type="text" name="admin_login" id="set_login">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="newPassword">Новый пароль</label>
|
||
<input type="password" name="admin_password" id="set_password" placeholder="">
|
||
</div>
|
||
<h3 data-i18n="telegram">Telegram</h3>
|
||
<div class="form-group">
|
||
<label data-i18n="botToken">Bot Token</label>
|
||
<input type="text" name="telegram_bot_token" id="set_tg_token">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="chatId">Chat ID</label>
|
||
<input type="text" name="telegram_chat_id" id="set_tg_chat">
|
||
</div>
|
||
<h3 data-i18n="monitoring">Мониторинг</h3>
|
||
<div class="form-group">
|
||
<label data-i18n="pollInterval">Интервал опроса (сек)</label>
|
||
<input type="number" name="monitor_interval" id="set_interval" value="60">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="cpuThreshold">Порог CPU (%)</label>
|
||
<input type="number" name="alert_cpu_threshold" id="set_cpu" value="90">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="ramThreshold">Порог RAM (%)</label>
|
||
<input type="number" name="alert_ram_threshold" id="set_ram" value="90">
|
||
</div>
|
||
<div class="form-group">
|
||
<label data-i18n="diskThreshold">Порог Disk (%)</label>
|
||
<input type="number" name="alert_disk_threshold" id="set_disk" value="90">
|
||
</div>
|
||
<button type="submit" class="btn-primary" data-i18n="save">Сохранить</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Instructions Modal -->
|
||
<div class="modal" id="instructionsModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2 data-i18n="instructions_title">Инструкции и шпаргалки</h2>
|
||
<button class="btn-close" onclick="closeModal('instructionsModal')">×</button>
|
||
</div>
|
||
<div id="instructions-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SSH Terminal Modal -->
|
||
<div class="modal" id="sshModal" style="display:none">
|
||
<div class="modal-content modal-large">
|
||
<div class="modal-header">
|
||
<h2 id="ssh-title">SSH Terminal</h2>
|
||
<button class="btn-close" onclick="closeSSH()">×</button>
|
||
</div>
|
||
<div id="terminal-container"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Server Detail Modal -->
|
||
<div class="modal" id="serverDetailModal" style="display:none">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 id="detail-title">Server</h2>
|
||
<button class="btn-close" onclick="closeModal('serverDetailModal')">×</button>
|
||
</div>
|
||
<div id="detail-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Synology Detail Modal -->
|
||
<div class="modal" id="synDetailModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2 id="syn-detail-title">Synology</h2>
|
||
<button class="btn-close" onclick="closeModal('synDetailModal')">×</button>
|
||
</div>
|
||
<div id="syn-detail-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- HA Detail Modal -->
|
||
<div class="modal" id="haDetailModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2 id="ha-detail-title">Home Assistant</h2>
|
||
<button class="btn-close" onclick="closeModal('haDetailModal')">×</button>
|
||
</div>
|
||
<div id="ha-detail-content"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Synology Tunnel Setup Modal -->
|
||
<div class="modal" id="synTunnelModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2>🔗 Настройка туннеля для Synology</h2>
|
||
<button class="btn-close" onclick="closeModal('synTunnelModal')">×</button>
|
||
</div>
|
||
<div class="instructions-section">
|
||
<div class="instr-card" style="border-left:3px solid var(--accent)">
|
||
<h4>⚠️ Зачем нужен туннель?</h4>
|
||
<p>VPS не может напрямую подключиться к вашему Synology NAS — порт 5000 не доступен из интернета.
|
||
Туннель через ПК на той же сети решает эту проблему.</p>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>📋 Шаг 1 — Запустите на ПК в той же сети (PowerShell от Администратора)</h4>
|
||
<code id="syn-tunnel-cmd" style="cursor:pointer" onclick="copyToClipboard(this.textContent)" title="Нажмите чтобы скопировать">Загрузка...</code>
|
||
<p style="margin-top:8px;font-size:11px;color:var(--text-secondary)">Нажмите на команду чтобы скопировать</p>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>📊 Шаг 2 — Обновите Synology на дашборде</h4>
|
||
<p>После запуска туннеля нажмите "Обновить" на карточке Synology — статус должен стать ONLINE.</p>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>🔧 Управление туннелем</h4>
|
||
<ul class="cmd-list">
|
||
<li>Get-ScheduledTask 'VPS-Monitor-SynologyTunnel'</li>
|
||
<li>Stop-ScheduledTask 'VPS-Monitor-SynologyTunnel'</li>
|
||
<li>Unregister-ScheduledTask 'VPS-Monitor-SynologyTunnel'</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PC Setup Modal -->
|
||
<div class="modal" id="pcSetupModal" style="display:none">
|
||
<div class="modal-content modal-wide">
|
||
<div class="modal-header">
|
||
<h2>💻 Установка агента на ПК</h2>
|
||
<button class="btn-close" onclick="closeModal('pcSetupModal')">×</button>
|
||
</div>
|
||
<div class="instructions-section">
|
||
<div class="instr-card">
|
||
<h4>📥 Быстрая установка (PowerShell от Администратора)</h4>
|
||
<code id="pc-install-cmd">Set-ExecutionPolicy Bypass -Scope Process -Force; $ProgressPreference = 'SilentlyContinue'; (New-Object Net.WebClient).DownloadFile('http://77.239.126.123/static/downloads/install_agent.ps1', "$PWD\install_agent.ps1"); & "$PWD\install_agent.ps1" -ServerUrl 'http://77.239.126.123' -AgentName 'MyPC'</code>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>⚙️ Параметры</h4>
|
||
<p><b>-ServerUrl</b> — адрес сервера мониторинга<br>
|
||
<b>-AgentName</b> — имя ПК (по умолчанию hostname)<br>
|
||
<b>-Interval</b> — интервал отправки в секундах (по умолчанию 60)</p>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>📊 Что мониторится</h4>
|
||
<p>CPU, RAM, Disk (все диски), Network, GPU, Uptime, Top 5 процессов</p>
|
||
</div>
|
||
<div class="instr-card">
|
||
<h4>🔧 Управление</h4>
|
||
<ul class="cmd-list">
|
||
<li>Get-ScheduledTask 'VPS-Monitor-Agent'</li>
|
||
<li>Stop-ScheduledTask 'VPS-Monitor-Agent'</li>
|
||
<li>Start-ScheduledTask 'VPS-Monitor-Agent'</li>
|
||
<li>Unregister-ScheduledTask 'VPS-Monitor-Agent'</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="app-footer">
|
||
автор: <a href="https://github.com/andrey271192" target="_blank">GitHub</a> · <a href="https://boosty.to/iot_andrey" target="_blank">Boosty</a> · <a href="https://t.me/Iot_andrey" target="_blank">Поддержка</a> · <a href="https://t.me/Iot_andrey" target="_blank">@Iot_andrey</a>
|
||
</footer>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js"></script>
|
||
<script src="/static/js/app.js?v=20260529a"></script>
|
||
</body>
|
||
</html>
|