diff --git a/public/admin.css b/public/admin.css
index 56412a2..19530d5 100644
--- a/public/admin.css
+++ b/public/admin.css
@@ -339,6 +339,8 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;b
.sys-item{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:4px 0}
.sys-label{font-size:.82rem;color:var(--muted)}
.sys-value{font-size:.9rem;font-weight:600;color:var(--text);text-align:right;word-break:break-word}
+.lucide-inline{display:inline-flex;align-items:center;vertical-align:-2px}
+.lucide-inline svg{width:14px;height:14px;flex-shrink:0}
.sys-details{margin-top:8px;padding-top:8px;border-top:1px solid var(--border)}
.sys-details summary{cursor:pointer;font-size:.75rem;color:var(--muted);font-weight:600}
.sys-table-list{margin-top:8px;display:flex;flex-direction:column;gap:4px}
diff --git a/public/js/audit.js b/public/js/audit.js
index 5f9c1db..b4eba53 100644
--- a/public/js/audit.js
+++ b/public/js/audit.js
@@ -4,6 +4,8 @@ const ACTION_LABELS = {
'user.create': 'Создан пользователь',
'user.update': 'Изменён пользователь',
'user.delete': 'Удалён пользователь',
+ 'ip.ban': 'Заблокирован IP-адрес',
+ 'ip.unban': 'Разблокирован IP-адрес',
'group.create': 'Создана группа',
'group.update': 'Изменена группа',
'group.delete': 'Удалена группа',
diff --git a/public/js/bans.js b/public/js/bans.js
index b7b6d86..b8e2b7e 100644
--- a/public/js/bans.js
+++ b/public/js/bans.js
@@ -49,43 +49,18 @@ function renderPage() {
renderPager(document.getElementById('pager'), page, Math.max(1, Math.ceil(allBans.length / PAGE_SIZE)), p => { page = p; renderPage(); });
}
-function askUnban(ip) {
- const old = document.getElementById('unbanConfirmRow');
- if (old) old.remove();
- const tr = document.createElement('tr');
- tr.id = 'unbanConfirmRow';
- tr.innerHTML = `
-
- Разблокировать ${esc(ip)}?
-
-
- | `;
- tr.querySelector('#unbanYes').addEventListener('click', () => doUnban(ip));
- tr.querySelector('#unbanNo').addEventListener('click', () => tr.remove());
- document.getElementById('bansBody').appendChild(tr);
- tr.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
-}
-
async function doUnban(ip) {
+ const ban = allBans.find(b => b.ip === ip) || {};
+ if (!confirm(`Удалить IP ${ip} из блокировки (${reasonLabel(ban.reason)})?`)) return;
const res = await fetch(`${API}/api/bans/${encodeURIComponent(ip)}`, { method: 'DELETE', headers: hdr() });
- if (res.ok) showToast('IP разблокирован: ' + ip);
+ if (res.ok) showToast('IP удалён из блокировки: ' + ip);
else showToast('Ошибка разблокировки');
- document.getElementById('unbanConfirmRow')?.remove();
loadBans();
}
document.getElementById('bansBody').addEventListener('click', e => {
const ip = e.target.closest('[data-unban]')?.dataset.unban;
- if (ip) askUnban(ip);
-});
-
-document.getElementById('bansBody').addEventListener('click', async e => {
- const ip = e.target.closest('[data-unban]')?.dataset.unban;
- if (!ip) return;
- const res = await fetch(`${API}/api/bans/${encodeURIComponent(ip)}`, { method: 'DELETE', headers: hdr() });
- if (res.ok) showToast('IP разблокирован: ' + ip);
- else showToast('Ошибка разблокировки');
- loadBans();
+ if (ip) doUnban(ip);
});
function openBanModal() {
diff --git a/public/js/worker.js b/public/js/worker.js
index fa50f6c..716ab8e 100644
--- a/public/js/worker.js
+++ b/public/js/worker.js
@@ -77,7 +77,7 @@ function renderCards() {
Модель
Модель${esc(state.model)}
-
Сервис${svc.reachable ? '✅ доступен' : '❌ недоступен'}
+
Сервис${svc.reachable ? ' доступен' : ' недоступен'}
Отклик${svc.latency_ms !== undefined ? svc.latency_ms + ' мс' : '—'}
Адрес${esc(state.ai_url || '')}
${svc.error ? `
${esc(svc.error)}
` : ''}
@@ -149,7 +149,7 @@ function renderRecent() {
${esc(r.student_name)} |
${esc(r.group_name || '')} |
${statusBadge(r.ai_status)} |
-
${r.changed ? '✏️ исправлен' : '—'} |
+
${r.changed ? ' исправлен' : '—'} |
|
`).join('');
}
@@ -175,6 +175,7 @@ function render() {
renderPending();
renderRecent();
renderErrors();
+ renderIcons();
}
async function load() {
diff --git a/public/worker.html b/public/worker.html
index 27910d5..4889850 100644
--- a/public/worker.html
+++ b/public/worker.html
@@ -36,7 +36,7 @@
Записи, ожидающие проверки моделью. Обновляются автоматически.
@@ -53,7 +53,7 @@
@@ -79,7 +79,7 @@
Записи, которые не удалось обработать после всех попыток. Нажмите «Перепроверить ошибки», чтобы запустить их снова.