feat(chat): скрытие и плановое удаление диалогов
Админ может скрыть диалог тьютора (мягкое удаление), снять скрытие, отменить плановое удаление или удалить диалог физически через TTL общей настройки корзины. - chat_threads: deleted_at, purge_at (init.sql, migration.sql, ensureChatTables) - маршруты hide / restore / unschedule / permanent под requireAdmin + аудит - purgeScheduledDeletions() + hardDeleteChatThread() с safeUnlink по вложениям - скрытые диалоги видны тьютору как обычно; новое сообщение тьютора авто-возвращает диалог в список (thread_update по SSE) - UI: кнопка «Скрытые» с бейджем и действия в карточке треда - бэкап: deleted_at/purge_at в normalizeRestoreData
This commit is contained in:
+20
-1
@@ -930,13 +930,32 @@ body.report-card-open .report-fields{display:flex}
|
||||
.chat-thread-preview{font-size:.78rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.chat-off{font-size:.65rem;color:var(--muted);border:1px solid var(--border);border-radius:5px;padding:1px 5px;flex-shrink:0}
|
||||
.chat-thread-badge{min-width:18px;height:18px;padding:0 6px;border-radius:999px;background:#ef4444;color:#fff;font-size:.65rem;font-weight:700;line-height:18px;text-align:center;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center}
|
||||
.chat-side-toggle{padding:7px 12px;font-size:.8rem;display:inline-flex;align-items:center;gap:6px}
|
||||
.chat-side-toggle svg{width:14px;height:14px}
|
||||
.chat-side-toggle.on{background:rgba(37,99,235,.1);border-color:var(--accent);color:var(--accent)}
|
||||
.chat-hidden-count{min-width:16px;height:16px;padding:0 5px;border-radius:999px;background:var(--muted);color:var(--card);font-size:.62rem;font-weight:700;line-height:16px;text-align:center}
|
||||
.chat-side-toggle.on .chat-hidden-count{background:var(--accent);color:#fff}
|
||||
.chat-side-hint{padding:9px 14px;border-bottom:1px solid var(--border);background:var(--bg);color:var(--muted);font-size:.72rem;line-height:1.4}
|
||||
.chat-side-hint[hidden]{display:none}
|
||||
.chat-thread-acts{display:flex;align-items:center;gap:4px;margin-left:auto;align-self:center;opacity:0;transition:opacity .15s}
|
||||
.chat-thread:hover .chat-thread-acts,.chat-thread:focus-visible .chat-thread-acts,.chat-thread.active .chat-thread-acts{opacity:1}
|
||||
.chat-act{width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;background:var(--bg);border:1px solid var(--border);border-radius:8px;color:var(--muted);cursor:pointer;padding:0;flex-shrink:0}
|
||||
.chat-act:hover{color:var(--accent);border-color:var(--accent);background:rgba(37,99,235,.07)}
|
||||
.chat-act:hover svg{stroke:var(--accent)}
|
||||
.chat-act-danger:hover{color:#ef4444;border-color:#ef4444;background:rgba(239,68,68,.08)}
|
||||
.chat-act-danger:hover svg{stroke:#ef4444}
|
||||
.chat-act svg{width:14px;height:14px}
|
||||
.chat-thread.is-hidden .chat-thread-avatar{opacity:.5}
|
||||
.chat-thread.is-hidden .chat-thread-name,.chat-thread.is-hidden .chat-thread-preview{opacity:.65}
|
||||
.chat-hidden-tag{border-color:rgba(239,68,68,.35);color:#ef4444}
|
||||
@media(hover:none){.chat-thread-acts{opacity:1}}
|
||||
.chat-pane{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);min-height:420px;display:flex;flex-direction:column;overflow:hidden}
|
||||
.chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:70px 20px;text-align:center;color:var(--muted)}
|
||||
.chat-empty svg{width:34px;height:34px;opacity:.4}
|
||||
.chat-empty-title{font-size:.95rem;font-weight:600;color:var(--text)}
|
||||
.chat-empty-sub{font-size:.82rem}
|
||||
.chat-main{display:flex;flex-direction:column;min-height:520px}
|
||||
.chat-side[hidden],.chat-empty[hidden],.chat-main[hidden],.chat-attach-list[hidden],.chat-new-btn[hidden]{display:none}
|
||||
.chat-side[hidden],.chat-empty[hidden],.chat-main[hidden],.chat-attach-list[hidden],.chat-new-btn[hidden],.chat-side-toggle[hidden],.chat-hidden-count[hidden]{display:none}
|
||||
.chat-head{display:flex;align-items:center;gap:11px;padding:12px 16px;border-bottom:1px solid var(--border)}
|
||||
.chat-head .grow{flex:1}
|
||||
.chat-avatar{width:36px;height:36px;border-radius:10px;background:rgba(37,99,235,.1);color:var(--accent);display:flex;align-items:center;justify-content:center;font-weight:700;flex-shrink:0}
|
||||
|
||||
Reference in New Issue
Block a user