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:
+78
-2
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user