From b049ed92c18d6a9bbda9ea1904de9e3e9fe418bc Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Tue, 14 Apr 2026 17:57:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BB=B6=E8=BF=9F=E6=97=B6?= =?UTF-8?q?=E5=8C=BA=E4=B8=BA=E5=9B=BA=E5=AE=9A=E5=8C=97=E4=BA=AC=E6=97=B6?= =?UTF-8?q?=E9=97=B4=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=BA=BF=E7=A8=8B=E9=97=B4?= =?UTF-8?q?=E9=9A=94=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background.js | 58 ++++++++++++++++++++++++++++++++++++++++-- sidepanel/sidepanel.js | 31 +++++++++++++++++++--- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/background.js b/background.js index adb4f24..11fd5ec 100644 --- a/background.js +++ b/background.js @@ -48,6 +48,7 @@ const HOTMAIL_SERVICE_MODE_LOCAL = 'local'; const DEFAULT_HOTMAIL_REMOTE_BASE_URL = ''; const DEFAULT_HOTMAIL_LOCAL_BASE_URL = 'http://127.0.0.1:17373'; const HOTMAIL_LOCAL_HELPER_TIMEOUT_MS = 45000; +const DISPLAY_TIMEZONE = 'Asia/Shanghai'; initializeSessionStorageAccess(); @@ -2328,6 +2329,7 @@ async function invalidateDownstreamAfterStepRestart(step, options = {}) { function clearStopRequest() { stopRequested = false; + autoRunCountdownSkipRequested = false; } function getRunningSteps(statuses = {}) { @@ -2424,6 +2426,7 @@ function isAutoRunScheduledState(state) { function formatAutoRunScheduleTime(timestamp) { return new Date(timestamp).toLocaleString('zh-CN', { hour12: false, + timeZone: DISPLAY_TIMEZONE, month: '2-digit', day: '2-digit', hour: '2-digit', @@ -2767,6 +2770,7 @@ async function broadcastStopToContentScripts() { } let stopRequested = false; +let autoRunCountdownSkipRequested = false; // ============================================================ // Message Handler (central router) @@ -2907,6 +2911,15 @@ async function handleMessage(message, sender) { return { ok: true }; } + case 'SKIP_AUTO_RUN_COUNTDOWN': { + clearStopRequest(); + const skipped = await skipAutoRunCountdown(); + if (!skipped) { + throw new Error('当前没有可立即开始的倒计时。'); + } + return { ok: true }; + } + case 'RESUME_AUTO_RUN': { clearStopRequest(); if (message.payload.email) { @@ -4067,11 +4080,52 @@ async function sleepWithAutoRunCountdown(waitMs, payload = {}) { return; } - await broadcastAutoRunStatus('waiting_interval', { + autoRunCountdownSkipRequested = false; + const countdownPayload = { ...payload, countdownAt: Date.now() + waitMs, + }; + await broadcastAutoRunStatus('waiting_interval', countdownPayload); + + const start = Date.now(); + try { + while (Date.now() - start < waitMs) { + throwIfStopped(); + if (autoRunCountdownSkipRequested) { + autoRunCountdownSkipRequested = false; + return; + } + await new Promise((resolve) => setTimeout(resolve, Math.min(100, waitMs - (Date.now() - start)))); + } + } finally { + if (!stopRequested) { + await broadcastAutoRunStatus('waiting_interval', { + ...payload, + countdownAt: null, + countdownTitle: '', + countdownNote: '', + }); + } + } +} + +async function skipAutoRunCountdown() { + const state = await getState(); + if (!autoRunActive || state.autoRunPhase !== 'waiting_interval') { + return false; + } + + autoRunCountdownSkipRequested = true; + await addLog('已手动跳过当前倒计时,自动流程将立即继续。', 'info'); + await broadcastAutoRunStatus('waiting_interval', { + currentRun: state.autoRunCurrentRun, + totalRuns: state.autoRunTotalRuns, + attemptRun: state.autoRunAttemptRun, + countdownAt: null, + countdownTitle: '', + countdownNote: '', }); - await sleepWithStop(waitMs); + return true; } async function waitBetweenAutoRunRounds(targetRun, totalRuns, roundSummary) { diff --git a/sidepanel/sidepanel.js b/sidepanel/sidepanel.js index 2bffe6c..623f020 100644 --- a/sidepanel/sidepanel.js +++ b/sidepanel/sidepanel.js @@ -145,6 +145,7 @@ const AUTO_RUN_FALLBACK_RISK_WARNING_MIN_RUNS = 15; const AUTO_RUN_FALLBACK_RISK_RECOMMENDED_THREAD_INTERVAL_MINUTES = 5; const HOTMAIL_SERVICE_MODE_REMOTE = 'remote'; const HOTMAIL_SERVICE_MODE_LOCAL = 'local'; +const DISPLAY_TIMEZONE = 'Asia/Shanghai'; let latestState = null; let currentAutoRun = { @@ -183,6 +184,8 @@ const getHotmailBulkActionLabel = window.HotmailUtils?.getHotmailBulkActionLabel const getHotmailListToggleLabel = window.HotmailUtils?.getHotmailListToggleLabel; const HOTMAIL_LIST_EXPANDED_STORAGE_KEY = 'multipage-hotmail-list-expanded'; const sidepanelUpdateService = window.SidepanelUpdateService; + +btnAutoCancelSchedule?.remove(); const MAIL_PROVIDER_LOGIN_CONFIGS = { '163': { label: '163 邮箱', @@ -745,6 +748,7 @@ function formatCountdown(remainingMs) { function formatScheduleTime(timestamp) { return new Date(timestamp).toLocaleString('zh-CN', { hour12: false, + timeZone: DISPLAY_TIMEZONE, month: '2-digit', day: '2-digit', hour: '2-digit', @@ -793,6 +797,13 @@ function renderScheduledAutoRunInfo() { const remainingMs = countdown.at - Date.now(); autoScheduleBar.style.display = 'flex'; + if (btnAutoRunNow) { + btnAutoRunNow.hidden = false; + btnAutoRunNow.textContent = currentAutoRun.phase === 'waiting_interval' ? '立即继续' : '立即开始'; + } + if (btnAutoCancelSchedule) { + btnAutoCancelSchedule.hidden = true; + } autoScheduleTitle.textContent = countdown.title; autoScheduleMeta.textContent = remainingMs > 0 ? `${countdown.note ? `${countdown.note},` : ''}剩余 ${formatCountdown(remainingMs)}` @@ -1707,7 +1718,10 @@ function formatDateTime(timestamp) { if (!Number.isFinite(value) || value <= 0) { return '未使用'; } - return new Date(value).toLocaleString('zh-CN', { hour12: false }); + return new Date(value).toLocaleString('zh-CN', { + hour12: false, + timeZone: DISPLAY_TIMEZONE, + }); } function getHotmailAvailabilityLabel(account) { @@ -2067,7 +2081,10 @@ function updateStatusDisplay(state) { } function appendLog(entry) { - const time = new Date(entry.timestamp).toLocaleTimeString('zh-CN', { hour12: false }); + const time = new Date(entry.timestamp).toLocaleTimeString('zh-CN', { + hour12: false, + timeZone: DISPLAY_TIMEZONE, + }); const levelLabel = LOG_LEVEL_LABELS[entry.level] || entry.level; const line = document.createElement('div'); line.className = `log-line log-${entry.level}`; @@ -2850,7 +2867,15 @@ btnAutoContinue.addEventListener('click', async () => { btnAutoRunNow?.addEventListener('click', async () => { try { btnAutoRunNow.disabled = true; - await chrome.runtime.sendMessage({ type: 'START_SCHEDULED_AUTO_RUN_NOW', source: 'sidepanel', payload: {} }); + const waitingInterval = currentAutoRun.phase === 'waiting_interval'; + await chrome.runtime.sendMessage({ + type: waitingInterval ? 'SKIP_AUTO_RUN_COUNTDOWN' : 'START_SCHEDULED_AUTO_RUN_NOW', + source: 'sidepanel', + payload: {}, + }); + if (waitingInterval) { + showToast('已跳过当前倒计时,自动流程将立即继续。', 'info', 1800); + } } catch (err) { showToast(err.message, 'error'); } finally {