172 lines
7.2 KiB
HTML
172 lines
7.2 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Инфраструктура - МКД ЛенКом 37{% endblock %}
|
||
{% block nav_infra %}active{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="mb-3">
|
||
<h4 class="mb-1" style="font-size: 16px; font-weight: bold;">Мониторинг инфраструктуры и сервисов</h4>
|
||
<div class="small text-muted">Состояние сетевых узлов, замеры интернет-канала и статус фоновых пайплайнов</div>
|
||
</div>
|
||
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-12">
|
||
<div class="card">
|
||
<div class="card-header d-flex justify-content-between align-items-center">
|
||
<span>ТЕСТЫ СКОРОСТИ ИНТЕРНЕТ-КАНАЛА (ТАРИФ 150 МБИТ/С)</span>
|
||
<button id="runSpeedtestBtn" class="btn-unix">
|
||
<i class="bi bi-play-fill"></i> Запустить замер сейчас
|
||
</button>
|
||
</div>
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive">
|
||
<table class="table mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th>Дата и время</th>
|
||
<th>Download (Мбит/с)</th>
|
||
<th>Upload (Мбит/с)</th>
|
||
<th>Ping (мс)</th>
|
||
<th>Сервер замера</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for test in speedtests %}
|
||
<tr>
|
||
<td>{{ test.timestamp }}</td>
|
||
<td><b>{{ test.download }}</b></td>
|
||
<td><b>{{ test.upload }}</b></td>
|
||
<td>{{ test.ping }}</td>
|
||
<td class="text-muted">{{ test.server_name }}</td>
|
||
</tr>
|
||
{% else %}
|
||
<tr>
|
||
<td colspan="5" class="text-center text-muted py-3">Данных замеров пока нет</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<div class="card h-100">
|
||
<div class="card-header">СЕТЕВЫЕ УЗЛЫ И ХОСТЫ</div>
|
||
<div class="card-body p-0">
|
||
<table class="table mb-0">
|
||
<tbody>
|
||
<tr>
|
||
<td style="width: 140px;"><b>NanoPi R3S</b></td>
|
||
<td>192.168.10.1 (Роутер / Шлюз)</td>
|
||
<td class="text-end"><span class="badge-status badge-success">ONLINE</span></td>
|
||
</tr>
|
||
<tr>
|
||
<td><b>Synology NAS</b></td>
|
||
<td>192.168.10.105 (Хранилище / PostgreSQL)</td>
|
||
<td class="text-end"><span class="badge-status badge-success">ONLINE</span></td>
|
||
</tr>
|
||
<tr>
|
||
<td><b>DockerServer</b></td>
|
||
<td>192.168.10.116 (Domovoy / Maya Bot)</td>
|
||
<td class="text-end"><span class="badge-status badge-success">ONLINE</span></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<div class="card h-100">
|
||
<div class="card-header d-flex justify-content-between align-items-center">
|
||
<span>ГИС ЖКХ & СБОРКА АРХИВА</span>
|
||
<span id="gisStatusBadge" class="badge-status">СТАТУС: ПРОВЕРКА</span>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="d-flex gap-2 mb-2">
|
||
<button id="runGisHarvestBtn" class="btn-unix btn-unix-primary flex-grow-1">
|
||
<i class="bi bi-cloud-download"></i> Запустить сборку ГИС ЖКХ
|
||
</button>
|
||
<button id="refreshGisStatusBtn" class="btn-unix">
|
||
Обновить статус
|
||
</button>
|
||
</div>
|
||
<div class="small text-muted mb-1">Лог выполнения процесса:</div>
|
||
<pre id="gisLogs" style="height: 160px; overflow-y: scroll; background-color: #ffffff; border: 1px solid var(--border-color); font-size: 11px;"></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.getElementById('runSpeedtestBtn').addEventListener('click', async function() {
|
||
const btn = this;
|
||
btn.disabled = true;
|
||
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Замер (до 60 сек)...';
|
||
|
||
try {
|
||
const response = await fetch('/api/infra/run_speedtest', { method: 'POST' });
|
||
const result = await response.json();
|
||
alert(result.message);
|
||
location.reload();
|
||
} catch (e) {
|
||
alert('Ошибка: ' + e);
|
||
} finally {
|
||
btn.disabled = false;
|
||
btn.innerHTML = '<i class="bi bi-play-fill"></i> Запустить замер сейчас';
|
||
}
|
||
});
|
||
|
||
document.getElementById('runGisHarvestBtn').addEventListener('click', async function() {
|
||
const btn = this;
|
||
if (!confirm('Запустить сборку ГИС ЖКХ? Это займет некоторое время.')) return;
|
||
|
||
btn.disabled = true;
|
||
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Процесс запущен...';
|
||
|
||
try {
|
||
const response = await fetch('/api/infra/run_gis_harvest', { method: 'POST' });
|
||
const result = await response.json();
|
||
alert(result.message);
|
||
} catch (e) {
|
||
alert('Ошибка: ' + e);
|
||
} finally {
|
||
btn.disabled = false;
|
||
btn.innerHTML = '<i class="bi bi-cloud-download"></i> Запустить сборку ГИС ЖКХ';
|
||
refreshGisStatus();
|
||
}
|
||
});
|
||
|
||
async function refreshGisStatus() {
|
||
const badge = document.getElementById('gisStatusBadge');
|
||
const logs = document.getElementById('gisLogs');
|
||
|
||
try {
|
||
const response = await fetch('/api/infra/gis_status');
|
||
const data = await response.json();
|
||
|
||
if (data.alive) {
|
||
badge.className = 'badge-status badge-success';
|
||
badge.innerText = 'РАБОТАЕТ';
|
||
} else {
|
||
badge.className = 'badge-status';
|
||
badge.innerText = 'ОЖИДАНИЕ';
|
||
}
|
||
|
||
logs.innerText = data.log || 'Лог чист';
|
||
logs.scrollTop = logs.scrollHeight;
|
||
} catch (e) {
|
||
badge.className = 'badge-status badge-danger';
|
||
badge.innerText = 'ОШИБКА';
|
||
}
|
||
}
|
||
|
||
document.getElementById('refreshGisStatusBtn').addEventListener('click', refreshGisStatus);
|
||
window.addEventListener('load', refreshGisStatus);
|
||
setInterval(refreshGisStatus, 30000);
|
||
</script>
|
||
{% endblock %}
|