Control Server (FastAPI) с WEB UI (Jinja2 + HTMX) и JSON API для группового администрирования устройств RouterOS 7 через REST. - Устройства: список, статус (модель, канал, версии ROS/FW, uptime, доступные обновления), примечания, пароли шифруются (Fernet); фоновый опрос каждые 30 с и быстрое обнаружение недоступности (таймаут соединения 4 с). - Группы устройств и фильтры (устройства, резервные копии). - Резервные копии: .backup и .rsc (show-sensitive) создаются через REST, скачиваются сервером и загружаются в S3 (Yandex Object Storage). - Обновление ROS/FW и выбор канала, групповые операции задачами. - Интерфейс по утверждённому макету: светлая/тёмная темы, окна, шрифты IBM Plex локально. Docker Compose, SQLite в томе, минимальный набор тестов. - Планы и итоги каждого изменения — в docs/changes/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
32 lines
1.8 KiB
HTML
32 lines
1.8 KiB
HTML
{% import "_ui.html" as ui %}
|
||
{% set running = jobs|selectattr("status", "in", ["pending", "running"])|list|length %}
|
||
{% set done = jobs|selectattr("status", "equalto", "done")|list|length %}
|
||
{% set failed = jobs|selectattr("status", "equalto", "failed")|list|length %}
|
||
<div class="section-head">
|
||
<h2>Задачи</h2>
|
||
{% if running %}<span class="badge run">{{ running }} выполняется</span>{% endif %}
|
||
{% if done %}<span class="badge">{{ done }} завершено</span>{% endif %}
|
||
{% if failed %}<span class="badge bad">{{ failed }} с ошибкой</span>{% endif %}
|
||
</div>
|
||
{% if flash %}<p class="err">{{ flash }}</p>{% endif %}
|
||
<div class="card">
|
||
<table class="grid jobs">
|
||
<colgroup><col style="width:56px"><col style="width:16%"><col style="width:16%"><col style="width:130px"><col><col style="width:150px"></colgroup>
|
||
<thead><tr><th>#</th><th>Устройство</th><th>Операция</th><th>Статус</th><th>Сообщение</th><th>Создана (UTC)</th></tr></thead>
|
||
<tbody>
|
||
{% for j in jobs %}
|
||
<tr>
|
||
<td class="muted">{{ j.id }}</td>
|
||
<td style="font-weight:500">{{ j.device_name }}</td>
|
||
<td>{{ {"backup": "Бэкап", "ros_update": "Обновление ROS", "fw_update": "Обновление FW"}.get(j.type, j.type) }}</td>
|
||
<td><span class="badge {{ {'running': 'run', 'done': 'ok', 'failed': 'bad'}.get(j.status, '') }}">{{ {"pending": "В очереди", "running": "Выполняется", "done": "Готово", "failed": "Ошибка"}.get(j.status, j.status) }}</span></td>
|
||
<td class="msg">{{ j.message }}</td>
|
||
<td class="c-small">{{ j.created_at|dt }}</td>
|
||
</tr>
|
||
{% else %}
|
||
<tr><td colspan="6" class="empty">Задач пока нет.</td></tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|