您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动完成 Microsoft Rewards 在必应(Bing)上的每日搜索任务,带有可配置的UI界面,模拟人工操作以提高安全性。
// ==UserScript== // @name Microsoft Rewards 自动搜索助手 // @name:en Microsoft Rewards Auto Searcher // @namespace WretchedSniper // @version 1.0.0 // @description 自动完成 Microsoft Rewards 在必应(Bing)上的每日搜索任务,带有可配置的UI界面,模拟人工操作以提高安全性。 // @description:en Automatically completes Microsoft Rewards daily search tasks on Bing. Features a configurable UI and mimics human behavior for better safety. // @author WretchedSniper // @match *://*.bing.com/* // @grant none // @run-at document-end // @license MIT // @icon https://www.bing.com/favicon.ico // ==/UserScript== (function () { 'use strict'; // 存储搜索词和当前进度 let mainPageSearchTerms = []; // 主页面搜索词 let iframeSearchTerms = []; // iframe搜索词 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], // 搜索间隔范围(秒) debug: true, // 调试模式 maxNoProgressCount: 3 // 连续多少次不增加分数才休息 }; // 工作状态 const searchState = { currentAction: 'idle', // 当前动作:idle, searching, scrolling, checking, waiting, resting countdown: 0, // 倒计时 needRest: false // 是否需要休息 }; // 创建UI控件 function createUI() { const container = document.createElement('div'); container.id = 'rewards-helper-container'; container.style.cssText = ` position: fixed; top: 20px; right: 20px; background-color: white; border: 1px solid #ddd; border-radius: 5px; padding: 10px; z-index: 10000; box-shadow: 0 2px 5px rgba(0,0,0,0.2); width: 300px; `; const header = document.createElement('div'); header.style.cssText = ` font-weight: bold; margin-bottom: 10px; border-bottom: 1px solid #ddd; padding-bottom: 5px; display: flex; justify-content: space-between; `; header.textContent = 'Microsoft Rewards 助手'; const closeBtn = document.createElement('span'); closeBtn.textContent = '×'; closeBtn.style.cssText = ` cursor: pointer; font-size: 18px; `; closeBtn.onclick = function () { container.style.display = 'none'; }; header.appendChild(closeBtn); const content = document.createElement('div'); content.id = 'rewards-helper-content'; content.style.cssText = ` margin-bottom: 10px; `; const progress = document.createElement('div'); progress.id = 'rewards-progress'; progress.textContent = '进度: 加载中...'; content.appendChild(progress); const searchStatus = document.createElement('div'); searchStatus.id = 'search-status'; searchStatus.style.cssText = ` margin-top: 5px; font-style: italic; `; content.appendChild(searchStatus); const countdown = document.createElement('div'); countdown.id = 'countdown'; countdown.style.cssText = ` margin-top: 5px; font-weight: bold; color: #0078d4; `; content.appendChild(countdown); // 添加调试日志区域 const debugLog = document.createElement('div'); debugLog.id = 'debug-log'; debugLog.style.cssText = ` margin-top: 5px; font-size: 12px; color: #666; max-height: 80px; overflow-y: auto; border-top: 1px dashed #ccc; padding-top: 5px; display: ${config.debug ? 'block' : 'none'}; `; content.appendChild(debugLog); const searchTermsContainer = document.createElement('div'); searchTermsContainer.style.cssText = ` margin-top: 10px; max-height: 200px; overflow-y: auto; `; const mainTermsTitle = document.createElement('div'); mainTermsTitle.textContent = '主页面搜索词:'; mainTermsTitle.style.fontWeight = 'bold'; searchTermsContainer.appendChild(mainTermsTitle); const mainTerms = document.createElement('div'); mainTerms.id = 'main-search-terms'; mainTerms.style.cssText = ` margin-bottom: 10px; padding-left: 10px; `; searchTermsContainer.appendChild(mainTerms); const iframeTermsTitle = document.createElement('div'); iframeTermsTitle.textContent = 'iframe中的搜索词:'; iframeTermsTitle.style.fontWeight = 'bold'; searchTermsContainer.appendChild(iframeTermsTitle); const iframeTerms = document.createElement('div'); iframeTerms.id = 'iframe-search-terms'; iframeTerms.style.cssText = ` padding-left: 10px; `; searchTermsContainer.appendChild(iframeTerms); content.appendChild(searchTermsContainer); const configSection = document.createElement('div'); configSection.style.cssText = ` margin-top: 10px; border-top: 1px solid #ddd; padding-top: 10px; `; const configTitle = document.createElement('div'); configTitle.textContent = '配置参数:'; configTitle.style.fontWeight = 'bold'; configSection.appendChild(configTitle); const configForm = document.createElement('div'); configForm.style.cssText = ` display: grid; grid-template-columns: auto auto; gap: 5px; margin-top: 5px; `; // 添加休息时间配置 configForm.innerHTML += ` <label for="rest-time">休息时间(分):</label> <input type="number" id="rest-time" value="${config.restTime / 60}" min="1" max="30" style="width: 50px;"> <label for="scroll-time">滚动时间(秒):</label> <input type="number" id="scroll-time" value="${config.scrollTime}" min="3" max="30" style="width: 50px;"> <label for="wait-time">等待时间(秒):</label> <input type="number" id="wait-time" value="${config.waitTime}" min="3" max="30" style="width: 50px;"> <label for="max-no-progress">容错次数:</label> <input type="number" id="max-no-progress" value="${config.maxNoProgressCount}" min="1" max="10" style="width: 50px;"> <label for="debug-mode">调试模式:</label> <input type="checkbox" id="debug-mode" ${config.debug ? 'checked' : ''}> `; configSection.appendChild(configForm); // 添加输入框变化事件监听 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'); const debugModeInput = document.getElementById('debug-mode'); if (restTimeInput) { restTimeInput.addEventListener('change', () => { const restTime = parseInt(restTimeInput.value) || 5; config.restTime = restTime * 60; updateStatus('休息时间已更新: ' + restTime + '分钟'); }); } if (scrollTimeInput) { scrollTimeInput.addEventListener('change', () => { const scrollTime = parseInt(scrollTimeInput.value) || 10; config.scrollTime = scrollTime; updateStatus('滚动时间已更新: ' + scrollTime + '秒'); }); } if (waitTimeInput) { waitTimeInput.addEventListener('change', () => { const waitTime = parseInt(waitTimeInput.value) || 10; config.waitTime = waitTime; updateStatus('等待时间已更新: ' + waitTime + '秒'); }); } if (maxNoProgressInput) { maxNoProgressInput.addEventListener('change', () => { const maxNoProgressCount = parseInt(maxNoProgressInput.value) || 3; config.maxNoProgressCount = maxNoProgressCount; updateStatus('容错次数已更新: ' + maxNoProgressCount + '次'); }); } if (debugModeInput) { debugModeInput.addEventListener('change', () => { config.debug = debugModeInput.checked; document.getElementById('debug-log').style.display = config.debug ? 'block' : 'none'; updateStatus('调试模式: ' + (config.debug ? '开启' : '关闭')); }); } }, 1000); content.appendChild(configSection); const buttonsContainer = document.createElement('div'); buttonsContainer.style.cssText = ` display: flex; justify-content: center; margin-top: 10px; `; const startSearchBtn = document.createElement('button'); startSearchBtn.id = 'start-search-btn'; startSearchBtn.textContent = '开始自动搜索'; startSearchBtn.style.cssText = ` padding: 5px 10px; cursor: pointer; background-color: #0078d4; color: white; border: none; border-radius: 3px; width: 100%; `; startSearchBtn.onclick = function () { if (!isSearching) { startAutomatedSearch(); } else { stopAutomatedSearch(); } }; buttonsContainer.appendChild(startSearchBtn); container.appendChild(header); container.appendChild(content); container.appendChild(buttonsContainer); document.body.appendChild(container); } // 更新状态显示 function updateStatus(message) { const statusElement = document.getElementById('search-status'); if (statusElement) { statusElement.textContent = message; } console.log(message); } // 添加调试日志 function logDebug(message) { if (!config.debug) return; console.log('[DEBUG] ' + message); const logElement = document.getElementById('debug-log'); if (logElement) { const logItem = document.createElement('div'); logItem.textContent = new Date().toLocaleTimeString() + ': ' + message; logElement.appendChild(logItem); // 自动滚动到底部 logElement.scrollTop = logElement.scrollHeight; // 限制日志条数 while (logElement.childNodes.length > 20) { logElement.removeChild(logElement.firstChild); } } } // 更新倒计时显示 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; case 'checking': actionText = '检查中'; break; default: actionText = '倒计时'; } countdownElement.textContent = `${actionText}: ${seconds}秒`; countdownElement.style.display = 'block'; } else { countdownElement.style.display = 'none'; } } } // 开始倒计时 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); } // 点击打开侧边栏 function openRewardsSidebar() { const pointsContainer = document.querySelector('.points-container'); if (pointsContainer) { pointsContainer.click(); logDebug('已点击积分按钮,正在打开侧边栏...'); return true; } else { logDebug('未找到积分按钮'); return false; } } // 从iframe中获取数据 function getDataFromIframe() { const iframe = document.querySelector('iframe'); if (!iframe) { logDebug('未找到iframe'); return false; } try { const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; logDebug('成功访问iframe文档'); // 获取进度 - 检查任务完成的几种可能情况 // 1. 检查包含"你已获得 X 积分"文本的元素 const allElements = iframeDoc.querySelectorAll('*'); for (let element of allElements) { const text = element.textContent || ''; if (text.includes('你已获得') && text.includes('积分')) { logDebug(`找到完成文本: "${text}"`); const match = text.match(/你已获得\s*(\d+)\s*积分/); if (match) { const totalPoints = parseInt(match[1]); currentProgress.current = totalPoints; currentProgress.total = totalPoints; currentProgress.completed = true; document.getElementById('rewards-progress').textContent = `进度: ${totalPoints}/${totalPoints} (已完成)`; logDebug(`搜索任务已完成! 总积分: ${totalPoints}`); return true; } } } // 2. 特定检查promo-title类 const promoTitleElements = iframeDoc.querySelectorAll('.promo-title'); if (promoTitleElements.length > 0) { for (let element of promoTitleElements) { const text = element.textContent || ''; logDebug(`找到promo-title元素: "${text}"`); 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; document.getElementById('rewards-progress').textContent = `进度: ${totalPoints}/${totalPoints} (已完成)`; logDebug(`搜索任务已完成! 总积分: ${totalPoints}`); return true; } } } } // 3. 检查是否有"Offer not Completed"的标识 const offerElements = iframeDoc.querySelectorAll('[aria-label="Offer not Completed"]'); if (offerElements.length > 0) { logDebug('找到"Offer not Completed"元素,但仍需检查是否实际完成'); // 即使有这个标识,也可能已经完成,所以继续检查 for (let element of offerElements) { const text = element.textContent || ''; if (text.includes('已获得') && text.includes('积分')) { logDebug(`找到完成文本: "${text}"`); const match = text.match(/已获得\s*(\d+)\s*积分/); if (match) { const totalPoints = parseInt(match[1]); currentProgress.current = totalPoints; currentProgress.total = totalPoints; currentProgress.completed = true; document.getElementById('rewards-progress').textContent = `进度: ${totalPoints}/${totalPoints} (已完成)`; logDebug(`搜索任务已完成! 总积分: ${totalPoints}`); return true; } } } } // 如果未完成,获取正常进度 const progressElement = iframeDoc.querySelector('.daily_search_row span:last-child'); if (progressElement) { const progress = progressElement.textContent; document.getElementById('rewards-progress').textContent = '进度: ' + progress; logDebug('搜索进度: ' + progress); // 解析进度数字 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) { logDebug(`进度未增加: ${current} <= ${currentProgress.lastChecked},已连续 ${currentProgress.noProgressCount + 1} 次未增加`); currentProgress.noProgressCount++; // 只有当连续多次未增加进度时才休息 if (currentProgress.noProgressCount >= config.maxNoProgressCount) { searchState.needRest = true; logDebug(`达到最大容错次数 ${config.maxNoProgressCount},需要休息`); } } else if (current > currentProgress.lastChecked) { // 进度增加,重置计数器 logDebug(`进度增加: ${current} > ${currentProgress.lastChecked},重置未增加计数`); currentProgress.noProgressCount = 0; } currentProgress.current = current; currentProgress.lastChecked = current; // 检查是否完成 if (current >= currentProgress.total) { currentProgress.completed = true; logDebug(`进度数字表明任务已完成: ${current}/${currentProgress.total}`); } } } else { logDebug('未找到进度元素'); } // 获取iframe中的搜索词 const searchTermsContainer = iframeDoc.querySelector('.ss_items_wrapper'); if (searchTermsContainer) { const terms = []; const spans = searchTermsContainer.querySelectorAll('span'); spans.forEach(span => { terms.push(span.textContent); }); // 保存到iframe搜索词变量 iframeSearchTerms = [...terms]; const termsContainer = document.getElementById('iframe-search-terms'); termsContainer.innerHTML = ''; terms.forEach(term => { const termElem = document.createElement('div'); termElem.textContent = term; termsContainer.appendChild(termElem); }); logDebug('找到iframe搜索词: ' + terms.length + '个'); } else { logDebug('未找到iframe搜索词容器'); } return true; } catch (e) { logDebug('读取iframe内容出错: ' + e.message); return false; } } // 从主文档中获取搜索词 function getSearchTermsFromMainDoc() { const suggestionsContainer = document.querySelector('.richrsrailsugwrapper'); if (suggestionsContainer) { const terms = []; const suggestions = suggestionsContainer.querySelectorAll('.richrsrailsuggestion_text'); suggestions.forEach(suggestion => { terms.push(suggestion.textContent); }); // 保存到主页面搜索词变量 mainPageSearchTerms = [...terms]; const termsContainer = document.getElementById('main-search-terms'); termsContainer.innerHTML = ''; terms.forEach(term => { const termElem = document.createElement('div'); termElem.textContent = term; termsContainer.appendChild(termElem); }); logDebug('找到主页面搜索词: ' + terms.length + '个'); return true; } else { logDebug('未找到主页面搜索词'); return false; } } // 获取Rewards数据 function getRewardsData(callback) { updateStatus('正在获取奖励数据...'); if (openRewardsSidebar()) { // 等待iframe加载 setTimeout(() => { const iframeLoaded = getDataFromIframe(); const mainTermsLoaded = getSearchTermsFromMainDoc(); 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); }); } // 获取搜索词(优先主页面,其次iframe) 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)) { logDebug('所有搜索词已用完,重置已使用列表'); usedSearchTerms = []; availableMainTerms = [...mainPageSearchTerms]; availableIframeTerms = [...iframeSearchTerms]; } // 优先使用主页面搜索词 if (availableMainTerms.length > 0) { const randomIndex = Math.floor(Math.random() * availableMainTerms.length); const term = availableMainTerms[randomIndex]; // 添加到已使用列表 usedSearchTerms.push(term); logDebug(`选择搜索词: ${term} (主页面,还有 ${availableMainTerms.length - 1} 个未使用)`); return { term: term, source: '主页面' }; } // 如果主页面没有搜索词,使用iframe搜索词 else if (availableIframeTerms.length > 0) { const randomIndex = Math.floor(Math.random() * availableIframeTerms.length); const term = availableIframeTerms[randomIndex]; // 添加到已使用列表 usedSearchTerms.push(term); logDebug(`选择搜索词: ${term} (iframe,还有 ${availableIframeTerms.length - 1} 个未使用)`); return { term: term, source: 'iframe' }; } // 如果都没有搜索词,返回null 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; // 70%向下,30%向上 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(); 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(); // 获取搜索词 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('搜索失败,请检查网页状态'); // 3秒后重试 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').style.backgroundColor = '#d83b01'; updateStatus('自动搜索已开始...'); // 计算还需要搜索的次数 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').style.backgroundColor = '#0078d4'; 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(); }); // 10秒后自动关闭 setTimeout(() => { if (document.body.contains(notification)) { notification.remove(); } }, 10000); } // 在页面加载完成后初始化 window.addEventListener('load', function () { console.log('Microsoft Rewards 助手已加载'); createUI(); // 初始获取数据 setTimeout(() => { getRewardsData(); }, 2000); }); })();