v1.8.4: единая стилистика — замена confirm/alert/prompt на кастомные модалки, SERVICE_STYLE_GUIDE.md, обновлен AGENTS.md
Tests / test (push) Has been cancelled
Tests / test-max-bot (push) Has been cancelled

This commit is contained in:
2026-06-02 20:40:24 +03:00
parent df34048e2a
commit e184e5fe79
23 changed files with 777 additions and 70 deletions
+37 -23
View File
@@ -8,19 +8,6 @@
.kb-table .active-badge { display:inline-block; padding:2px 8px; border-radius:4px; font-size:11px; font-weight:600; }
.kb-table .active-badge.yes { background:var(--success-bg, #d4edda); color:var(--success, #155724); }
.kb-table .active-badge.no { background:var(--danger-bg, #f8d7da); color:var(--danger, #721c24); }
.kb-modal { display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.4);
z-index:1000; align-items:center; justify-content:center; }
.kb-modal.open { display:flex; }
.kb-modal-content { background:var(--bg-card); border-radius:12px; padding:30px; width:600px; max-width:90vw;
max-height:80vh; overflow-y:auto; }
.kb-modal-content h3 { margin-bottom:20px; }
.form-group { margin-bottom:14px; }
.form-group label { display:block; font-weight:600; margin-bottom:4px; font-size:13px; color:var(--text-muted); }
.form-group input, .form-group textarea, .form-group select {
width:100%; padding:8px 12px; border:1px solid var(--border); border-radius:6px; font-size:14px;
}
.form-group textarea { min-height:100px; resize:vertical; }
.modal-actions { display:flex; gap:12px; margin-top:16px; }
.filter-bar { display:flex; gap:12px; margin-bottom:16px; align-items:center; flex-wrap:wrap; }
.filter-bar input, .filter-bar select { padding:8px 12px; border:1px solid var(--border); border-radius:6px; font-size:13px; }
</style>
@@ -60,9 +47,10 @@
</table>
</div>
<div class="kb-modal" id="kb-modal">
<div class="kb-modal-content">
<h3 id="modal-title">Новая карточка</h3>
<div class="modal-overlay" id="kb-modal">
<div class="modal" style="max-width:600px;">
<button type="button" class="modal-close" onclick="closeModal()"></button>
<h2 id="modal-title">Новая карточка</h2>
<form id="kb-form">
<div class="form-group">
<label>Категория</label>
@@ -84,10 +72,8 @@
<label>URL источника</label>
<input type="url" name="source_url" id="kb-source-url" placeholder="https://aegisone.ru/...">
</div>
<div class="form-group">
<label><input type="checkbox" name="is_active" id="kb-is-active" checked> Активная карточка</label>
</div>
<div class="modal-actions">
<div class="form-check"><input type="checkbox" name="is_active" id="kb-is-active" checked><label for="kb-is-active">Активная карточка</label></div>
<div class="modal-actions" style="justify-content:flex-end;">
<button type="submit" class="btn btn-primary">Сохранить</button>
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
</div>
@@ -95,6 +81,19 @@
</div>
</div>
<div class="modal-overlay" id="confirm-delete-kb">
<div class="modal" style="max-width:420px;">
<h2 style="font-size:16px;margin-bottom:8px;">Удалить карточку?</h2>
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
Карточка <strong id="delete-kb-name"></strong> будет удалена навсегда. Это действие нельзя отменить.
</p>
<div class="modal-actions" style="justify-content:flex-end;">
<button type="button" class="btn btn-danger" onclick="confirmDeleteKB()">Удалить</button>
<button type="button" class="btn" onclick="closeConfirmDeleteKB()">Отмена</button>
</div>
</div>
</div>
<script>
var categories = {};
var allCards = [];
@@ -126,7 +125,7 @@ function renderKB(cards){
'<td>' + catName + '</td>' +
'<td><span class="active-badge ' + activeClass + '">' + activeLabel + '</span></td>' +
'<td style="font-size:12px;">' + (c.source_url ? '<a href="' + c.source_url + '" target="_blank">ссылка</a>' : '—') + '</td>' +
'<td><button class="btn btn-sm" onclick="editCard(' + c.id + ')" title="Редактировать">✏️</button> <button class="btn btn-sm" onclick="deleteCard(' + c.id + ')" style="color:#dc3545;" title="Удалить">🗑</button></td>' +
'<td><button class="btn btn-secondary btn-sm" onclick="editCard(' + c.id + ')" title="Редактировать"></button> <button class="btn btn-danger btn-sm" onclick="openConfirmDeleteKB(' + c.id + ', \'' + escapeHtml(c.question).replace(/'/g, "\\'") + '\')" title="Удалить"></button></td>' +
'</tr>';
});
tbody.innerHTML = html;
@@ -173,8 +172,23 @@ function editCard(id){
document.getElementById('kb-modal').classList.add('open');
}
function deleteCard(id){
if(!confirm('Удалить карточку?')) return;
var deleteKBId = null;
function openConfirmDeleteKB(id, name){
deleteKBId = id;
document.getElementById('delete-kb-name').textContent = name || '#' + id;
document.getElementById('confirm-delete-kb').classList.add('open');
}
function closeConfirmDeleteKB(){
document.getElementById('confirm-delete-kb').classList.remove('open');
deleteKBId = null;
}
function confirmDeleteKB(){
if(!deleteKBId) return;
var id = deleteKBId;
closeConfirmDeleteKB();
fetch('/api/bot/kb/' + id, { method: 'DELETE' }).then(function(r){ return r.json() }).then(function(d){
if(d.ok) { showNotification('Карточка удалена', 'success'); loadKB(); }
else showNotification('Ошибка удаления', 'error');