diff --git a/web/api.py b/web/api.py index ce01a70..d2a2f1c 100644 --- a/web/api.py +++ b/web/api.py @@ -116,14 +116,14 @@ def normalize_ban(row: dict) -> dict: @app.get("/api/messages") async def api_messages(limit: int = Query(default=50, ge=1, le=500)): - msgs = await Message.filter(manually_deleted=False).order_by("-created_at").limit(limit).values() + msgs = await Message.all().order_by("-created_at").limit(limit).values() return JSONResponse(json_safe([normalize_message(m) for m in msgs])) @app.get("/api/chat") async def api_chat(limit: int = Query(default=100, ge=1, le=500)): """兼容旧前端:返回聊天记录。""" - msgs = await Message.filter(manually_deleted=False).order_by("-created_at").limit(limit).values() + msgs = await Message.all().order_by("-created_at").limit(limit).values() return JSONResponse(json_safe([normalize_message(m) for m in msgs])) @@ -229,7 +229,7 @@ async def api_delete_message(message_id: int): "chat_id": rec.chat_id, "deleted_at": rec.deleted_at, })) - return JSONResponse({"ok": True, "tg_deleted": tg_deleted, "tg_error": tg_error}) + return JSONResponse(json_safe({"ok": True, "tg_deleted": tg_deleted, "tg_error": tg_error, "deleted_at": rec.deleted_at})) @app.get("/api/scores") diff --git a/web/static/index.html b/web/static/index.html index 43294b1..88b7e5a 100644 --- a/web/static/index.html +++ b/web/static/index.html @@ -68,6 +68,8 @@ .chat-item { padding: 8px 10px; border-bottom: 1px solid #edf2f7; border-radius: 8px; transition: background .15s; } .chat-item:hover { background: #f8fafc; } .chat-item.spam { background: #fff1f2; border-left: 3px solid #ef4444; } + .chat-item.deleted { background: #f8fafc; border-left: 3px solid #94a3b8; opacity: .72; } + .chat-item.deleted .text { color: #94a3b8; text-decoration: line-through; } .chat-item .meta { display: flex; justify-content: space-between; gap: 8px; margin-bottom: 4px; } .chat-item .meta-right { display: flex; align-items: center; gap: 6px; flex-shrink: 0; } .chat-item .user { font-weight: 700; color: #2563eb; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @@ -170,16 +172,18 @@
💬等待消息...
-
+
@{{ item.username || item.first_name || 'unknown' }} ({{ item.user_id }}) #{{ item.msg_id || '-' }} · {{ formatTime(item.time) }} - 删除 + 手动删除 + 删除
{{ item.text }}
垃圾:{{ item.reason || item.spam_reason }} + 已手动删除 · {{ formatTime(item.deleted_at) }}
@@ -286,7 +290,12 @@ new Vue({ }) es.addEventListener('chat_delete', (e) => { const data = JSON.parse(e.data) - this.chatLogs = this.chatLogs.filter(m => m.id !== data.id) + const item = this.chatLogs.find(m => m.id === data.id) + if (item) { + this.$set(item, 'deleted', true) + this.$set(item, 'manually_deleted', true) + this.$set(item, 'deleted_at', data.deleted_at) + } this.loadStats() }) es.addEventListener('ban', (e) => { @@ -362,8 +371,10 @@ new Vue({ try { const data = await (await fetch(`/api/messages/${item.id}/delete`, { method: 'POST' })).json() if (data.ok) { - this.chatLogs = this.chatLogs.filter(m => m.id !== item.id) - this.$message.success('✅ 已删除并标记') + this.$set(item, 'deleted', true) + this.$set(item, 'manually_deleted', true) + this.$set(item, 'deleted_at', data.deleted_at || new Date().toISOString()) + this.$message.success('✅ 已标记为手动删除') this.loadStats() } else { this.$message.error(`❌ 删除失败: ${data.error}`)