feat: add Auto Run mode for full automated flow

- Background: add step completion waiting (promise-based), autoRun/resumeAutoRun
  chains steps 1→2 (pause for email) → 3→4→5→6→7→8→9 automatically
- Side Panel: add "Auto Run" button and "Continue Auto" bar for email pause point
- signup-page.js: add step 8 handler to click "继续" on OAuth consent page
- Fix all steps to reportComplete before form submit (prevents connection loss on navigation)
- qq-mail.js: fallback after 3 attempts to first matching email
- vps-panel.js: step 9 waits for "认证成功!" status badge
This commit is contained in:
unknown
2026-04-05 09:42:17 +08:00
parent 887709e824
commit 1c1e589bdc
7 changed files with 743 additions and 431 deletions
+78 -2
View File
@@ -23,6 +23,11 @@ header h1 {
font-weight: 600;
}
.header-btns {
display: flex;
gap: 6px;
}
#btn-reset {
padding: 4px 10px;
font-size: 12px;
@@ -34,6 +39,49 @@ header h1 {
}
#btn-reset:hover { background: #c82333; }
.btn-auto {
padding: 4px 10px;
font-size: 12px;
background: #28a745;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 600;
}
.btn-auto:hover { background: #218838; }
.btn-auto:disabled { background: #6c757d; cursor: not-allowed; }
.auto-continue-bar {
margin-top: 8px;
padding: 8px;
background: #fff3cd;
border: 1px solid #ffc107;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
}
.auto-hint {
font-size: 11px;
color: #856404;
flex: 1;
}
.btn-continue {
padding: 4px 12px;
font-size: 12px;
background: #007bff;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 600;
white-space: nowrap;
}
.btn-continue:hover { background: #0069d9; }
/* Data Section */
#data-section {
background: #fff;
@@ -141,6 +189,34 @@ header h1 {
}
.log-info { color: #d4d4d4; }
.log-ok { color: #4ec9b0; }
.log-ok { color: #4ec9b0; font-weight: bold; }
.log-warn { color: #dcdcaa; }
.log-error { color: #f44747; }
.log-error { color: #f44747; font-weight: bold; }
.log-step-tag {
display: inline-block;
background: #3a3d41;
color: #569cd6;
border-radius: 3px;
padding: 0 4px;
margin-right: 4px;
font-weight: bold;
font-size: 10px;
}
.log-step-tag.step-1 { color: #4fc1ff; }
.log-step-tag.step-2 { color: #c586c0; }
.log-step-tag.step-3 { color: #dcdcaa; }
.log-step-tag.step-4 { color: #ce9178; }
.log-step-tag.step-5 { color: #b5cea8; }
.log-step-tag.step-6 { color: #4fc1ff; }
.log-step-tag.step-7 { color: #ce9178; }
.log-step-tag.step-8 { color: #c586c0; }
.log-step-tag.step-9 { color: #b5cea8; }
.log-time { color: #6a9955; }
.log-level { font-weight: bold; }
.log-level-info { color: #569cd6; }
.log-level-ok { color: #4ec9b0; }
.log-level-warn { color: #dcdcaa; }
.log-level-error { color: #f44747; }
+8 -1
View File
@@ -9,7 +9,10 @@
<body>
<header>
<h1>Multi-Page Automation</h1>
<button id="btn-reset" title="Reset all steps">Reset</button>
<div class="header-btns">
<button id="btn-auto-run" class="btn-auto" title="Run all steps automatically">Auto Run</button>
<button id="btn-reset" title="Reset all steps">Reset</button>
</div>
</header>
<section id="data-section">
@@ -29,6 +32,10 @@
<label>Status:</label>
<span id="display-status" class="data-value">Waiting</span>
</div>
<div id="auto-continue-bar" class="auto-continue-bar" style="display:none;">
<span class="auto-hint">Paste DuckDuckGo email above, then:</span>
<button id="btn-auto-continue" class="btn-continue">Continue Auto</button>
</div>
</section>
<section id="steps-section">
+70 -1
View File
@@ -128,11 +128,30 @@ function appendLog(entry) {
const levelLabel = entry.level.toUpperCase().padEnd(5);
const line = document.createElement('div');
line.className = `log-${entry.level}`;
line.textContent = `${time} [${levelLabel}] ${entry.message}`;
// Extract step number from message (e.g., "Step 4: ..." or "[vps-panel] Step 1: ...")
const stepMatch = entry.message.match(/Step (\d)/);
const stepNum = stepMatch ? stepMatch[1] : null;
// Build rich HTML
let html = `<span class="log-time">${time}</span> `;
html += `<span class="log-level log-level-${entry.level}">[${levelLabel}]</span> `;
if (stepNum) {
html += `<span class="log-step-tag step-${stepNum}">S${stepNum}</span>`;
}
html += `<span>${escapeHtml(entry.message)}</span>`;
line.innerHTML = html;
logArea.appendChild(line);
logArea.scrollTop = logArea.scrollHeight;
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ============================================================
// Button Handlers
// ============================================================
@@ -163,6 +182,32 @@ document.querySelectorAll('.step-btn').forEach(btn => {
});
});
// Auto Run button
const btnAutoRun = document.getElementById('btn-auto-run');
const btnAutoContinue = document.getElementById('btn-auto-continue');
const autoContinueBar = document.getElementById('auto-continue-bar');
btnAutoRun.addEventListener('click', async () => {
btnAutoRun.disabled = true;
btnAutoRun.textContent = 'Running...';
await chrome.runtime.sendMessage({ type: 'AUTO_RUN', source: 'sidepanel' });
});
btnAutoContinue.addEventListener('click', async () => {
const email = inputEmail.value.trim();
if (!email) {
appendLog({ message: 'Please paste DuckDuckGo email first!', level: 'error', timestamp: Date.now() });
return;
}
autoContinueBar.style.display = 'none';
btnAutoRun.textContent = 'Running...';
await chrome.runtime.sendMessage({
type: 'RESUME_AUTO_RUN',
source: 'sidepanel',
payload: { email },
});
});
// Reset button
btnReset.addEventListener('click', async () => {
if (confirm('Reset all steps and data?')) {
@@ -177,6 +222,9 @@ btnReset.addEventListener('click', async () => {
displayStatus.classList.remove('has-value');
logArea.innerHTML = '';
document.querySelectorAll('.step-status').forEach(el => el.textContent = '\u2B1A');
btnAutoRun.disabled = false;
btnAutoRun.textContent = 'Auto Run';
autoContinueBar.style.display = 'none';
updateButtonStates();
}
});
@@ -222,6 +270,27 @@ chrome.runtime.onMessage.addListener((message) => {
}
break;
}
case 'AUTO_RUN_STATUS': {
const { phase } = message.payload;
switch (phase) {
case 'waiting_email':
autoContinueBar.style.display = 'flex';
btnAutoRun.textContent = 'Waiting...';
break;
case 'complete':
btnAutoRun.disabled = false;
btnAutoRun.textContent = 'Auto Run';
autoContinueBar.style.display = 'none';
break;
case 'stopped':
btnAutoRun.disabled = false;
btnAutoRun.textContent = 'Auto Run';
autoContinueBar.style.display = 'none';
break;
}
break;
}
}
});