From 7954aeaf59c01a8dd2bbfd9e50b19f45392698c8 Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Wed, 10 Dec 2025 20:20:44 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1=E6=97=A5=E5=BF=97=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加用户清空日志按钮 - 添加30天自动清理定时任务执行日志 - 简化日志API代码,移除调试日志 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- app.py | 69 +++++++++++++++++--------------------------- database.py | 24 +++++++++++++++ templates/index.html | 21 ++++++++++++++ 3 files changed, 71 insertions(+), 43 deletions(-) diff --git a/app.py b/app.py index fb93f61..d6e415d 100755 --- a/app.py +++ b/app.py @@ -2816,9 +2816,9 @@ def scheduled_task_worker(): print(f"[定时清理] 清理验证码出错: {str(e)}") def cleanup_old_data(): - """清理7天前的截图和日志""" + """清理旧数据:7天前截图和任务日志,30天前操作日志和定时任务执行日志""" try: - print(f"[定时清理] 开始清理7天前的数据...") + print(f"[定时清理] 开始清理旧数据...") # 清理7天前的任务日志 deleted_logs = database.delete_old_task_logs(7) @@ -2827,6 +2827,10 @@ def scheduled_task_worker(): # 清理30天前的操作日志 deleted_operation_logs = database.clean_old_operation_logs(30) print(f"[定时清理] 已删除 {deleted_operation_logs} 条操作日志") + + # 清理30天前的定时任务执行日志 + deleted_schedule_logs = database.clean_old_schedule_logs(30) + print(f"[定时清理] 已删除 {deleted_schedule_logs} 条定时任务执行日志") # 清理7天前的截图 deleted_screenshots = 0 if os.path.exists(SCREENSHOTS_DIR): @@ -3278,53 +3282,32 @@ def run_schedule_now_api(schedule_id): def get_schedule_logs_api(schedule_id): """获取定时任务执行日志""" try: - print(f"[API日志] 开始处理日志请求 - schedule_id={schedule_id}, user_id={current_user.id}") - - # 先验证定时任务是否存在和权限 - try: - schedule = database.get_schedule_by_id(schedule_id) - print(f"[API日志] 查询定时任务结果: {schedule}") - except Exception as e: - print(f"[API日志] 查询定时任务失败: {e}") - # 即使查询失败,也返回空数组,避免500错误 - return jsonify([]) - - if not schedule: - print(f"[API日志] 定时任务#{schedule_id}不存在,返回空数组") - return jsonify([]) - - try: - if schedule['user_id'] != current_user.id: - print(f"[API日志] 权限不足,返回空数组") - return jsonify([]) - except Exception as e: - print(f"[API日志] 权限检查失败: {e},返回空数组") - return jsonify([]) - - # 查询日志 - try: - limit = request.args.get('limit', 10, type=int) - print(f"[API日志] 开始查询日志,limit={limit}") - - logs = database.get_schedule_execution_logs(schedule_id, limit) - print(f"[API日志] 成功查询到{len(logs)}条日志") - - return jsonify(logs if logs else []) - except Exception as e: - print(f"[API日志] 查询日志失败: {e}") - import traceback - traceback.print_exc() - # 查询失败也返回空数组 + schedule = database.get_schedule_by_id(schedule_id) + if not schedule or schedule['user_id'] != current_user.id: return jsonify([]) + limit = request.args.get('limit', 20, type=int) + logs = database.get_schedule_execution_logs(schedule_id, limit) + return jsonify(logs if logs else []) except Exception as e: - print(f"[API日志] 外层异常捕获: {str(e)}") - import traceback - traceback.print_exc() - # 任何错误都返回空数组,不返回500 return jsonify([]) +@app.route('/api/schedules//logs', methods=['DELETE']) +@login_required +def delete_schedule_logs_api(schedule_id): + """清空定时任务执行日志""" + try: + schedule = database.get_schedule_by_id(schedule_id) + if not schedule or schedule['user_id'] != current_user.id: + return jsonify({"error": "无权限"}), 403 + + deleted = database.delete_schedule_logs(schedule_id, current_user.id) + return jsonify({"success": True, "deleted": deleted}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + + # ==================== 批量操作API ==================== @app.route('/api/accounts/batch/start', methods=['POST']) diff --git a/database.py b/database.py index 33a02ae..42063b8 100755 --- a/database.py +++ b/database.py @@ -1706,3 +1706,27 @@ def get_user_all_schedule_logs(user_id, limit=50): LIMIT ? ''', (user_id, limit)) return [dict(row) for row in cursor.fetchall()] + + +def delete_schedule_logs(schedule_id, user_id): + """删除指定定时任务的所有执行日志(需验证用户权限)""" + with db_pool.get_db() as conn: + cursor = conn.cursor() + cursor.execute(''' + DELETE FROM schedule_execution_logs + WHERE schedule_id = ? AND user_id = ? + ''', (schedule_id, user_id)) + conn.commit() + return cursor.rowcount + + +def clean_old_schedule_logs(days=30): + """清理指定天数前的定时任务执行日志""" + with db_pool.get_db() as conn: + cursor = conn.cursor() + cursor.execute(''' + DELETE FROM schedule_execution_logs + WHERE execute_time < datetime('now', '-' || ? || ' days') + ''', (days,)) + conn.commit() + return cursor.rowcount diff --git a/templates/index.html b/templates/index.html index 2a1aa18..9846b99 100644 --- a/templates/index.html +++ b/templates/index.html @@ -493,6 +493,7 @@
@@ -1312,6 +1313,8 @@ if (schedule) openScheduleModal(schedule); } + let currentLogsScheduleId = null; + function viewScheduleLogs(scheduleId) { const numericId = parseInt(scheduleId, 10); const schedule = schedules.find(s => s.id == numericId); @@ -1320,6 +1323,7 @@ return; } + currentLogsScheduleId = numericId; document.getElementById("scheduleLogsTitle").textContent = "【" + (schedule.name || "未命名任务") + "】 执行日志"; fetch("/api/schedules/" + numericId + "/logs?limit=20") @@ -1362,6 +1366,23 @@ }); } + function clearScheduleLogs() { + if (!currentLogsScheduleId) return; + if (!confirm('确定要清空该任务的所有执行日志吗?')) return; + + fetch("/api/schedules/" + currentLogsScheduleId + "/logs", { method: 'DELETE' }) + .then(r => r.json()) + .then(data => { + if (data.success) { + showToast('已清空 ' + data.deleted + ' 条日志', 'success'); + document.getElementById("scheduleLogsList").innerHTML = "

暂无执行日志

"; + } else { + showToast(data.error || '清空失败', 'error'); + } + }) + .catch(err => showToast('清空失败', 'error')); + } + function formatDuration(seconds) { if (seconds < 60) return seconds + "秒"; const minutes = Math.floor(seconds / 60);