feat(notifications): центр уведомлений о системных событиях

Добавлена система уведомлений о системных и фоновых событиях (новые записи
журнала, обработка фото, авто-проверка текста, блокировки IP, бэкапы).

- backend (server.js, worker.js):
  - каталог NOTIFY_TYPES с метаданными и уровнями
  - таблицы notifications и notification_reads в db/init.sql и db/migration.sql
  - SSE-стрим GET /api/notifications/stream через Redis pub/sub с in-memory fallback
  - REST API: список, счётчик непрочитанных, отметка о прочтении, удаление, очистка
  - настройки уведомлений в settings (notify_enabled, notify_retention_days, notify_<тип>)
  - автоматическая очистка старых уведомлений по расписанию
- frontend:
  - колокольчик со счётчиком непрочитанных в шапке (admin.js)
  - страница списка уведомлений public/notifications.html и public/js/notifications.js
  - секция настроек уведомлений в public/settings.html и public/js/settings.js
  - стили для уведомлений в public/admin.css
- тесты и документация:
  - добавлены проверки в api.smoketest.js
  - обновлены README.md и AGENTS.md
This commit is contained in:
dev
2026-09-27 23:34:47 +03:00
parent f31b8deea2
commit 2afe676969
13 changed files with 1158 additions and 4 deletions
+24
View File
@@ -26,6 +26,7 @@
<a href="#sec-share" data-nav="sec-share"><i data-lucide="link"></i> Публичные ссылки</a>
<a href="#sec-form" data-nav="sec-form"><i data-lucide="file-text"></i> Форма ответа</a>
<a href="#sec-photo" data-nav="sec-photo"><i data-lucide="camera"></i> Фото</a>
<a href="#sec-notify" data-nav="sec-notify"><i data-lucide="bell"></i> Уведомления</a>
<a href="#sec-ai" data-nav="sec-ai"><i data-lucide="bot"></i> ИИ</a>
<a href="#sec-backup" data-nav="sec-backup"><i data-lucide="database"></i> Бэкапы</a>
<a href="#sec-trash" data-nav="sec-trash"><i data-lucide="trash-2"></i> Корзина</a>
@@ -274,6 +275,29 @@
</div>
</div>
<div class="settings-card wide" id="sec-notify">
<div class="card-head">
<div class="ic"><i data-lucide="bell"></i></div>
<h3>Уведомления</h3>
<button class="icon-btn" id="notifyTestBtn" type="button" title="Отправить тестовое уведомление" aria-label="Тестовое уведомление"><i data-lucide="send"></i></button>
</div>
<p class="hint">Уведомления собираются в «колокольчике» админ-панели и на странице «Уведомления». Здесь выбирается, о каких событиях сообщать: новые записи журнала, обработка фото нейросетью, блокировки IP, бэкапы и другое.</p>
<label class="toggle">
<input type="checkbox" id="notifyEnabled">
<span class="toggle-track"><span class="toggle-thumb"></span></span>
<span class="toggle-text"><b>Уведомления включены</b><small>Общий выключатель: при снятии галочки не создаётся ни одно уведомление</small></span>
</label>
<div class="settings-field">
<label for="notifyRetentionDays">Хранение уведомлений</label>
<div class="unit-row">
<input type="number" id="notifyRetentionDays" class="settings-input" min="1" max="365" step="1">
<span class="unit">дней</span>
</div>
<span class="hint">От 1 до 365 дней, старые уведомления удаляются автоматически</span>
</div>
<div class="notify-types" id="notifyTypes"><span class="hint">Загрузка…</span></div>
</div>
<div class="settings-card" id="sec-bans">
<div class="card-head">
<div class="ic"><i data-lucide="shield-off"></i></div>