From 226d6724bd7f4c942253f2a0d33f18261767e75f Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Wed, 10 Dec 2025 19:10:59 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1=E6=97=A5=E5=BF=97=E5=92=8C=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复日志按钮点击无反应(类型匹配和错误处理) - 修复定时任务到时间不执行(时间格式标准化) - 增强所有检查点的调试日志输出 - 改进今日执行检查逻辑(支持同一天不同时间执行) Bug 1: 日志按钮完全没反应 - 将严格相等(===)改为宽松相等(==)避免类型不匹配 - 添加详细的错误日志和用户提示 - 添加容器元素存在性检查 Bug 2: 定时任务到时间不会被执行 - 标准化时间格式(8:00 -> 08:00) - 增强所有检查点的日志输出(时间、星期、账号) - 改进今日执行检查(同一天不同时间可再次执行) - 前端添加时间格式验证和标准化 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- app.py | 77 +++++++++++++++++++++++++++++++++++--------- templates/index.html | 38 +++++++++++++++++++--- 2 files changed, 95 insertions(+), 20 deletions(-) diff --git a/app.py b/app.py index 1ab273b..b417a7e 100755 --- a/app.py +++ b/app.py @@ -2870,36 +2870,59 @@ def scheduled_task_worker(): print(f"[定时任务检查] 当前时间: {current_time}, 星期: {current_weekday}, 找到 {len(enabled_schedules)} 个启用的定时任务") for schedule_config in enabled_schedules: - schedule_time = schedule_config['schedule_time'] + schedule_time = schedule_config['schedule_time'].strip() schedule_name = schedule_config.get('name', '未命名任务') schedule_id = schedule_config['id'] + + # 标准化时间格式(处理 "8:00" -> "08:00") + if ':' in schedule_time: + h, m = schedule_time.split(':') + schedule_time = f"{int(h):02d}:{int(m):02d}" + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}': 设定时间={schedule_time}, 当前时间={current_time}, 匹配={schedule_time == current_time}") # 检查时间是否匹配 - if schedule_config['schedule_time'] != current_time: - print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 时间不匹配") + if schedule_time != current_time: + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 时间不匹配 (设定:{schedule_time} vs 当前:{current_time})") continue print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 时间匹配,继续检查...") # 检查星期是否匹配 - allowed_weekdays = [int(d) for d in schedule_config.get('weekdays', '1,2,3,4,5').split(',') if d.strip()] - print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 允许星期: {allowed_weekdays}, 当前星期: {current_weekday}") + weekdays_str = schedule_config.get('weekdays', '1,2,3,4,5') + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' weekdays字段原始值: '{weekdays_str}'") + + try: + allowed_weekdays = [int(d) for d in weekdays_str.split(',') if d.strip()] + except Exception as e: + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 解析weekdays失败: {e}") + continue + + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 允许星期: {allowed_weekdays}, 当前星期: {current_weekday} (1=周一,7=周日)") if current_weekday not in allowed_weekdays: - print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 星期不匹配") + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 星期不匹配 ({current_weekday} not in {allowed_weekdays})") continue print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 星期匹配,继续检查...") - # 检查今天是否已经执行过 + # 检查今天是否已经执行过(同一天同一时间只执行一次) last_run = schedule_config.get('last_run_at') print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 最后执行时间: {last_run}") if last_run: try: - last_run_date = datetime.strptime(last_run, '%Y-%m-%d %H:%M:%S').date() - if last_run_date == now.date(): - print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 今天已执行过") - continue # 今天已执行过 + last_run_datetime = datetime.strptime(last_run, '%Y-%m-%d %H:%M:%S') + last_run_date = last_run_datetime.date() + last_run_time = last_run_datetime.strftime('%H:%M') + + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 最后执行: 日期={last_run_date}, 时间={last_run_time}") + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 当前: 日期={now.date()}, 时间={current_time}") + + # 检查是否在同一天的同一时间已执行过 + if last_run_date == now.date() and last_run_time == schedule_time: + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 今天此时间({schedule_time})已执行过") + continue + elif last_run_date == now.date() and last_run_time != schedule_time: + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 提示: 今天已在{last_run_time}执行过,当前时间{schedule_time}可以再次执行") except Exception as e: print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 解析last_run时间失败: {e}") @@ -2915,11 +2938,16 @@ def scheduled_task_worker(): print(f"[DEBUG] 定时任务 {schedule_config.get('name')}: enable_screenshot={enable_screenshot} (类型:{type(enable_screenshot).__name__})") try: - account_ids = json.loads(schedule_config.get('account_ids', '[]') or '[]') - except: + account_ids_raw = schedule_config.get('account_ids', '[]') or '[]' + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' account_ids原始值: {account_ids_raw}") + account_ids = json.loads(account_ids_raw) + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 解析后account_ids: {account_ids}, 共{len(account_ids)}个账号") + except Exception as e: + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 解析account_ids失败: {e}") account_ids = [] if not account_ids: + print(f"[定时任务检查] 任务#{schedule_id} '{schedule_name}' 跳过: 未配置账号") continue print(f"[用户定时任务] 用户 {schedule_config.get('user_username', user_id)} 的任务 '{schedule_config.get('name', '')}' 开始执行") @@ -2934,11 +2962,28 @@ def scheduled_task_worker(): ) started_count = 0 + skipped_count = 0 + print(f"[定时任务检查] 任务#{schedule_id} 准备启动{len(account_ids)}个账号") + print(f"[定时任务检查] user_accounts中的用户: {list(user_accounts.keys())}") + if user_id in user_accounts: + print(f"[定时任务检查] 用户{user_id}的账号: {list(user_accounts[user_id].keys())}") + else: + print(f"[定时任务检查] ⚠️ 用户{user_id}不在user_accounts中!") + for account_id in account_ids: - if user_id not in user_accounts or account_id not in user_accounts[user_id]: + print(f"[定时任务检查] 检查账号 {account_id} (类型: {type(account_id)})") + if user_id not in user_accounts: + print(f"[定时任务检查] 跳过账号{account_id}: 用户{user_id}不在user_accounts中") + skipped_count += 1 + continue + if account_id not in user_accounts[user_id]: + print(f"[定时任务检查] 跳过账号{account_id}: 账号不在user_accounts[{user_id}]中") + skipped_count += 1 continue account = user_accounts[user_id][account_id] if account.is_running: + print(f"[定时任务检查] 跳过账号{account_id}: 账号正在运行中") + skipped_count += 1 continue account.is_running = True @@ -2970,7 +3015,9 @@ def scheduled_task_worker(): status='completed' ) - print(f"[用户定时任务] 已启动 {started_count} 个账号") + print(f"[用户定时任务] 已启动 {started_count} 个账号,跳过 {skipped_count} 个账号") + if started_count == 0 and len(account_ids) > 0: + print(f"[用户定时任务] ⚠️ 警告:所有账号都被跳过了!请检查user_accounts状态") except Exception as e: print(f"[用户定时任务] 检查出错: {str(e)}") diff --git a/templates/index.html b/templates/index.html index d041c7f..cb28864 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1282,7 +1282,23 @@ function saveSchedule() { const name = document.getElementById('scheduleName').value.trim() || '我的定时任务'; - const scheduleTime = document.getElementById('scheduleTime').value; + const scheduleTimeRaw = document.getElementById('scheduleTime').value; + + // 标准化时间格式为 HH:MM + const timeParts = scheduleTimeRaw.match(/^(\d{1,2}):(\d{2})$/); + if (!timeParts) { + showToast('时间格式错误,请使用HH:MM格式', 'error'); + return; + } + const hour = parseInt(timeParts[1], 10); + const minute = parseInt(timeParts[2], 10); + if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { + showToast('时间范围错误', 'error'); + return; + } + const scheduleTime = hour.toString().padStart(2, '0') + ':' + minute.toString().padStart(2, '0'); + console.log('[定时任务] 标准化时间:', scheduleTimeRaw, '->', scheduleTime); + const browseType = document.getElementById('scheduleBrowseType').value; const enableScreenshot = document.getElementById('scheduleScreenshot').checked ? 1 : 0; const weekdays = []; @@ -1305,11 +1321,17 @@ } function viewScheduleLogs(scheduleId) { - console.log('[日志弹窗] 开始查看日志, scheduleId=', scheduleId); + console.log('[日志弹窗] 开始查看日志, scheduleId=', scheduleId, '(类型:', typeof scheduleId + ')'); + console.log('[日志弹窗] 当前schedules数组:', schedules); - const schedule = schedules.find(s => s.id === scheduleId); + // 类型转换确保兼容性 + const numericId = parseInt(scheduleId, 10); + + const schedule = schedules.find(s => s.id == numericId); // 使用宽松相等 if (!schedule) { - console.log('[日志弹窗] 未找到任务'); + console.error('[日志弹窗] 未找到任务, scheduleId=', scheduleId); + console.error('[日志弹窗] 可用的任务IDs:', schedules.map(s => s.id)); + showToast('未找到该定时任务', 'error'); return; } @@ -1317,7 +1339,7 @@ document.getElementById("scheduleLogsTitle").textContent = "【" + (schedule.name || "未命名任务") + "】 执行日志"; console.log('[日志弹窗] 开始请求API'); - fetch("/api/schedules/" + scheduleId + "/logs?limit=20") + fetch("/api/schedules/" + numericId + "/logs?limit=20") .then(r => { console.log('[日志弹窗] API响应状态:', r.status); return r.json(); @@ -1326,6 +1348,12 @@ console.log('[日志弹窗] 收到日志数据:', logs); const container = document.getElementById("scheduleLogsList"); + if (!container) { + console.error('[日志弹窗] 找不到日志容器元素 scheduleLogsList'); + showToast('页面元素加载异常', 'error'); + return; + } + if (!logs || logs.length === 0) { console.log('[日志弹窗] 无日志,显示空状态'); container.innerHTML = "

暂无执行日志

";