From 14a07e741e2d8daf96d1134e70d7a5e9b4cbc419 Mon Sep 17 00:00:00 2001 From: kyx236 Date: Sun, 1 Feb 2026 06:02:39 +0800 Subject: [PATCH] feat: add a service for periodic cleanup of error accounts based on configuration. --- backend/cmd/main.go | 25 +++++++++++++++++++++-- backend/internal/api/error_cleaner.go | 4 ---- backend/internal/logger/logger.go | 19 +++++++++++++++++ frontend/src/components/LiveLogViewer.tsx | 22 ++++++++++++++++---- frontend/src/pages/Cleaner.tsx | 25 +++++++++++++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 9393f1e..b6dd95f 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -104,8 +104,9 @@ func startServer(cfg *config.Config) { // 日志 API mux.HandleFunc("/api/logs", api.CORS(handleGetLogs)) mux.HandleFunc("/api/logs/clear", api.CORS(handleClearLogs)) - mux.HandleFunc("/api/logs/query", api.CORS(handleQueryLogs)) // 按模块查询日志 - mux.HandleFunc("/api/logs/stream", handleLogStream) // SSE 实时日志 + mux.HandleFunc("/api/logs/clear-module", api.CORS(handleClearLogsByModule)) // 按模块清除日志 + mux.HandleFunc("/api/logs/query", api.CORS(handleQueryLogs)) // 按模块查询日志 + mux.HandleFunc("/api/logs/stream", handleLogStream) // SSE 实时日志 // S2A 代理 API mux.HandleFunc("/api/s2a/test", api.CORS(handleS2ATest)) @@ -296,6 +297,26 @@ func handleClearLogs(w http.ResponseWriter, r *http.Request) { api.Success(w, map[string]string{"message": "日志已清空"}) } +// handleClearLogsByModule POST /api/logs/clear-module?module=cleaner +func handleClearLogsByModule(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + api.Error(w, http.StatusMethodNotAllowed, "仅支持 POST") + return + } + + module := r.URL.Query().Get("module") + if module == "" { + api.Error(w, http.StatusBadRequest, "缺少 module 参数") + return + } + + cleared := logger.ClearLogsByModule(module) + api.Success(w, map[string]interface{}{ + "message": fmt.Sprintf("已清除 %d 条 %s 日志", cleared, module), + "cleared": cleared, + }) +} + // handleQueryLogs GET /api/logs/query?module=cleaner&page=1&page_size=5 func handleQueryLogs(w http.ResponseWriter, r *http.Request) { module := r.URL.Query().Get("module") diff --git a/backend/internal/api/error_cleaner.go b/backend/internal/api/error_cleaner.go index 1320a74..53e4777 100644 --- a/backend/internal/api/error_cleaner.go +++ b/backend/internal/api/error_cleaner.go @@ -89,13 +89,10 @@ func checkAndCleanErrors() { } if len(errorAccounts) == 0 { - logger.Info("没有错误账号需要清理", "", "cleaner") lastCleanTime = time.Now() return } - logger.Info(fmt.Sprintf("找到 %d 个错误账号,开始删除...", len(errorAccounts)), "", "cleaner") - success := 0 failed := 0 @@ -106,7 +103,6 @@ func checkAndCleanErrors() { logger.Warning(fmt.Sprintf("删除账号失败: ID=%d, Email=%s, Error=%v", account.ID, account.Email, err), account.Email, "cleaner") } else { success++ - logger.Success(fmt.Sprintf("删除账号成功: ID=%d, Email=%s", account.ID, account.Email), account.Email, "cleaner") } } diff --git a/backend/internal/logger/logger.go b/backend/internal/logger/logger.go index eba6bb1..f7ad706 100644 --- a/backend/internal/logger/logger.go +++ b/backend/internal/logger/logger.go @@ -242,3 +242,22 @@ func ClearLogs() { defer logsMu.Unlock() logs = make([]LogEntry, 0, 1000) } + +// ClearLogsByModule 按模块清除日志 +func ClearLogsByModule(module string) int { + logsMu.Lock() + defer logsMu.Unlock() + + // 过滤掉指定模块的日志 + var newLogs []LogEntry + cleared := 0 + for _, log := range logs { + if log.Module != module { + newLogs = append(newLogs, log) + } else { + cleared++ + } + } + logs = newLogs + return cleared +} diff --git a/frontend/src/components/LiveLogViewer.tsx b/frontend/src/components/LiveLogViewer.tsx index 1b30317..2004e15 100644 --- a/frontend/src/components/LiveLogViewer.tsx +++ b/frontend/src/components/LiveLogViewer.tsx @@ -131,8 +131,22 @@ export default function LiveLogViewer({ } } - const handleClear = () => { - setLogs([]) + const handleClear = async () => { + if (!confirm('确定要清空所有日志吗?此操作不可撤销。')) { + return + } + try { + const res = await fetch('/api/logs/clear', { method: 'POST' }) + const data = await res.json() + if (data.code === 0) { + setLogs([]) + pausedLogsRef.current = [] + } else { + alert('清空日志失败: ' + (data.message || '未知错误')) + } + } catch (e) { + alert('清空日志失败: ' + (e instanceof Error ? e.message : '网络错误')) + } } return ( @@ -161,8 +175,8 @@ export default function LiveLogViewer({ diff --git a/frontend/src/pages/Cleaner.tsx b/frontend/src/pages/Cleaner.tsx index 60faa02..b32bc4e 100644 --- a/frontend/src/pages/Cleaner.tsx +++ b/frontend/src/pages/Cleaner.tsx @@ -396,6 +396,31 @@ export default function Cleaner() { 共 {logTotal} 条 +