您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
模拟操作,自动完成Microsoft Rewards必应搜索任务,带可视化界面与配置,美观安全防检测。
当前为
// ==UserScript== // @name Microsoft Rewards助手 // @version 3.0.2 // @description 模拟操作,自动完成Microsoft Rewards必应搜索任务,带可视化界面与配置,美观安全防检测。 // @author Sentaku1129 & WretchedSniper UI enhanced // @match *://*.bing.com/* // @license GNU GPLv3 // @icon https://www.bing.com/favicon.ico // @run-at document-end // @grant none // @namespace http://greasyfork.icu/users/1029902 // ==/UserScript== (function () { 'use strict'; if (window.trustedTypes && window.trustedTypes.createPolicy) { window.trustedTypes.createPolicy('default', { createHTML: input => input, createScript: input => input, createScriptURL: input => input }); } // --- 颜色与字体配置 --- const theme = { main: "#0078d4", accent: "#4CAF50", error: "#f44336", bg: "#fff", fg: "#222", border: "#e0e0e0", shadow: "0 4px 20px 0 rgba(0,0,0,.10)", font: `-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"` }; let mainPageSearchTerms = []; let iframeSearchTerms = []; let usedSearchTerms = []; let currentProgress = { current: 0, total: 0, lastChecked: 0, completed: false, noProgressCount: 0 }; let isSearching = false; let countdownTimer = null; const config = { restTime: 5 * 60, scrollTime: 10, waitTime: 10, searchInterval: [5, 10], maxNoProgressCount: 3 }; const searchState = { currentAction: 'idle', countdown: 0, needRest: false, isCollapsed: true }; // ---- UI functions ---- function injectGlobalStyle() { const style = document.createElement('style'); style.innerHTML = ` #rewards-helper-container { transition: box-shadow .2s, width .2s, height .2s; } #rewards-helper-container::-webkit-scrollbar, #rewards-helper-content::-webkit-scrollbar, #rewards-search-terms-container::-webkit-scrollbar { width: 8px; background: #f6f6f6; } #rewards-helper-container::-webkit-scrollbar-thumb, #rewards-helper-content::-webkit-scrollbar-thumb, #rewards-search-terms-container::-webkit-scrollbar-thumb { background: ${theme.main}33; border-radius: 5px; } #rewards-helper-content { font-family: ${theme.font}; font-size: 15px; color: ${theme.fg}; } #rewards-helper-container input[type=number] { border: 1px solid ${theme.border}; border-radius: 3px; padding: 2px 5px; font-size: 13px; } #rewards-helper-container button { transition: background .15s, color .15s; } #rewards-helper-container .term-pill { display: inline-block; background: ${theme.main}12; border-radius: 14px; padding: 2px 10px; margin: 2px 2px 2px 0; font-size: 13px; color: ${theme.main}; border: 1px solid ${theme.main}22; user-select: text; } #rewards-helper-container .term-pill.used { opacity: .45; background: #aaa1; color: #999; border: 1px solid #ccc; text-decoration: line-through; } #rewards-helper-container .heading { font-size: 14px; color: ${theme.main}; font-weight: bold; margin-bottom: 2px; letter-spacing: .05em; } #rewards-helper-container .action-btn { background: ${theme.main}; color: #fff; border: none; border-radius: 4px; font-weight: bold; font-size: 15px; padding: 6px 0; margin-bottom: 0; width: 100%; transition: background .15s; } #rewards-helper-container .action-btn.stop { background: ${theme.error}; } #rewards-helper-container .status-message { font-size: 13px; color: #888; margin-top: -1px; min-height: 18px; } #rewards-helper-container .progress-bar { background: #eee; height: 10px; border-radius: 6px; overflow: hidden; margin: 4px 0 6px 0; } #rewards-helper-container .progress-bar-inner { background: ${theme.accent}; height: 100%; transition: width .5s; } #rewards-helper-container .countdown { font-size: 13px; color: ${theme.main}; margin-top: 3px; font-weight: bold; } @media (max-width: 500px) { #rewards-helper-container { width: 98vw !important; right: 1vw !important; left: unset !important; min-width: 0 !important; max-width: none !important; } } `; document.head.appendChild(style); } function createUI() { injectGlobalStyle(); const container = document.createElement('div'); container.id = 'rewards-helper-container'; container.style.cssText = ` position: fixed; top: 32px; right: 24px; background: ${theme.bg}; border: 1.5px solid ${theme.border}; border-radius: 10px; padding: 0 0 10px 0; z-index: 10000; width: 340px; min-width: 260px; max-width: 97vw; box-shadow: ${theme.shadow}; user-select: none; font-family: ${theme.font}; font-size: 15px; `; const header = document.createElement('div'); header.style.cssText = ` font-weight: bold; background: ${theme.main}; color: #fff; border-radius: 10px 10px 0 0; padding: 10px 12px 8px 18px; display: flex; justify-content: space-between; align-items: center; cursor: move; font-size: 18px; `; header.innerHTML = `<span>🎁 Microsoft Rewards 助手</span>`; const controls = document.createElement('div'); controls.style.cssText = `display:flex;align-items:center;gap:10px;`; const minimizeBtn = document.createElement('span'); minimizeBtn.id = 'minimize-btn'; minimizeBtn.textContent = '-'; minimizeBtn.title = '折叠/展开'; minimizeBtn.style.cssText = ` cursor:pointer;font-size:22px;transform:scaleX(1.3);margin-right:10px;user-select:none; `; minimizeBtn.onclick = () => { toggleCollapse(); }; controls.appendChild(minimizeBtn); const closeBtn = document.createElement('span'); closeBtn.textContent = '×'; closeBtn.title = '关闭助手'; closeBtn.style.cssText = ` cursor:pointer;font-size:24px;user-select:none;opacity:.85; `; closeBtn.onclick = () => { container.style.display = 'none'; }; controls.appendChild(closeBtn); header.appendChild(controls); const content = document.createElement('div'); content.id = 'rewards-helper-content'; content.style.cssText = `padding: 14px 18px 0 18px;`; const progress = document.createElement('div'); progress.id = 'rewards-progress'; progress.style.cssText = `font-size:15px;margin-bottom:6px;font-weight:500;letter-spacing:.02em;`; progress.innerHTML = `进度: <span class="progress-value">加载中...</span>`; content.appendChild(progress); const progressBar = document.createElement('div'); progressBar.className = 'progress-bar'; progressBar.style.width = "100%"; const progressBarInner = document.createElement('div'); progressBarInner.className = 'progress-bar-inner'; progressBarInner.style.width = "0%"; progressBar.appendChild(progressBarInner); content.appendChild(progressBar); const statusLine = document.createElement('div'); statusLine.id = 'search-status'; statusLine.className = 'status-message'; statusLine.textContent = ""; content.appendChild(statusLine); const countdown = document.createElement('div'); countdown.id = 'countdown'; countdown.className = 'countdown'; countdown.style.display = 'none'; content.appendChild(countdown); const searchTermsContainer = document.createElement('div'); searchTermsContainer.id = 'rewards-search-terms-container'; searchTermsContainer.style.cssText = `margin-top:8px;max-height:120px;overflow-y:auto;`; const mainTermsTitle = document.createElement('div'); mainTermsTitle.className = 'heading'; mainTermsTitle.textContent = '主页面搜索词'; searchTermsContainer.appendChild(mainTermsTitle); const mainTerms = document.createElement('div'); mainTerms.id = 'main-search-terms'; mainTerms.style.cssText = `margin-bottom: 6px;line-height:1.7;`; searchTermsContainer.appendChild(mainTerms); const iframeTermsTitle = document.createElement('div'); iframeTermsTitle.className = 'heading'; iframeTermsTitle.textContent = '侧栏推荐搜索词'; searchTermsContainer.appendChild(iframeTermsTitle); const iframeTerms = document.createElement('div'); iframeTerms.id = 'iframe-search-terms'; iframeTerms.style.cssText = `margin-bottom:3px;line-height:1.7;`; searchTermsContainer.appendChild(iframeTerms); content.appendChild(searchTermsContainer); const divider = document.createElement('hr'); divider.style.cssText = `border:0;border-top:1px solid ${theme.border};margin:10px 0 8px 0;`; content.appendChild(divider); const configSection = document.createElement('div'); configSection.id = 'rewards-config-section'; configSection.style.cssText = `margin-bottom:10px;`; const configTitle = document.createElement('div'); configTitle.className = 'heading'; configTitle.textContent = '配置参数:'; configSection.appendChild(configTitle); const configForm = document.createElement('div'); configForm.style.cssText = ` display: grid; grid-template-columns: 110px auto; gap: 4px 6px; align-items:center; font-size:13px;margin-top:2px; `; configForm.innerHTML = ` <label for="rest-time">休息时间(分):</label> <input type="number" id="rest-time" value="${config.restTime / 60}" min="1" max="30"> <label for="scroll-time">滚动时间(秒):</label> <input type="number" id="scroll-time" value="${config.scrollTime}" min="3" max="30"> <label for="wait-time">等待时间(秒):</label> <input type="number" id="wait-time" value="${config.waitTime}" min="3" max="30"> <label for="max-no-progress">容错次数:</label> <input type="number" id="max-no-progress" value="${config.maxNoProgressCount}" min="1" max="10"> `; configSection.appendChild(configForm); content.appendChild(configSection); const buttonsContainer = document.createElement('div'); buttonsContainer.id = 'rewards-buttons-container'; buttonsContainer.style.cssText = ` display:flex;flex-direction:column;align-items:stretch;margin-top:0;gap:7px 0;padding:0 18px; `; const startSearchBtn = document.createElement('button'); startSearchBtn.id = 'start-search-btn'; startSearchBtn.className = 'action-btn'; startSearchBtn.textContent = '开始自动搜索'; startSearchBtn.onclick = function () { if (!isSearching) startAutomatedSearch(); else stopAutomatedSearch(); }; buttonsContainer.appendChild(startSearchBtn); const linksContainer = document.createElement('div'); linksContainer.style.cssText = ` display: flex;justify-content:center;gap:15px;margin-top:5px;width:100%;font-size:13px;color:#888; `; const supportAuthorContainer = document.createElement('div'); const supportAuthorLink = document.createElement('span'); supportAuthorLink.textContent = '🧧 支持作者'; supportAuthorLink.style.cssText = 'cursor:pointer;color:' + theme.error + ';font-weight:bold;'; const qrCodeContainer = document.createElement('div'); qrCodeContainer.style.cssText = ` display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%); background:#fff;padding:22px 25px 18px 25px;border:1.5px solid #eee;border-radius:8px;box-shadow:0 0 30px 0 #0004;z-index:10002;flex-direction:row;gap:16px; `; [ 'https://image.baidu.com/search/down?url=https://tokyo.sentaku.trade:9999/down/A3Z8wGynBHGo.png', 'https://image.baidu.com/search/down?url=https://tokyo.sentaku.trade:9999/down/DcDNyzGgGG4E.png' ].forEach(url => { if (!url.startsWith('//')) { const img = document.createElement('img'); img.src = url; // img.style.cssText = `width: 150px; height: auto; display: block; border-radius:6px;border:1px solid #eee;box-shadow:0 0 8px #0002;`; img.style.cssText = `max-width: 250px;max-height: 300px;width: auto;height: auto;display: block;border-radius: 6px;border: 1px solid #eee;box-shadow: 0 0 8px #0002;margin: 0 auto;background: #fff;`; qrCodeContainer.appendChild(img); } }); supportAuthorLink.onclick = (e) => { e.preventDefault(); qrCodeContainer.style.display = 'flex'; const overlay = document.createElement('div'); overlay.style.cssText = ` position:fixed;top:0;left:0;width:100vw;height:100vh; background:rgba(0,0,0,.36);z-index:10001; `; overlay.onclick = () => { qrCodeContainer.style.display = 'none'; document.body.removeChild(overlay); }; document.body.appendChild(overlay); if (qrCodeContainer.parentElement !== document.body) document.body.appendChild(qrCodeContainer); }; supportAuthorContainer.appendChild(supportAuthorLink); supportAuthorContainer.appendChild(qrCodeContainer); linksContainer.appendChild(supportAuthorContainer); const rateLink = document.createElement('a'); rateLink.href = 'http://greasyfork.icu/zh-CN/scripts/460310-%E5%BF%85%E5%BA%94rewards%E7%83%AD%E6%90%9C%E8%87%AA%E5%8A%A8%E8%BE%93%E5%85%A5%E4%BB%BB%E5%8A%A1/feedback'; rateLink.target = '_blank'; rateLink.textContent = '👍 给个好评'; rateLink.style.cssText = 'color:' + theme.accent + ';font-weight:bold;text-decoration:none;'; linksContainer.appendChild(rateLink); buttonsContainer.appendChild(linksContainer); container.appendChild(header); container.appendChild(content); container.appendChild(buttonsContainer); document.body.appendChild(container); makeDraggable(container, header); setTimeout(() => { const restTimeInput = document.getElementById('rest-time'); const scrollTimeInput = document.getElementById('scroll-time'); const waitTimeInput = document.getElementById('wait-time'); const maxNoProgressInput = document.getElementById('max-no-progress'); if (restTimeInput) restTimeInput.addEventListener('change', () => { config.restTime = (parseInt(restTimeInput.value) || 5) * 60; updateStatus('休息时间已更新: ' + restTimeInput.value + '分钟'); }); if (scrollTimeInput) scrollTimeInput.addEventListener('change', () => { config.scrollTime = parseInt(scrollTimeInput.value) || 10; updateStatus('滚动时间已更新: ' + scrollTimeInput.value + '秒'); }); if (waitTimeInput) waitTimeInput.addEventListener('change', () => { config.waitTime = parseInt(waitTimeInput.value) || 10; updateStatus('等待时间已更新: ' + waitTimeInput.value + '秒'); }); if (maxNoProgressInput) maxNoProgressInput.addEventListener('change', () => { config.maxNoProgressCount = parseInt(maxNoProgressInput.value) || 3; updateStatus('容错次数已更新: ' + maxNoProgressInput.value + '次'); }); }, 600); } function toggleCollapse() { searchState.isCollapsed = !searchState.isCollapsed; applyCollapseState(); } function applyCollapseState() { const searchTermsContainer = document.getElementById('rewards-search-terms-container'); const configSection = document.getElementById('rewards-config-section'); const minimizeBtn = document.getElementById('minimize-btn'); if (searchState.isCollapsed) { if (searchTermsContainer) searchTermsContainer.style.display = 'none'; if (configSection) configSection.style.display = 'none'; if (minimizeBtn) minimizeBtn.textContent = '+'; } else { if (searchTermsContainer) searchTermsContainer.style.display = 'block'; if (configSection) configSection.style.display = 'block'; if (minimizeBtn) minimizeBtn.textContent = '-'; } } function updateStatus(message) { const statusElement = document.getElementById('search-status'); if (statusElement) statusElement.textContent = message || ''; } function updateCountdown(seconds, action) { const countdownElement = document.getElementById('countdown'); if (countdownElement) { if (seconds > 0) { let actionText = ""; switch (action) { case 'scrolling': actionText = '滚动中'; break; case 'waiting': actionText = '等待中'; break; case 'resting': actionText = '休息中'; break; default: actionText = '倒计时'; } countdownElement.textContent = `${actionText}: ${seconds}秒`; countdownElement.style.display = 'block'; } else { countdownElement.style.display = 'none'; } } } function updateProgressUI() { const elem = document.getElementById('rewards-progress'); const bar = document.querySelector('.progress-bar-inner'); let current = currentProgress.current, total = currentProgress.total; if (!total || total === 0) total = 1; let percent = Math.min(100, Math.round((current / total) * 100)); if (elem) { let done = currentProgress.completed; elem.innerHTML = `进度: <span class="progress-value">${current}/${total}${done ? " (已完成)" : ""}</span>`; } if (bar) bar.style.width = percent + "%"; } function updateSearchTermsUI() { const mainTermsContainer = document.getElementById('main-search-terms'); if (mainTermsContainer) { mainTermsContainer.innerHTML = ""; mainPageSearchTerms.forEach(term => { const div = document.createElement('span'); div.className = "term-pill" + (usedSearchTerms.includes(term) ? " used" : ""); div.textContent = term; mainTermsContainer.appendChild(div); }); } const iframeTermsContainer = document.getElementById('iframe-search-terms'); if (iframeTermsContainer) { iframeTermsContainer.innerHTML = ""; iframeSearchTerms.forEach(term => { const div = document.createElement('span'); div.className = "term-pill" + (usedSearchTerms.includes(term) ? " used" : ""); div.textContent = term; iframeTermsContainer.appendChild(div); }); } } function makeDraggable(container, header) { let offsetX, offsetY, isDragging = false; header.addEventListener('mousedown', (e) => { if (window.getComputedStyle(e.target).cursor === 'pointer') return; isDragging = true; if (container.style.right) { container.style.left = container.offsetLeft + 'px'; container.style.right = ''; } offsetX = e.clientX - container.offsetLeft; offsetY = e.clientY - container.offsetTop; document.body.style.userSelect = 'none'; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp, { once: true }); function onMouseMove(e) { if (!isDragging) return; container.style.top = (e.clientY - offsetY) + 'px'; container.style.left = (e.clientX - offsetX) + 'px'; } function onMouseUp() { isDragging = false; document.body.style.userSelect = ''; document.removeEventListener('mousemove', onMouseMove); } }); } // ----------- 自动Rewards主逻辑(融合UI) ----------- function openRewardsSidebar() { const pointsContainer = document.querySelector('.points-container'); if (pointsContainer) { pointsContainer.click(); return true; } return false; } function getDataFromIframe() { const iframe = document.querySelector('iframe'); if (!iframe) return false; try { const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; // 1. 检查已获取积分 const allElements = iframeDoc.querySelectorAll('*'); for (let element of allElements) { const text = element.textContent || ''; if (text.includes('你已获得') && text.includes('积分')) { const match = text.match(/你已获得\s*(\d+)\s*积分/); if (match) { const totalPoints = parseInt(match[1]); currentProgress.current = totalPoints; currentProgress.total = totalPoints; currentProgress.completed = true; updateProgressUI(); return true; } } } // 2. 特定promo-title const promoTitleElements = iframeDoc.querySelectorAll('.promo-title'); if (promoTitleElements.length > 0) { for (let element of promoTitleElements) { const text = element.textContent || ''; if (text.includes('已获得')) { const match = text.match(/已获得\s*(\d+)\s*积分/); if (match) { const totalPoints = parseInt(match[1]); currentProgress.current = totalPoints; currentProgress.total = totalPoints; currentProgress.completed = true; updateProgressUI(); return true; } } } } // 3. offer not completed const offerElements = iframeDoc.querySelectorAll('[aria-label="Offer not Completed"]'); if (offerElements.length > 0) { for (let element of offerElements) { const text = element.textContent || ''; if (text.includes('已获得') && text.includes('积分')) { const match = text.match(/已获得\s*(\d+)\s*积分/); if (match) { const totalPoints = parseInt(match[1]); currentProgress.current = totalPoints; currentProgress.total = totalPoints; currentProgress.completed = true; updateProgressUI(); return true; } } } } // 未完成,获取正常进度 const progressElement = iframeDoc.querySelector('.daily_search_row span:last-child'); if (progressElement) { const progress = progressElement.textContent; const match = progress.match(/(\d+)\/(\d+)/); if (match) { const current = parseInt(match[1]); currentProgress.total = parseInt(match[2]); if (currentProgress.lastChecked > 0 && current <= currentProgress.lastChecked && isSearching) { currentProgress.noProgressCount++; if (currentProgress.noProgressCount >= config.maxNoProgressCount) { searchState.needRest = true; } } else if (current > currentProgress.lastChecked) { currentProgress.noProgressCount = 0; } currentProgress.current = current; currentProgress.lastChecked = current; if (current >= currentProgress.total) { currentProgress.completed = true; } } updateProgressUI(); } // 获取iframe中的搜索词 const searchTermsContainer = iframeDoc.querySelector('.ss_items_wrapper'); if (searchTermsContainer) { const terms = []; const spans = searchTermsContainer.querySelectorAll('span'); spans.forEach(span => { if (span.textContent) terms.push(span.textContent); }); iframeSearchTerms = [...terms]; updateSearchTermsUI(); } return true; } catch (e) { return false; } } function getSearchTermsFromMainDoc() { const suggestionsContainer = document.querySelector('.richrsrailsugwrapper'); if (suggestionsContainer) { const terms = []; const suggestions = suggestionsContainer.querySelectorAll('.richrsrailsuggestion_text'); suggestions.forEach(suggestion => { if (suggestion.textContent) terms.push(suggestion.textContent); }); mainPageSearchTerms = [...terms]; updateSearchTermsUI(); return true; } return false; } function getRewardsData(callback) { updateStatus('正在获取奖励数据...'); if (openRewardsSidebar()) { setTimeout(() => { const iframeLoaded = getDataFromIframe(); const mainTermsLoaded = getSearchTermsFromMainDoc(); updateProgressUI(); updateSearchTermsUI(); if (!iframeLoaded && !mainTermsLoaded) { updateStatus('获取数据失败,请重试'); } else { updateStatus('数据获取成功'); if (currentProgress.completed) { updateStatus('搜索任务已完成!'); if (isSearching) { showCompletionNotification(); stopAutomatedSearch(); } } } if (searchState.needRest && isSearching) { startResting(); } else if (callback) { callback(); } }, 1500); } else { updateStatus('未找到积分按钮,请确保已登录'); if (callback) callback(); } } function startResting() { searchState.needRest = false; currentProgress.noProgressCount = 0; updateStatus(`连续 ${config.maxNoProgressCount} 次搜索无进度,休息 ${config.restTime / 60} 分钟后继续`); startCountdown(config.restTime, 'resting', () => { updateStatus('休息结束,继续搜索'); setTimeout(performNextSearch, 1000); }); } function getSearchTerm() { let availableMainTerms = mainPageSearchTerms.filter(term => !usedSearchTerms.includes(term)); let availableIframeTerms = iframeSearchTerms.filter(term => !usedSearchTerms.includes(term)); if (availableMainTerms.length === 0 && availableIframeTerms.length === 0 && (mainPageSearchTerms.length > 0 || iframeSearchTerms.length > 0)) { usedSearchTerms = []; availableMainTerms = [...mainPageSearchTerms]; availableIframeTerms = [...iframeSearchTerms]; } if (availableMainTerms.length > 0) { const randomIndex = Math.floor(Math.random() * availableMainTerms.length); const term = availableMainTerms[randomIndex]; usedSearchTerms.push(term); updateSearchTermsUI(); return { term: term, source: '主页面' }; } else if (availableIframeTerms.length > 0) { const randomIndex = Math.floor(Math.random() * availableIframeTerms.length); const term = availableIframeTerms[randomIndex]; usedSearchTerms.push(term); updateSearchTermsUI(); return { term: term, source: 'iframe' }; } return null; } function performSearch(term) { if (!term) return false; const searchBox = document.querySelector('#sb_form_q'); if (searchBox) { searchBox.value = term; const searchForm = document.querySelector('#sb_form'); if (searchForm) { searchForm.submit(); return true; } } return false; } function simulateScrolling(callback) { updateStatus('正在滚动页面...'); searchState.currentAction = 'scrolling'; startCountdown(config.scrollTime, 'scrolling', callback); const scrollInterval = setInterval(() => { const scrollAmount = Math.floor(Math.random() * 300) + 100; const scrollDirection = Math.random() > 0.3 ? 1 : -1; window.scrollBy(0, scrollAmount * scrollDirection); if (searchState.currentAction !== 'scrolling') clearInterval(scrollInterval); }, 1000); setTimeout(() => { clearInterval(scrollInterval); }, config.scrollTime * 1000); } function checkProgress(callback) { updateStatus('正在检查搜索进度...'); searchState.currentAction = 'checking'; if (openRewardsSidebar()) { setTimeout(() => { getDataFromIframe(); getSearchTermsFromMainDoc(); updateProgressUI(); updateSearchTermsUI(); if (currentProgress.completed) { showCompletionNotification(); updateStatus('搜索任务已完成!'); stopAutomatedSearch(); return; } if (searchState.needRest) { startResting(); } else if (callback) { callback(); } }, 1500); } else { updateStatus('无法打开侧边栏检查进度'); if (callback) callback(); } } function waitForNextSearch() { updateStatus('等待下一次搜索...'); startCountdown(config.waitTime, 'waiting', performNextSearch); } function performNextSearch() { if (!isSearching) return; const remainingSearches = currentProgress.total - currentProgress.current; if (remainingSearches <= 0 || currentProgress.completed) { showCompletionNotification(); updateStatus('搜索任务已完成!'); stopAutomatedSearch(); return; } updateStatus('获取最新搜索词...'); getSearchTermsFromMainDoc(); updateSearchTermsUI(); const searchTermObj = getSearchTerm(); if (!searchTermObj) { updateStatus('没有可用的搜索词,获取数据...'); getRewardsData(() => { const newSearchTermObj = getSearchTerm(); if (newSearchTermObj) { setTimeout(performNextSearch, 1000); } else { updateStatus('无法获取搜索词,停止搜索'); stopAutomatedSearch(); } }); return; } const { term, source } = searchTermObj; updateStatus(`正在搜索: ${term} (${source}搜索词) [剩余:${remainingSearches}]`); if (performSearch(term)) { setTimeout(() => { simulateScrolling(() => { checkProgress(() => { waitForNextSearch(); }); }); }, 2000); } else { updateStatus('搜索失败,请检查网页状态'); setTimeout(performNextSearch, 3000); } } function startAutomatedSearch() { if (mainPageSearchTerms.length === 0 && iframeSearchTerms.length === 0) { updateStatus('获取搜索词中...'); getRewardsData(() => { if (mainPageSearchTerms.length === 0 && iframeSearchTerms.length === 0) { alert('没有搜索词,无法开始搜索'); return; } else { startSearchProcess(); } }); } else { startSearchProcess(); } } function startSearchProcess() { isSearching = true; searchState.needRest = false; currentProgress.noProgressCount = 0; usedSearchTerms = []; document.getElementById('start-search-btn').textContent = '停止搜索'; document.getElementById('start-search-btn').classList.add('stop'); updateStatus('自动搜索已开始...'); updateProgressUI(); updateSearchTermsUI(); const remainingSearches = currentProgress.total - currentProgress.current; if (remainingSearches <= 0 || currentProgress.completed) { updateStatus('搜索任务已完成!'); stopAutomatedSearch(); return; } performNextSearch(); } function stopAutomatedSearch() { if (countdownTimer) { clearInterval(countdownTimer); countdownTimer = null; } isSearching = false; searchState.currentAction = 'idle'; searchState.needRest = false; currentProgress.noProgressCount = 0; usedSearchTerms = []; updateCountdown(0, ''); document.getElementById('start-search-btn').textContent = '开始自动搜索'; document.getElementById('start-search-btn').classList.remove('stop'); updateStatus('搜索已停止'); } function showCompletionNotification() { const notification = document.createElement('div'); notification.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #0078d4; color: white; padding: 20px; border-radius: 5px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); z-index: 10001; text-align: center; font-size: 16px; `; notification.innerHTML = ` <div style="font-weight: bold; margin-bottom: 10px; font-size: 18px;">任务完成!</div> <div>已完成所有 ${currentProgress.total} 次搜索任务</div> <button id="notification-close" style=" margin-top: 15px; padding: 5px 15px; background-color: white; color: #0078d4; border: none; border-radius: 3px; cursor: pointer; ">关闭</button> `; document.body.appendChild(notification); document.getElementById('notification-close').addEventListener('click', function () { notification.remove(); }); setTimeout(() => { if (document.body.contains(notification)) notification.remove(); }, 10000); } function startCountdown(seconds, action, callback) { if (countdownTimer) { clearInterval(countdownTimer); countdownTimer = null; } searchState.currentAction = action; searchState.countdown = seconds; updateCountdown(seconds, action); countdownTimer = setInterval(() => { searchState.countdown--; updateCountdown(searchState.countdown, action); if (searchState.countdown <= 0) { clearInterval(countdownTimer); countdownTimer = null; if (callback) callback(); } }, 1000); } window.addEventListener('load', function () { createUI(); applyCollapseState(); setTimeout(() => { getRewardsData(); }, 2000); }); })();