// ==UserScript== // @name Welearn助手 // @namespace https://bbs.tampermonkey.net.cn/ // @version 0.2.3 // @author 恶搞之家 // @description 自动选择Welearn平台的选择题、判断题、填空题和下拉框答案 // @match *://welearn.sflep.com/Student/StudyCourse.aspx* // @match *://welearn.sflep.com/student/StudyCourse.aspx* // @match *://welearn.sflep.com/student/studyCourse.aspx* // @match *://welearn.sflep.com/student/Studycourse.aspx* // @match *://welearn.sflep.com/student/studycourse.aspx* // @match *://welearn.sflep.com/course/trycourse.aspx* // @match *://welearn.sflep.com/course/Trycourse.aspx* // @match *://welearn.sflep.com/course/TryCourse.aspx* // @match *://welearn.sflep.com/*/TryCourse.aspx* // @grant GM_getValue // @grant GM_setValue // ==/UserScript== (function () { 'use strict'; // 预设主题方案 const themePresets = { default: { name: '默认绿色', primaryColor: '#4CAF50', secondaryColor: '#45a049', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#e0e0e0', buttonColor: '#26a69a', buttonHoverColor: '#2ab7a9', accentColor: '#5c6bc0', borderColor: 'rgba(255, 255, 255, 0.12)' }, pink: { name: '少女粉', primaryColor: '#FF69B4', secondaryColor: '#FF1493', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#FFB6C1', buttonColor: '#FF69B4', buttonHoverColor: '#FF1493', accentColor: '#DDA0DD', borderColor: 'rgba(255, 192, 203, 0.3)' }, sakura: { name: '樱花粉', primaryColor: '#FFB7C5', secondaryColor: '#FF9EB5', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#FFE4E1', buttonColor: '#FF8DA1', buttonHoverColor: '#FF7B93', accentColor: '#FFB5C5', borderColor: 'rgba(255, 228, 225, 0.3)' }, coral: { name: '珊瑚橙', primaryColor: '#FF7F50', secondaryColor: '#FF6347', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#FFA07A', buttonColor: '#FF8C69', buttonHoverColor: '#FF7256', accentColor: '#FA8072', borderColor: 'rgba(255, 160, 122, 0.3)' }, blue: { name: '深邃蓝', primaryColor: '#1976D2', secondaryColor: '#1565C0', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#90CAF9', buttonColor: '#2196F3', buttonHoverColor: '#1976D2', accentColor: '#64B5F6', borderColor: 'rgba(144, 202, 249, 0.3)' }, ocean: { name: '海洋蓝', primaryColor: '#00CED1', secondaryColor: '#20B2AA', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#E0FFFF', buttonColor: '#48D1CC', buttonHoverColor: '#40E0D0', accentColor: '#00CED1', borderColor: 'rgba(224, 255, 255, 0.3)' }, purple: { name: '神秘紫', primaryColor: '#9C27B0', secondaryColor: '#7B1FA2', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#E1BEE7', buttonColor: '#BA68C8', buttonHoverColor: '#AB47BC', accentColor: '#9575CD', borderColor: 'rgba(225, 190, 231, 0.3)' }, lavender: { name: '薰衣草', primaryColor: '#9B59B6', secondaryColor: '#8E44AD', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#D7BDE2', buttonColor: '#AF7AC5', buttonHoverColor: '#A569BD', accentColor: '#BB8FCE', borderColor: 'rgba(215, 189, 226, 0.3)' }, mint: { name: '薄荷绿', primaryColor: '#00B894', secondaryColor: '#00A885', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#E0F2F1', buttonColor: '#1ABC9C', buttonHoverColor: '#16A085', accentColor: '#4DB6AC', borderColor: 'rgba(224, 242, 241, 0.3)' }, gold: { name: '金色', primaryColor: '#F1C40F', secondaryColor: '#F39C12', backgroundColor: 'rgba(28, 32, 34, 0.92)', textColor: '#FFF3E0', buttonColor: '#FFB300', buttonHoverColor: '#FFA000', accentColor: '#FFD700', borderColor: 'rgba(255, 243, 224, 0.3)' }, dark: { name: '暗夜黑', primaryColor: '#424242', secondaryColor: '#212121', backgroundColor: 'rgba(18, 18, 18, 0.95)', textColor: '#BDBDBD', buttonColor: '#616161', buttonHoverColor: '#757575', accentColor: '#9E9E9E', borderColor: 'rgba(189, 189, 189, 0.2)' } }; let currentTheme = GM_getValue('welearnTheme', themePresets.default); function createThemePanel() { const themePanel = document.createElement('div'); themePanel.id = 'welearnThemePanel'; themePanel.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: ${currentTheme.backgroundColor}; padding: 20px; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35); z-index: 10001; display: none; width: 300px; color: ${currentTheme.textColor}; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; `; const title = document.createElement('h3'); title.textContent = '主题选择'; title.style.cssText = ` margin: 0 0 20px 0; color: ${currentTheme.textColor}; text-align: center; font-size: 18px; `; const themesContainer = document.createElement('div'); themesContainer.style.cssText = ` display: grid; gap: 10px; grid-template-columns: repeat(2, 1fr); `; Object.entries(themePresets).forEach(([key, theme]) => { const themeButton = document.createElement('button'); themeButton.textContent = theme.name; themeButton.style.cssText = ` padding: 15px; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.3s ease; background: linear-gradient(135deg, ${theme.primaryColor}, ${theme.secondaryColor}); color: ${theme.textColor}; position: relative; overflow: hidden; `; themeButton.addEventListener('mouseover', () => { themeButton.style.transform = 'scale(1.05)'; themeButton.style.boxShadow = `0 4px 15px ${theme.primaryColor}40`; }); themeButton.addEventListener('mouseout', () => { themeButton.style.transform = 'scale(1)'; themeButton.style.boxShadow = 'none'; }); themeButton.addEventListener('click', () => { currentTheme = { ...theme }; GM_setValue('welearnTheme', currentTheme); updateUIColors(); themePanel.style.display = 'none'; }); themesContainer.appendChild(themeButton); }); const closeButton = document.createElement('button'); closeButton.textContent = '关闭'; closeButton.style.cssText = ` padding: 8px 16px; background: #666; color: white; border: none; border-radius: 4px; cursor: pointer; transition: all 0.3s ease; margin-top: 20px; width: 100%; `; closeButton.addEventListener('click', () => { themePanel.style.display = 'none'; }); themePanel.appendChild(title); themePanel.appendChild(themesContainer); themePanel.appendChild(closeButton); return themePanel; } function updateUIColors() { const panel = document.getElementById('welearnHelperPanel'); if (!panel) return; panel.style.background = currentTheme.backgroundColor; panel.style.color = currentTheme.textColor; panel.style.borderColor = currentTheme.borderColor; const titleBar = panel.querySelector('.welearn-title-bar'); if (titleBar) { titleBar.style.background = `linear-gradient(135deg, ${currentTheme.primaryColor}15, ${currentTheme.secondaryColor}10, ${currentTheme.primaryColor}15)`; } const buttons = panel.querySelectorAll('.welearn-button'); buttons.forEach(button => { if (button.classList.contains('welearn-auto-button')) { button.style.background = `linear-gradient(135deg, ${currentTheme.buttonColor} 0%, ${currentTheme.buttonHoverColor} 100%)`; } else if (button.classList.contains('welearn-loop-button')) { button.style.background = `linear-gradient(135deg, ${currentTheme.accentColor} 0%, ${adjustColor(currentTheme.accentColor, -20)} 100%)`; } }); const containers = panel.querySelectorAll('.welearn-timer-container, .welearn-accuracy-container'); containers.forEach(container => { container.style.borderColor = currentTheme.borderColor; }); const inputs = panel.querySelectorAll('.welearn-time-input, .welearn-accuracy-input'); inputs.forEach(input => { input.style.borderColor = currentTheme.borderColor; input.style.color = currentTheme.textColor; }); } function adjustColor(color, amount) { return color.replace(/^#/, '').match(/.{2}/g).map(hex => { const num = Math.min(255, Math.max(0, parseInt(hex, 16) + amount)); return num.toString(16).padStart(2, '0'); }).join(''); } function addThemeButton() { const panel = document.getElementById('welearnHelperPanel'); if (!panel) return; const themeButton = document.createElement('button'); themeButton.className = 'welearn-theme-button'; themeButton.innerHTML = '🎨'; themeButton.style.cssText = ` position: absolute; top: 16px; right: 50px; background: none; border: none; color: ${currentTheme.textColor}; font-size: 18px; cursor: pointer; padding: 0; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; transition: all 0.3s ease; `; themeButton.addEventListener('mouseover', () => { themeButton.style.transform = 'rotate(180deg) scale(1.1)'; }); themeButton.addEventListener('mouseout', () => { themeButton.style.transform = 'none'; }); themeButton.addEventListener('click', () => { let themePanel = document.getElementById('welearnThemePanel'); if (!themePanel) { themePanel = createThemePanel(); document.body.appendChild(themePanel); } themePanel.style.display = themePanel.style.display === 'none' ? 'block' : 'none'; }); const titleBar = panel.querySelector('.welearn-title-bar'); titleBar.appendChild(themeButton); } const originalCreateIntegratedUI = createIntegratedUI; createIntegratedUI = function() { const panel = originalCreateIntegratedUI(); updateUIColors(); return panel; }; const originalAlert = window.alert; const originalConfirm = window.confirm; const originalPrompt = window.prompt; window.alert = function(message) { console.log('拦截到alert弹窗:', message); return true; }; window.confirm = function(message) { console.log('拦截到confirm弹窗:', message); return true; }; window.prompt = function(message, defaultValue) { console.log('拦截到prompt弹窗:', message); return defaultValue || ''; }; function handleIframeDialogs(iframe) { try { if (iframe.contentWindow) { iframe.contentWindow.alert = window.alert; iframe.contentWindow.confirm = window.confirm; iframe.contentWindow.prompt = window.prompt; } } catch (e) { console.log('处理iframe弹窗失败:', e); } } function setupIframeDialogHandlers() { const iframes = document.getElementsByTagName('iframe'); for (const iframe of iframes) { iframe.addEventListener('load', () => handleIframeDialogs(iframe)); handleIframeDialogs(iframe); } const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.tagName === 'IFRAME') { node.addEventListener('load', () => handleIframeDialogs(node)); handleIframeDialogs(node); } } } }); observer.observe(document.body, { childList: true, subtree: true }); } setupIframeDialogHandlers(); const originalWindow = window; setInterval(() => { if (window.alert !== originalWindow.alert) { window.alert = originalWindow.alert; } if (window.confirm !== originalWindow.confirm) { window.confirm = originalWindow.confirm; } if (window.prompt !== originalWindow.prompt) { window.prompt = originalWindow.prompt; } const iframes = document.getElementsByTagName('iframe'); for (const iframe of iframes) { handleIframeDialogs(iframe); } }, 1000); window.isAutoLoopActive = false; window.autoLoopTimeout = null; window.waitTimerActive = false; window.waitTimerInterval = null; window.defaultWaitTime = 30; window.defaultAccuracyRate = 100; window.autoNextEnabled = true; window.autoSubmitEnabled = true; const createEvent = (type, options = {}) => new Event(type, {bubbles: true, cancelable: true, ...options}); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); async function autoFillAnswers() { console.log('开始自动填空'); let filled = false; const answerElements = document.querySelectorAll('span.key, div.key'); const inputBoxes = document.querySelectorAll('span[autocapitalize="none"], textarea.blank'); const dataInputs = document.querySelectorAll('input[data-itemtype="input"], textarea[data-itemtype="input"]'); const textareaInputs = document.querySelectorAll('textarea[data-itemtype="textarea"]'); const editableSpans = document.querySelectorAll('span[contenteditable][ng-class*="blank.isOverflowed"]'); const totalInputs = inputBoxes.length + dataInputs.length + textareaInputs.length + editableSpans.length; console.log('找到填空题数量:', totalInputs); let correctCount, wrongCount; let wrongIndices = new Set(); if (totalInputs > 5) { correctCount = Math.ceil((totalInputs * window.defaultAccuracyRate) / 100); wrongCount = totalInputs - correctCount; console.log(`总题目: ${totalInputs}, 正确数: ${correctCount}, 错误数: ${wrongCount}`); while (wrongIndices.size < wrongCount) { const randomIndex = Math.floor(Math.random() * totalInputs); wrongIndices.add(randomIndex); } } let currentIndex = 0; if (inputBoxes.length > 0) { for (let index = 0; index < answerElements.length; index++) { try { const answer = answerElements[index].textContent; const inputBox = inputBoxes[index]; if (!inputBox) continue; let finalAnswer; if (totalInputs > 5 && wrongIndices.has(currentIndex)) { finalAnswer = answer + String.fromCharCode(65 + Math.floor(Math.random() * 26)); console.log(`准备填写第${currentIndex + 1}题错误答案:`, finalAnswer); } else { finalAnswer = answer; console.log(`准备填写第${currentIndex + 1}题正确答案:`, finalAnswer); } if (inputBox.tagName === 'SPAN') { inputBox.textContent = finalAnswer; } else { inputBox.value = finalAnswer; } ['click', 'focus', 'input', 'change', 'blur'].forEach(evt => inputBox.dispatchEvent(createEvent(evt)) ); filled = true; await sleep(200); currentIndex++; } catch (error) { console.log(`填写第${currentIndex + 1}题出错:`, error); } } } if (dataInputs.length > 0) { for (let i = 0; i < dataInputs.length; i++) { try { const input = dataInputs[i]; let answer = input.getAttribute('data-solution'); if (!answer) { const parentDiv = input.closest('div'); if (parentDiv) { const resultDiv = parentDiv.querySelector('div[data-itemtype="result"]'); if (resultDiv) { answer = resultDiv.textContent.trim(); } } } if (!answer) continue; let finalAnswer; if (totalInputs > 5 && wrongIndices.has(currentIndex)) { finalAnswer = answer + String.fromCharCode(65 + Math.floor(Math.random() * 26)); console.log(`准备填写第${currentIndex + 1}题错误答案:`, finalAnswer); } else { finalAnswer = answer; console.log(`准备填写第${currentIndex + 1}题正确答案:`, finalAnswer); } if (input.tagName === 'INPUT') { input.value = finalAnswer; } else { input.textContent = finalAnswer; } ['click', 'focus', 'input', 'change', 'blur'].forEach(evt => input.dispatchEvent(createEvent(evt)) ); filled = true; await sleep(200); currentIndex++; } catch (error) { console.log(`处理data-solution题目出错:`, error); } } } if (textareaInputs.length > 0) { for (let i = 0; i < textareaInputs.length; i++) { try { const textarea = textareaInputs[i]; let answer = textarea.getAttribute('data-solution'); if (!answer) { const parentDiv = textarea.closest('div'); if (parentDiv) { const resultDiv = parentDiv.querySelector('div[data-itemtype="result"]'); if (resultDiv) { answer = resultDiv.textContent.trim(); } } } if (!answer) continue; let finalAnswer; if (totalInputs > 5 && wrongIndices.has(currentIndex)) { finalAnswer = answer + String.fromCharCode(65 + Math.floor(Math.random() * 26)); console.log(`准备填写第${currentIndex + 1}题错误答案:`, finalAnswer); } else { finalAnswer = answer; console.log(`准备填写第${currentIndex + 1}题正确答案:`, finalAnswer); } textarea.value = finalAnswer; ['click', 'focus', 'input', 'change', 'blur'].forEach(evt => textarea.dispatchEvent(createEvent(evt)) ); if (textarea.style.height) { const computedStyle = window.getComputedStyle(textarea); const height = computedStyle.height; textarea.style.height = height; } filled = true; await sleep(200); currentIndex++; } catch (error) { console.log(`处理textarea题目出错:`, error); } } } if (editableSpans.length > 0) { for (let i = 0; i < editableSpans.length; i++) { try { const span = editableSpans[i]; const answerSpan = span.nextElementSibling?.querySelector('span.key[ng-if="blank.hasKey"]') || span.parentElement?.querySelector('span.key[ng-if="blank.hasKey"]'); if (!answerSpan) continue; let answer = answerSpan.textContent.trim(); if (!answer) continue; let finalAnswer; if (totalInputs > 5 && wrongIndices.has(currentIndex)) { finalAnswer = answer + String.fromCharCode(65 + Math.floor(Math.random() * 26)); console.log(`准备填写第${currentIndex + 1}题错误答案:`, finalAnswer); } else { finalAnswer = answer; console.log(`准备填写第${currentIndex + 1}题正确答案:`, finalAnswer); } span.textContent = finalAnswer; ['click', 'focus', 'input', 'change', 'blur'].forEach(evt => span.dispatchEvent(createEvent(evt)) ); if (typeof angular !== 'undefined') { try { const scope = angular.element(span).scope(); if (scope && scope.blank) { scope.blank.value = finalAnswer; scope.$apply(); } } catch (e) { console.log('Angular数据绑定更新失败:', e); } } filled = true; await sleep(200); currentIndex++; } catch (error) { console.log(`处理contenteditable span题目出错:`, error); } } } await sleep(500); console.log('开始对每个填空框进行点击操作'); const allInputs = [...inputBoxes, ...dataInputs, ...textareaInputs, ...editableSpans]; allInputs.forEach((inputBox, index) => { try { if (!document.body.contains(inputBox)) return; console.log(`对第${index + 1}个填空框进行点击操作`); inputBox.dispatchEvent(createEvent('click')); inputBox.dispatchEvent(createEvent('focus')); setTimeout(() => { inputBox.dispatchEvent(createEvent('blur')); }, 50); } catch (error) { console.log(`额外点击第${index + 1}个填空框出错:`, error); } }); console.log('填空题处理完成'); return filled; } function isElementInViewport(el) { const rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } async function handleUnitTestAnswers() { console.log('开始处理单元测试题目'); let answered = false; try { const resultSpans = document.querySelectorAll('span.unittestresult'); if (resultSpans.length > 0) { console.log('找到单元测试题目数量:', resultSpans.length); const totalQuestions = resultSpans.length; const correctCount = Math.ceil((totalQuestions * window.defaultAccuracyRate) / 100); const wrongCount = totalQuestions - correctCount; console.log(`总题目: ${totalQuestions}, 正确数: ${correctCount}, 错误数: ${wrongCount}`); const wrongIndices = new Set(); while (wrongIndices.size < wrongCount) { const randomIndex = Math.floor(Math.random() * totalQuestions); wrongIndices.add(randomIndex); } let currentIndex = 0; for (const span of resultSpans) { try { const resultDiv = span.querySelector('div[data-itemtype="result"]'); if (!resultDiv) continue; const answer = resultDiv.textContent.trim(); console.log('找到答案:', answer); const questionText = span.closest('div[data-controltype="filling"]')?.querySelector('span[data-itemtype="sn"]')?.textContent.trim(); if (!questionText) continue; const answerSheets = document.querySelectorAll('div.AnswerSheet'); for (const sheet of answerSheets) { const sheetTitle = sheet.querySelector('h6.unit_test_answersheet_tit')?.textContent.trim(); if (sheetTitle && sheetTitle.includes(questionText)) { const options = Array.from(sheet.querySelectorAll('ul.AnswerSheet_chooseBox li h5')); if (wrongIndices.has(currentIndex)) { const wrongOptions = options.filter(opt => opt.textContent.trim() !== answer); if (wrongOptions.length > 0) { const randomWrongOption = wrongOptions[Math.floor(Math.random() * wrongOptions.length)]; randomWrongOption.click(); console.log(`第${currentIndex + 1}题选择错误答案: ${randomWrongOption.textContent.trim()}`); } else { const correctOption = options.find(opt => opt.textContent.trim() === answer); if (correctOption) { correctOption.click(); console.log(`第${currentIndex + 1}题未找到错误选项,选择正确答案: ${answer}`); } } } else { const correctOption = options.find(opt => opt.textContent.trim() === answer); if (correctOption) { correctOption.click(); console.log(`第${currentIndex + 1}题选择正确答案: ${answer}`); } } answered = true; await sleep(300); break; } } currentIndex++; } catch (error) { console.log('处理单个题目时出错:', error); } } } } catch (error) { console.log('处理单元测试题目出错:', error); } return answered; } async function autoSelectCorrectAnswers() { console.log('开始自动选择答案'); let allQuestions = []; let answered = false; const choiceQuestions = document.querySelectorAll('et-choice[et-index]'); const tfQuestions = document.querySelectorAll('et-tof[et-index]'); const newChoiceQuestions = document.querySelectorAll('div[data-controltype="choice"]'); allQuestions = [...choiceQuestions, ...tfQuestions, ...newChoiceQuestions]; const totalQuestions = allQuestions.length; console.log('找到选择/判断题数量:', totalQuestions); if (totalQuestions <= 5) { for (const question of allQuestions) { await handleQuestion(question, true); } } else { const correctCount = Math.ceil((totalQuestions * window.defaultAccuracyRate) / 100); const wrongCount = totalQuestions - correctCount; console.log(`总题目: ${totalQuestions}, 正确数: ${correctCount}, 错误数: ${wrongCount}`); const wrongIndices = new Set(); while (wrongIndices.size < wrongCount) { const randomIndex = Math.floor(Math.random() * totalQuestions); wrongIndices.add(randomIndex); } for (let i = 0; i < allQuestions.length; i++) { const question = allQuestions[i]; const shouldBeCorrect = !wrongIndices.has(i); await handleQuestion(question, shouldBeCorrect); await sleep(300); } } console.log('选择/判断题处理完成'); } async function handleQuestion(question, shouldBeCorrect) { const questionType = question.tagName.toLowerCase() === 'et-tof' ? 'tof' : question.hasAttribute('data-controltype') ? 'new-choice' : 'choice'; let options = []; if (questionType === 'tof') { options = question.querySelectorAll('span[ng-class*="chosen:tof.value"], div.wrapper span'); } else if (questionType === 'new-choice') { const optionsList = question.querySelector('ul[data-itemtype="options"]'); if (optionsList) { options = Array.from(optionsList.querySelectorAll('li')); const correctOption = optionsList.querySelector('li[data-solution]'); if (correctOption && shouldBeCorrect) { try { correctOption.click(); console.log('找到并选择了正确答案:', correctOption.textContent.trim()); await sleep(300); return; } catch (error) { console.log('点击正确选项出错:', error); } } else if (!shouldBeCorrect && options.length > 0) { const wrongOptions = Array.from(options).filter(opt => opt !== correctOption); if (wrongOptions.length > 0) { const randomWrongOption = wrongOptions[Math.floor(Math.random() * wrongOptions.length)]; try { randomWrongOption.click(); console.log('已选择错误答案:', randomWrongOption.textContent.trim()); await sleep(300); return; } catch (error) { console.log('选择错误答案时出错:', error); } } } } } else { options = question.querySelectorAll('ol > li, div.wrapper li, span[ng-click*="choice.select"], li[class]'); } if (options.length === 0) { console.log('未找到选项,跳过'); return; } if (shouldBeCorrect) { for (const option of options) { try { option.click(); await sleep(300); const wrapper = questionType === 'tof' ? option.closest('div[ng-class*="isKeyVisible"]') : option.closest('div.wrapper'); if (wrapper?.classList.contains('correct')) { console.log('找到并选择了正确答案:', option.textContent.trim()); break; } } catch (error) { console.log('点击选项出错:', error); } } } else { let correctOption = null; for (const option of options) { try { option.click(); await sleep(300); const wrapper = questionType === 'tof' ? option.closest('div[ng-class*="isKeyVisible"]') : option.closest('div.wrapper'); if (wrapper?.classList.contains('correct')) { correctOption = option; break; } } catch (error) { console.log('查找正确答案时出错:', error); } } if (correctOption) { const wrongOptions = Array.from(options).filter(opt => opt !== correctOption); if (wrongOptions.length > 0) { const randomWrongOption = wrongOptions[Math.floor(Math.random() * wrongOptions.length)]; try { randomWrongOption.click(); console.log('已选择错误答案:', randomWrongOption.textContent.trim()); } catch (error) { console.log('选择错误答案时出错:', error); } } } } await sleep(300); } function autoSelectDropdownAnswers() { console.log('开始处理下拉框选择题'); const dropdowns = document.querySelectorAll('select[ng-model]'); console.log('找到下拉框数量:', dropdowns.length); if (dropdowns.length === 0) return; dropdowns.forEach((dropdown, index) => { try { const correctOption = dropdown.querySelector('option.key'); if (!correctOption) return; dropdown.value = correctOption.value; dropdown.dispatchEvent(createEvent('change')); console.log(`已选择第${index + 1}个下拉框答案:`, correctOption.textContent.trim()); } catch (error) { console.log(`处理第${index + 1}个下拉框出错:`, error); } }); } async function autoMatchLines() { console.log('开始处理连线题'); const matchingElements = document.querySelectorAll('et-matching[et-index]'); if (matchingElements.length === 0) return; console.log(`找到连线题数量: ${matchingElements.length}`); for (const matchingElement of matchingElements) { const matchingKey = matchingElement.getAttribute('key'); if (!matchingKey) continue; console.log(`处理连线题,答案key: ${matchingKey}`); try { const pairs = matchingKey.split(',').map(pair => { const [left, right] = pair.split('-'); return { leftIndex: parseInt(left) - 1, rightIndex: parseInt(right) - 1 }; }); let angularSuccess = false; if (typeof angular !== 'undefined') { try { const scope = angular.element(matchingElement).scope(); if (scope?.matching) { if (Array.isArray(scope.matching.lines)) { scope.matching.lines = []; } for (const {leftIndex, rightIndex} of pairs) { const leftCircle = scope.matching.circles?.A?.[leftIndex]; const rightCircle = scope.matching.circles?.B?.[rightIndex]; if (!leftCircle || !rightCircle) continue; if (typeof leftCircle.select === 'function') { leftCircle.select(); await sleep(200); rightCircle.select?.(); } else if (typeof scope.matching.connect === 'function') { scope.matching.connect(leftCircle, rightCircle); } else if (Array.isArray(scope.matching.lines)) { scope.matching.lines.push({ x1: leftCircle.x, y1: leftCircle.y, x2: rightCircle.x, y2: rightCircle.y, circleA: leftCircle, circleB: rightCircle }); } await sleep(200); } scope.$apply?.(); await sleep(500); if (Array.isArray(scope.matching.lines) && scope.matching.lines.length > 0) { angularSuccess = true; } } } catch (e) { console.error('Angular模型操作失败:', e); } } if (angularSuccess) continue; console.log('尝试DOM操作方式'); let leftCircles = []; let rightCircles = []; leftCircles = Array.from(matchingElement.querySelectorAll('circle[data-circle="A"]')); rightCircles = Array.from(matchingElement.querySelectorAll('circle[data-circle="B"]')); if (leftCircles.length === 0 || rightCircles.length === 0) { const allCircles = matchingElement.querySelectorAll('circle[ng-repeat]'); leftCircles = []; rightCircles = []; for (const circle of allCircles) { const ngRepeat = circle.getAttribute('ng-repeat'); if (ngRepeat?.includes('matching.circles.A')) { leftCircles.push(circle); } else if (ngRepeat?.includes('matching.circles.B')) { rightCircles.push(circle); } } } if (leftCircles.length === 0 || rightCircles.length === 0) { const allCircles = matchingElement.querySelectorAll('circle'); if (allCircles.length > 1) { const circlesWithCoords = Array.from(allCircles) .map(circle => ({ element: circle, x: parseFloat(circle.getAttribute('cx')), y: parseFloat(circle.getAttribute('cy')) })) .filter(c => !isNaN(c.x) && !isNaN(c.y)); if (circlesWithCoords.length > 1) { circlesWithCoords.sort((a, b) => a.x - b.x); const midX = (circlesWithCoords[0].x + circlesWithCoords[circlesWithCoords.length - 1].x) / 2; leftCircles = circlesWithCoords.filter(c => c.x < midX).map(c => c.element); rightCircles = circlesWithCoords.filter(c => c.x >= midX).map(c => c.element); } } } if (leftCircles.length === 0 || rightCircles.length === 0) continue; for (const {leftIndex, rightIndex} of pairs) { if (leftIndex < 0 || leftIndex >= leftCircles.length || rightIndex < 0 || rightIndex >= rightCircles.length) continue; const leftCircle = leftCircles[leftIndex]; const rightCircle = rightCircles[rightIndex]; const leftX = parseFloat(leftCircle.getAttribute('cx')); const leftY = parseFloat(leftCircle.getAttribute('cy')); const rightX = parseFloat(rightCircle.getAttribute('cx')); const rightY = parseFloat(rightCircle.getAttribute('cy')); try { const createMouseEvent = (type, x, y) => new MouseEvent(type, { bubbles: true, cancelable: true, view: window, clientX: x, clientY: y }); ['mousedown', 'click'].forEach(type => leftCircle.dispatchEvent(createMouseEvent(type, leftX, leftY))); await sleep(300); ['mousedown', 'click'].forEach(type => rightCircle.dispatchEvent(createMouseEvent(type, rightX, rightY))); await sleep(300); if (typeof angular !== 'undefined') { const scope = angular.element(leftCircle).scope(); scope?.$apply?.(); if (element.tagName === 'circle' && element.hasAttribute('data-index')) { const dataIndex = element.getAttribute('data-index'); const dataCircle = element.getAttribute('data-circle'); const matchingElement = element.closest('et-matching[et-index]'); if (matchingElement && dataCircle) { const matchingScope = angular.element(matchingElement).scope(); const circles = matchingScope?.matching?.circles?.[dataCircle]; const circle = circles?.[dataIndex]; if (circle?.select) { circle.select(); matchingScope.$apply?.(); } } } } } catch (e) { console.error('点击圆圈出错:', e); } } } catch (error) { console.error(`处理连线题出错:`, error); } await new Promise(resolve => setTimeout(resolve, 1000)); } console.log('所有连线题处理完成'); } function isElementVisible(element) { if (!element) return false; try { const style = window.getComputedStyle(element); return style.display !== 'none' && style.visibility !== 'hidden' && element.offsetParent !== null; } catch (e) { return true; } } async function clickElement(element) { if (!element) return; try { element.click(); await sleep(100); const cx = parseFloat(element.getAttribute('cx')) || 0; const cy = parseFloat(element.getAttribute('cy')) || 0; const mouseEventOptions = { view: window, bubbles: true, cancelable: true, clientX: cx, clientY: cy }; ['mousedown', 'mouseup', 'click'].forEach(type => element.dispatchEvent(new MouseEvent(type, mouseEventOptions))); if (typeof angular !== 'undefined') { const scope = angular.element(element).scope(); scope?.$apply?.(); if (element.tagName === 'circle' && element.hasAttribute('data-index')) { const dataIndex = element.getAttribute('data-index'); const dataCircle = element.getAttribute('data-circle'); const matchingElement = element.closest('et-matching[et-index]'); if (matchingElement && dataCircle) { const matchingScope = angular.element(matchingElement).scope(); const circles = matchingScope?.matching?.circles?.[dataCircle]; const circle = circles?.[dataIndex]; if (circle?.select) { circle.select(); matchingScope.$apply?.(); } } } } } catch (error) { console.error('点击元素出错:', error); } } async function submitAnswers() { if (!window.autoSubmitEnabled) { console.log('自动提交已禁用,跳过提交'); return false; } console.log('准备提交答案'); let submitted = false; let maxAttempts = 3; let attemptCount = 0; await sleep(2000); while (!submitted && attemptCount < maxAttempts) { attemptCount++; console.log(`尝试提交答案 (第${attemptCount}次)`); try { let submitButton = null; submitButton = Array.from(document.querySelectorAll('button')).find(btn => (btn.textContent.trim() === 'Submit' || btn.querySelector('span')?.textContent.trim() === 'Submit') && !btn.disabled && btn.offsetParent !== null ); if (!submitButton) { const etButtons = document.querySelectorAll('et-button[right][action="item.submit()"]'); for (const etBtn of etButtons) { const btn = etBtn.querySelector('button[ng-click="btn.doAction()"]'); if (btn && !btn.disabled && btn.offsetParent !== null) { submitButton = btn; break; } } } if (!submitButton) { submitButton = document.querySelector('button[ng-click*="submit"], button[ng-click*="btn.doAction()"]'); } if (submitButton) { console.log('找到Submit按钮,尝试点击'); submitButton.scrollIntoView({ behavior: 'smooth', block: 'center' }); await sleep(500); submitButton.click(); await sleep(500); if (typeof angular !== 'undefined') { const scope = angular.element(submitButton).scope(); if (scope?.item?.submit) { scope.item.submit(); scope.$apply(); } } submitted = true; await sleep(2000); } else { console.log('未找到Submit按钮,尝试其他方式'); const submitLink = document.querySelector('a[data-controltype="submit"]'); if (submitLink) { submitLink.click(); await sleep(1000); submitted = true; } } } catch (error) { console.error(`第${attemptCount}次提交尝试失败:`, error); } if (!submitted) { await sleep(1000); } } if (submitted) { console.log('提交成功'); return true; } console.log('所有提交尝试均失败'); return false; } async function autoNextSection() { if (!window.autoNextEnabled) { console.log('自动跳转已禁用,跳过跳转'); return false; } if (window.isTransitioning) { console.log('跳转已在进行中,跳过重复跳转'); return true; } console.log('准备自动跳转到下一章节'); const isInIframe = window !== window.top; console.log(`跳转环境: ${isInIframe ? 'iframe内' : '主窗口'}`); await sleep(3000); let nextSectionAttempts = 0; const maxNextSectionAttempts = 3; let transitionStarted = false; while (nextSectionAttempts < maxNextSectionAttempts && !transitionStarted) { nextSectionAttempts++; console.log(`尝试跳转到下一章节 (第${nextSectionAttempts}次)`); try { const navLinks = document.querySelectorAll('a[href*="javascript:NextSCO()"], a[href*="javascript:PrevSCO()"]'); if (navLinks.length > 0) { const nextLink = Array.from(navLinks).find(link => link.href.includes('NextSCO') && !link.href.includes('PrevSCO') ); if (nextLink) { console.log('找到NextSCO链接,尝试点击'); nextLink.click(); await sleep(3000); transitionStarted = true; break; } } } catch (e) { console.log('点击NextSCO链接失败:', e); } if (transitionStarted) break; try { console.log('尝试直接执行NextSCO函数'); const scriptEl = document.createElement('script'); scriptEl.textContent = ` try { if (typeof NextSCO === 'function') { NextSCO(); console.log("成功执行NextSCO函数"); } } catch(e) { console.error("执行NextSCO出错:", e); } `; document.body.appendChild(scriptEl); document.body.removeChild(scriptEl); await sleep(2000); transitionStarted = true; break; } catch (e) { console.log('执行NextSCO函数失败:', e); } if (transitionStarted) break; try { window.location.href = 'javascript:void(0); try { NextSCO(); } catch(e) {}'; await sleep(2000); transitionStarted = true; break; } catch (e) { console.log('通过location.href跳转失败:', e); } if (!transitionStarted && nextSectionAttempts < maxNextSectionAttempts) { console.log('本次跳转尝试失败,等待后重试'); await sleep(2000); } } if (transitionStarted) { console.log('已成功触发跳转,等待新页面加载'); window.isTransitioning = false; return true; } console.log('所有跳转尝试都失败'); window.isTransitioning = false; return false; } async function ensureCorrectContext() { const isInIframe = window !== window.top; console.log(`当前环境: ${isInIframe ? 'iframe内' : '主窗口'}`); if (isInIframe && window.name === 'contentFrame') { console.log('已在答题的iframe中,可以直接答题'); return; } if (!isInIframe) { console.log('在主窗口中,尝试切换到contentFrame'); let contentFrame = document.getElementById('contentFrame'); if (!contentFrame) { const frames = document.getElementsByTagName('iframe'); for (let i = 0; i < frames.length; i++) { if (frames[i].name === 'contentFrame') { contentFrame = frames[i]; break; } } } if (contentFrame) { console.log('找到contentFrame,准备在其中执行答题'); try { return executeInContentFrame(contentFrame); } catch (e) { console.error('向contentFrame执行答题失败:', e); } } else { const iframes = document.querySelectorAll('iframe'); console.log(`共找到${iframes.length}个iframe`); for (let i = 0; i < iframes.length; i++) { try { const iframe = iframes[i]; if (!iframe.contentDocument) continue; const hasQuizElements = iframe.contentDocument.querySelector('et-choice') || iframe.contentDocument.querySelector('et-tof') || iframe.contentDocument.querySelector('span.key') || iframe.contentDocument.querySelector('div.key') || iframe.contentDocument.querySelector('select[ng-model]') || iframe.contentDocument.querySelector('button'); if (hasQuizElements) { console.log(`找到可能的答题iframe: ${iframe.name || iframe.id || i}`); return executeInContentFrame(iframe); } } catch (e) { console.log(`检查iframe ${i}失败:`, e); } } console.log('未找到答题iframe,直接在当前窗口执行'); } } } function executeInContentFrame(frame) { console.log('准备在iframe中执行答题'); try { const scriptContent = ` if (!window.weLearnHelperInjected) { window.weLearnHelperInjected = true; window.defaultAccuracyRate = ${window.defaultAccuracyRate}; window.isAutoLoopActive = ${window.isAutoLoopActive}; window.autoLoopTimeout = null; window.waitTimerActive = ${window.waitTimerActive}; window.waitTimerInterval = null; window.defaultWaitTime = ${window.defaultWaitTime}; window.autoNextEnabled = ${window.autoNextEnabled}; window.autoSubmitEnabled = ${window.autoSubmitEnabled}; window.parent.postMessage({ action: 'iframeReady', frameId: '${frame.id || frame.name || 'unknown'}' }, '*'); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); const createEvent = (type, options = {}) => new Event(type, {bubbles: true, cancelable: true, ...options}); ${autoFillAnswers.toString()} ${autoSelectCorrectAnswers.toString()} ${autoSelectDropdownAnswers.toString()} ${autoMatchLines.toString()} ${submitAnswers.toString()} ${handleQuestion.toString()} ${handlePickerQuestions.toString()} window.addEventListener('message', async function(event) { if (event.data && event.data.action === 'runQuizFunctions') { console.log('iframe收到执行答题请求:', event.data.step); const executeAsync = async () => { try { const questionCount = document.querySelectorAll('et-choice[et-index], et-tof[et-index], span[autocapitalize="none"], textarea.blank, span.key, div.key, select[ng-model], et-matching[et-index], span.blank[ng-attr-tabindex]').length; console.log('找到题目数量:', questionCount); const baseDelay = 200; const additionalDelayPerQuestion = 100; const operationDelay = baseDelay + Math.floor(questionCount / 5) * additionalDelayPerQuestion; console.log(\`设置操作延迟: \${operationDelay}ms\`); if (event.data.step === 'selectAnswers') { await autoSelectCorrectAnswers(); await sleep(operationDelay); window.parent.postMessage({ action: 'stepComplete', step: 'selectAnswers' }, '*'); } else if (event.data.step === 'fillAnswers') { await autoFillAnswers(); await sleep(operationDelay); window.parent.postMessage({ action: 'stepComplete', step: 'fillAnswers' }, '*'); } else if (event.data.step === 'selectDropdowns') { await autoSelectDropdownAnswers(); await sleep(operationDelay); window.parent.postMessage({ action: 'stepComplete', step: 'selectDropdowns' }, '*'); } else if (event.data.step === 'matchLines') { await autoMatchLines(); await sleep(operationDelay); window.parent.postMessage({ action: 'stepComplete', step: 'matchLines' }, '*'); } else if (event.data.step === 'submitAnswers') { await submitAnswers(); await sleep(operationDelay); window.parent.postMessage({ action: 'stepComplete', step: 'submitAnswers' }, '*'); } else if (event.data.step === 'pickerQuestions') { await handlePickerQuestions(); await sleep(operationDelay); window.parent.postMessage({ action: 'stepComplete', step: 'pickerQuestions' }, '*'); } else if (event.data.step === 'all') { console.log('执行所有答题步骤'); await autoSelectCorrectAnswers(); await sleep(operationDelay); await autoFillAnswers(); await sleep(operationDelay); await autoSelectDropdownAnswers(); await sleep(operationDelay); await autoMatchLines(); await sleep(operationDelay); await handlePickerQuestions(); await sleep(operationDelay); if (window.autoSubmitEnabled) { await submitAnswers(); await sleep(operationDelay); } window.parent.postMessage({ action: 'stepComplete', step: 'all' }, '*'); } } catch (error) { console.error('执行iframe中的答题函数出错:', error); window.parent.postMessage({ action: 'stepError', error: error.message, step: event.data.step }, '*'); } }; executeAsync(); } }); } `; const script = document.createElement('script'); script.textContent = scriptContent; try { frame.contentDocument.body.appendChild(script); frame.contentDocument.body.removeChild(script); console.log('已将答题脚本注入到iframe中'); } catch (e) { console.error('注入脚本到iframe失败:', e); return null; } return { autoSelectCorrectAnswers: () => sendCommandToIframe(frame, 'selectAnswers'), autoFillAnswers: () => sendCommandToIframe(frame, 'fillAnswers'), autoSelectDropdownAnswers: () => sendCommandToIframe(frame, 'selectDropdowns'), autoMatchLines: () => sendCommandToIframe(frame, 'matchLines'), submitAnswers: () => sendCommandToIframe(frame, 'submitAnswers'), handlePickerQuestions: () => sendCommandToIframe(frame, 'pickerQuestions') }; } catch (e) { console.error('iframe操作失败:', e); return null; } } function handleIframeMessage(event) { if (event.data && event.data.action) { if (event.data.action === 'iframeReady') { console.log(`iframe已就绪: ${event.data.frameId}`); } else if (event.data.action === 'stepComplete') { console.log(`iframe完成步骤: ${event.data.step}`); } else if (event.data.action === 'stepError') { console.error(`iframe执行出错: ${event.data.error}`); } } } async function sendCommandToIframe(frame, step) { return new Promise((resolve, reject) => { let timeout; try { const frameDoc = frame.contentDocument || frame.contentWindow.document; const questionCount = frameDoc.querySelectorAll('et-choice[et-index], et-tof[et-index], span[autocapitalize="none"], textarea.blank, span.key, div.key, select[ng-model], et-matching[et-index]').length; const baseTimeout = 30000; const additionalTimePerTenQuestions = 30000; timeout = baseTimeout + Math.ceil(questionCount / 10) * additionalTimePerTenQuestions; console.log(`题目数量: ${questionCount}, 设置超时时间: ${timeout/1000}秒`); } catch (e) { console.log('计算题目数量失败,使用默认超时时间60秒'); timeout = 60000; } let timeoutHandle; let isCompleted = false; const messageHandler = (event) => { if (!event.data) return; if (event.data.action === 'stepComplete' && event.data.step === step) { isCompleted = true; cleanup(); resolve(); } else if (event.data.action === 'stepError' && event.data.step === step) { cleanup(); reject(new Error(event.data.error || '未知iframe错误')); } }; const cleanup = () => { if (timeoutHandle) { clearTimeout(timeoutHandle); timeoutHandle = null; } window.removeEventListener('message', messageHandler); }; timeoutHandle = setTimeout(() => { if (!isCompleted) { cleanup(); reject(new Error(`向iframe发送${step}命令超时 (${timeout/1000}秒)`)); } }, timeout); window.addEventListener('message', messageHandler); try { frame.contentWindow.postMessage({ action: 'runQuizFunctions', step: step }, '*'); console.log(`已向iframe发送${step}命令`); } catch (e) { cleanup(); reject(e); } }); } function createIntegratedUI() { const globalStyle = document.createElement('style'); globalStyle.id = 'welearn-helper-style'; globalStyle.textContent = ` @keyframes slideIn { from { transform: translateX(-120%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.03); opacity: 0.8; } 100% { transform: scale(1); opacity: 1; } } @keyframes subtlePopIn { 0% { opacity: 0; transform: scale(0.95) translateY(5px); } 100% { opacity: 1; transform: scale(1) translateY(0); } } @keyframes shine { 0% { background-position: -150% 50%; } 100% { background-position: 250% 50%; } } @keyframes gradientFlow { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes titleGlow { 0% { text-shadow: 0 0 5px rgba(76, 175, 80, 0.5); } 50% { text-shadow: 0 0 15px rgba(76, 175, 80, 0.8), 0 0 25px rgba(76, 175, 80, 0.4); } 100% { text-shadow: 0 0 5px rgba(76, 175, 80, 0.5); } } @keyframes borderPulse { 0% { border-color: rgba(255, 255, 255, 0.15); } 50% { border-color: rgba(76, 175, 80, 0.3); } 100% { border-color: rgba(255, 255, 255, 0.15); } } #welearnHelperPanel { position: fixed; top: 15px; left: 15px; z-index: 10000; background: rgba(28, 32, 34, 0.75); backdrop-filter: blur(10px) saturate(180%); -webkit-backdrop-filter: blur(10px) saturate(180%); border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35), 0 2px 8px rgba(76, 175, 80, 0.15), inset 0 0 0 0.5px rgba(255, 255, 255, 0.15); padding: 18px; color: #e0e0e0; font-size: 14px; width: 290px; display: flex; flex-direction: column; gap: 14px; border: 1px solid rgba(255, 255, 255, 0.12); animation: slideIn 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; } #welearnHelperPanel:hover { transform: translateY(-3px) scale(1.01); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(76, 175, 80, 0.2), inset 0 0 0 0.5px rgba(255, 255, 255, 0.2); } .welearn-title-bar { display: flex; justify-content: space-between; align-items: center; background: linear-gradient(135deg, rgba(76, 175, 80, 0.15), rgba(56, 142, 60, 0.1), rgba(76, 175, 80, 0.15)); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); background-size: 200% 200%; animation: gradientFlow 8s ease infinite; margin: -18px -18px 6px -18px; padding: 16px 18px; border-bottom: 1px solid rgba(255, 255, 255, 0.15); border-radius: 12px 12px 0 0; position: relative; overflow: hidden; } .welearn-title-bar::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transform: translateX(-100%); animation: shine 8s infinite; } .welearn-title-bar::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 1px; background: linear-gradient(90deg, transparent, rgba(76, 175, 80, 0.5), transparent); animation: borderPulse 4s infinite; } .welearn-title { font-weight: 600; font-size: 20px; background: linear-gradient(135deg, #ffffff 30%, #4CAF50); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); animation: titleGlow 3s ease-in-out infinite; letter-spacing: 0.5px; position: relative; padding-left: 24px; } .welearn-title::before { content: '🎯'; position: absolute; left: 0; top: 50%; transform: translateY(-50%); font-size: 16px; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)); animation: pulse 2s ease-in-out infinite; } .welearn-minimize-btn { background: rgba(255, 255, 255, 0.1); border: none; color: #c0c0c0; font-size: 18px; font-weight: bold; cursor: pointer; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); backdrop-filter: blur(4px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } .welearn-minimize-btn:hover { background-color: rgba(76, 175, 80, 0.25); color: #ffffff; transform: rotate(180deg) scale(1.1); box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); } .welearn-minimize-btn.minimized:hover { transform: rotate(-180deg) scale(1.1); } .welearn-minimize-btn::before { content: ''; position: absolute; width: 100%; height: 100%; border-radius: 50%; background: radial-gradient(circle at center, rgba(255, 255, 255, 0.1) 0%, transparent 70%); opacity: 0; transition: opacity 0.3s ease; } .welearn-minimize-btn:hover::before { opacity: 1; } .welearn-button-container { display: flex; gap: 10px; animation: fadeIn 0.5s ease-out 0.2s both; } .welearn-button { position: relative; flex: 1; padding: 10px 14px; border: none; border-radius: 8px; cursor: pointer; font-weight: 500; font-size: 13.5px; transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); color: white; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.2); } .welearn-button::before { content: ''; position: absolute; top: 0; left: -100%; width: 200%; height: 100%; background: linear-gradient( 90deg, transparent, rgba(255, 255, 255, 0.15), transparent ); transition: 0.5s; } .welearn-button:hover::before { animation: shine 1.2s infinite linear; } .welearn-button:hover { transform: translateY(-2.5px); box-shadow: 0 5px 15px rgba(0,0,0,0.2), inset 0 0 0 0.5px rgba(255, 255, 255, 0.3); } .welearn-button:active { transform: scale(0.96) translateY(-1px); box-shadow: 0 2px 8px rgba(0,0,0,0.15); } .welearn-auto-button { background: linear-gradient(135deg, rgba(38, 166, 154, 0.95) 0%, rgba(0, 121, 107, 0.95) 100%); } .welearn-auto-button:hover { background: linear-gradient(135deg, rgba(42, 183, 169, 0.95) 0%, rgba(0, 137, 123, 0.95) 100%); box-shadow: 0 5px 18px rgba(38, 166, 154, 0.35), inset 0 0 0 0.5px rgba(255, 255, 255, 0.3); } .welearn-loop-button { background: linear-gradient(135deg, rgba(92, 107, 192, 0.95) 0%, rgba(57, 73, 171, 0.95) 100%); } .welearn-loop-button:hover { background: linear-gradient(135deg, rgba(111, 125, 214, 0.95) 0%, rgba(71, 88, 184, 0.95) 100%); box-shadow: 0 5px 18px rgba(92, 107, 192, 0.35), inset 0 0 0 0.5px rgba(255, 255, 255, 0.3); } .welearn-loop-active { background: linear-gradient(135deg, #ef5350 0%, #d32f2f 100%); animation: pulse 1.8s infinite ease-in-out; } .welearn-loop-active:hover { background: linear-gradient(135deg, #fa6e6b 0%, #e53935 100%); box-shadow: 0 5px 18px rgba(239, 83, 80, 0.45); } .welearn-timer-container, .welearn-accuracy-container { background: rgba(255, 255, 255, 0.08); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); padding: 10px; border-radius: 8px; display: flex; align-items: center; gap: 8px; animation: fadeIn 0.5s ease-out 0.3s both; border: 1px solid rgba(255, 255, 255, 0.1); transition: all 0.3s ease; box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.05); } .welearn-timer-container:hover, .welearn-accuracy-container:hover { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.2); box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.1); } .welearn-accuracy-container { animation-delay: 0.2s; } .welearn-time-input, .welearn-accuracy-input { width: 45px; padding: 7px; border-radius: 6px; border: 1px solid rgba(255, 255, 255, 0.2); background-color: rgba(0, 0, 0, 0.2); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); text-align: center; font-weight: 500; color: #e0e0e0; transition: all 0.25s ease; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .welearn-time-input:hover, .welearn-accuracy-input:hover { transform: scale(1.05); border-color: rgba(255, 255, 255, 0.3); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); } .welearn-time-input:focus, .welearn-accuracy-input:focus { outline: none; border-color: #26a69a; background-color: rgba(0, 0, 0, 0.3); box-shadow: 0 0 10px rgba(38, 166, 154, 0.5), inset 0 1px 3px rgba(0, 0, 0, 0.2); transform: scale(1.08); } .welearn-countdown { margin-left: auto; font-weight: 500; min-width: 65px; text-align: right; color: #80cbc4; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); transition: color 0.3s ease, transform 0.3s ease; } .welearn-countdown.status-update { animation: subtlePopIn 0.4s ease-out; } .welearn-status { font-size: 11.5px; color: #9e9e9e; text-align: center; padding: 7px; background-color: rgba(0, 0, 0, 0.15); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); border-radius: 6px; animation: fadeIn 0.5s ease-out 0.4s both; border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.05); } .welearn-loop-status { display: flex; align-items: center; justify-content: center; gap: 6px; background-color: rgba(239, 83, 80, 0.15); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); padding: 7px; border-radius: 6px; margin-top: 2px; font-weight: 500; font-size: 12.5px; border: 1px solid rgba(239, 83, 80, 0.25); color: #f5c8c7; animation: fadeIn 0.5s ease-out; box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.1); } @media (max-width: 768px) { #welearnHelperPanel { width: calc(100% - 30px); left: 15px; top: 15px; } } `; document.head.appendChild(globalStyle); const mainPanel = document.createElement('div'); mainPanel.id = 'welearnHelperPanel'; const titleBar = document.createElement('div'); titleBar.className = 'welearn-title-bar'; const title = document.createElement('div'); title.className = 'welearn-title'; title.textContent = 'Welearn助手'; const themeButton = document.createElement('button'); themeButton.className = 'welearn-theme-button'; themeButton.innerHTML = '🎨'; themeButton.style.cssText = ` background: none; border: none; color: ${currentTheme?.textColor || '#e0e0e0'}; font-size: 18px; cursor: pointer; padding: 0; display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; transition: all 0.3s ease; margin-right: 10px; `; themeButton.addEventListener('mouseover', () => { themeButton.style.transform = 'rotate(180deg) scale(1.1)'; }); themeButton.addEventListener('mouseout', () => { themeButton.style.transform = 'none'; }); themeButton.addEventListener('click', () => { let themePanel = document.getElementById('welearnThemePanel'); if (!themePanel) { themePanel = createThemePanel(); document.body.appendChild(themePanel); } themePanel.style.display = themePanel.style.display === 'none' ? 'block' : 'none'; }); const minimizeBtn = document.createElement('button'); minimizeBtn.className = 'welearn-minimize-btn'; minimizeBtn.textContent = '-'; minimizeBtn.onclick = () => { const content = document.getElementById('welearnHelperContent'); const payBtn = document.querySelector('.welearn-pay-btn'); if (content.style.display === 'none') { content.style.display = 'flex'; if (payBtn) payBtn.style.display = 'block'; minimizeBtn.textContent = '-'; } else { content.style.display = 'none'; if (payBtn) payBtn.style.display = 'none'; minimizeBtn.textContent = '+'; } }; titleBar.appendChild(title); titleBar.appendChild(themeButton); titleBar.appendChild(minimizeBtn); mainPanel.appendChild(titleBar); const content = document.createElement('div'); content.id = 'welearnHelperContent'; content.style.cssText = 'display: flex; flex-direction: column; gap: 12px;'; const accuracyContainer = document.createElement('div'); accuracyContainer.className = 'welearn-accuracy-container'; const accuracyLabel = document.createElement('span'); accuracyLabel.textContent = '正确率:'; accuracyLabel.style.fontWeight = '500'; const accuracyInput = document.createElement('input'); accuracyInput.id = 'accuracyInput'; accuracyInput.className = 'welearn-accuracy-input'; accuracyInput.type = 'number'; accuracyInput.min = '0'; accuracyInput.max = '100'; accuracyInput.value = defaultAccuracyRate.toString(); const percentLabel = document.createElement('span'); percentLabel.textContent = '%'; percentLabel.style.fontWeight = '500'; accuracyInput.addEventListener('change', function() { const newRate = parseInt(this.value, 10); if (!isNaN(newRate) && newRate >= 0 && newRate <= 100) { defaultAccuracyRate = newRate; } else { this.value = defaultAccuracyRate.toString(); } }); accuracyContainer.appendChild(accuracyLabel); accuracyContainer.appendChild(accuracyInput); accuracyContainer.appendChild(percentLabel); content.appendChild(accuracyContainer); const autoNextContainer = document.createElement('div'); autoNextContainer.className = 'welearn-accuracy-container'; autoNextContainer.style.justifyContent = 'space-between'; const autoNextLabel = document.createElement('span'); autoNextLabel.textContent = '自动跳转下一章:'; autoNextLabel.style.fontWeight = '500'; const autoNextCheckbox = document.createElement('input'); autoNextCheckbox.type = 'checkbox'; autoNextCheckbox.id = 'autoNextCheckbox'; autoNextCheckbox.className = 'welearn-checkbox'; autoNextCheckbox.checked = window.autoNextEnabled; autoNextCheckbox.style.cssText = ` width: 18px; height: 18px; cursor: pointer; accent-color: #4CAF50; transition: all 0.3s ease; `; const style = document.createElement('style'); style.textContent = ` .welearn-checkbox:hover { transform: scale(1.1); box-shadow: 0 0 5px rgba(76, 175, 80, 0.5); } .welearn-checkbox:checked { animation: checkmark 0.2s ease-in-out; } @keyframes checkmark { 0% { transform: scale(1); } 50% { transform: scale(0.9); } 100% { transform: scale(1); } } `; document.head.appendChild(style); autoNextCheckbox.addEventListener('change', function() { window.autoNextEnabled = this.checked; const container = this.closest('.welearn-accuracy-container'); container.style.backgroundColor = 'rgba(76, 175, 80, 0.1)'; setTimeout(() => { container.style.backgroundColor = ''; }, 300); }); autoNextContainer.appendChild(autoNextLabel); autoNextContainer.appendChild(autoNextCheckbox); content.insertBefore(autoNextContainer, accuracyContainer.nextSibling); const autoSubmitContainer = document.createElement('div'); autoSubmitContainer.className = 'welearn-accuracy-container'; autoSubmitContainer.style.justifyContent = 'space-between'; const autoSubmitLabel = document.createElement('span'); autoSubmitLabel.textContent = '自动提交答案:'; autoSubmitLabel.style.fontWeight = '500'; const autoSubmitCheckbox = document.createElement('input'); autoSubmitCheckbox.type = 'checkbox'; autoSubmitCheckbox.id = 'autoSubmitCheckbox'; autoSubmitCheckbox.className = 'welearn-checkbox'; autoSubmitCheckbox.checked = window.autoSubmitEnabled; autoSubmitCheckbox.style.cssText = ` width: 18px; height: 18px; cursor: pointer; accent-color: #4CAF50; transition: all 0.3s ease; `; autoSubmitCheckbox.addEventListener('change', function() { window.autoSubmitEnabled = this.checked; const container = this.closest('.welearn-accuracy-container'); container.style.backgroundColor = 'rgba(76, 175, 80, 0.1)'; setTimeout(() => { container.style.backgroundColor = ''; }, 300); const frames = document.getElementsByTagName('iframe'); for (const frame of frames) { try { frame.contentWindow.postMessage({ action: 'updateAutoSubmit', enabled: this.checked }, '*'); } catch (e) { console.log('向iframe发送自动提交状态更新失败:', e); } } }); autoSubmitContainer.appendChild(autoSubmitLabel); autoSubmitContainer.appendChild(autoSubmitCheckbox); content.insertBefore(autoSubmitContainer, autoNextContainer.nextSibling); const buttonContainer = document.createElement('div'); buttonContainer.className = 'welearn-button-container'; const autoAnswerButton = document.createElement('button'); autoAnswerButton.id = 'autoAnswerButton'; autoAnswerButton.textContent = '一键全自动'; autoAnswerButton.className = 'welearn-button welearn-auto-button'; const autoLoopButton = document.createElement('button'); autoLoopButton.id = 'autoLoopButton'; autoLoopButton.textContent = '开始自动挂机'; autoLoopButton.className = 'welearn-button welearn-loop-button'; autoAnswerButton.onclick = async function() { await runAutoAnswerProcess(false); }; autoLoopButton.onclick = async function() { await toggleAutoLoop(); }; buttonContainer.appendChild(autoAnswerButton); buttonContainer.appendChild(autoLoopButton); content.appendChild(buttonContainer); const timerContainer = document.createElement('div'); timerContainer.id = 'waitTimerContainer'; timerContainer.className = 'welearn-timer-container'; const label = document.createElement('span'); label.textContent = '刷时长:'; label.style.fontWeight = '500'; const timeInput = document.createElement('input'); timeInput.id = 'waitTimeInput'; timeInput.className = 'welearn-time-input'; timeInput.type = 'number'; timeInput.min = '1'; timeInput.max = '3600'; timeInput.value = defaultWaitTime.toString(); timeInput.addEventListener('change', function() { const newTime = parseInt(this.value, 10); if (!isNaN(newTime) && newTime > 0) { defaultWaitTime = newTime; const countdownDisplay = document.getElementById('countdownDisplay'); if (countdownDisplay) { const originalText = countdownDisplay.textContent; const originalColor = countdownDisplay.style.color; countdownDisplay.textContent = '已保存'; countdownDisplay.style.color = '#4CAF50'; countdownDisplay.classList.add('status-update'); setTimeout(() => { if (countdownDisplay) { countdownDisplay.textContent = originalText; countdownDisplay.style.color = originalColor; countdownDisplay.classList.remove('status-update'); } }, 1000); } } }); const secondsLabel = document.createElement('span'); secondsLabel.textContent = '秒'; secondsLabel.style.fontWeight = '500'; const statusDisplay = document.createElement('div'); statusDisplay.id = 'countdownDisplay'; statusDisplay.className = 'welearn-countdown'; statusDisplay.textContent = '未开始'; timerContainer.appendChild(label); timerContainer.appendChild(timeInput); timerContainer.appendChild(secondsLabel); timerContainer.appendChild(statusDisplay); content.appendChild(timerContainer); const statusContainer = document.createElement('div'); statusContainer.className = 'welearn-status'; statusContainer.textContent = 'by恶搞之家'; content.appendChild(statusContainer); const loopStatus = document.createElement('div'); loopStatus.id = 'loopStatusIndicator'; loopStatus.className = 'welearn-loop-status'; loopStatus.style.display = 'none'; loopStatus.textContent = '自动挂机中'; content.appendChild(loopStatus); mainPanel.appendChild(content); let isDragging = false; let currentX; let currentY; let initialX; let initialY; let xOffset = 0; let yOffset = 0; titleBar.addEventListener('mousedown', dragStart); document.addEventListener('mousemove', drag); document.addEventListener('mouseup', dragEnd); function dragStart(e) { initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; if (e.target === titleBar || e.target === title) { isDragging = true; titleBar.style.cursor = 'grabbing'; } } function drag(e) { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; setTranslate(currentX, currentY, mainPanel); } } function setTranslate(xPos, yPos, el) { el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; } function dragEnd() { initialX = currentX; initialY = currentY; isDragging = false; titleBar.style.cursor = 'grab'; } return mainPanel; } async function executeWaitTimer(callback) { const timeInput = document.getElementById('waitTimeInput'); const countdownDisplay = document.getElementById('countdownDisplay'); let waitTime = parseInt(timeInput?.value || defaultWaitTime); if (isNaN(waitTime) || waitTime < 1) { waitTime = defaultWaitTime; if (timeInput) timeInput.value = defaultWaitTime.toString(); } else { defaultWaitTime = waitTime; } if (waitTime <= 0) { if (typeof callback === 'function') callback(); return; } if (countdownDisplay) { countdownDisplay.textContent = waitTime + ' 秒'; countdownDisplay.style.color = '#00ffcc'; countdownDisplay.style.display = 'block'; } if (waitTimerInterval) { clearInterval(waitTimerInterval); } waitTimerActive = true; let remainingTime = waitTime; return new Promise(resolve => { waitTimerInterval = setInterval(() => { remainingTime--; if (countdownDisplay) { countdownDisplay.textContent = remainingTime + ' 秒'; if (remainingTime <= 10 && remainingTime > 0) { countdownDisplay.style.color = '#ff6b6b'; countdownDisplay.style.transform = 'scale(1.05)'; } else { countdownDisplay.style.transform = 'scale(1)'; } } if (remainingTime <= 0) { clearInterval(waitTimerInterval); waitTimerInterval = null; waitTimerActive = false; if (countdownDisplay) { countdownDisplay.textContent = '完成!'; countdownDisplay.style.color = '#4CAF50'; countdownDisplay.classList.add('status-update'); setTimeout(() => { if (countdownDisplay) { countdownDisplay.textContent = '未开始'; countdownDisplay.style.color = '#80cbc4'; countdownDisplay.classList.remove('status-update'); } }, 3000); } if (typeof callback === 'function') callback(); resolve(); } }, 1000); }); } function cancelWaitTimer() { if (waitTimerInterval) { clearInterval(waitTimerInterval); waitTimerInterval = null; } waitTimerActive = false; const countdownDisplay = document.getElementById('countdownDisplay'); if (countdownDisplay) { countdownDisplay.textContent = '已取消'; countdownDisplay.style.color = '#ff9800'; countdownDisplay.classList.add('status-update'); setTimeout(() => { if (countdownDisplay) { countdownDisplay.textContent = '未开始'; countdownDisplay.style.color = '#80cbc4'; countdownDisplay.classList.remove('status-update'); } }, 3000); } } function addButton() { if (window !== window.top) { console.log('当前在iframe中,不添加按钮'); return; } removeExistingButtons(); const uiPanel = createIntegratedUI(); document.body.appendChild(uiPanel); updateButtonsState(); } function updateButtonsState() { const loopButton = document.getElementById('autoLoopButton'); if (loopButton) { if (isAutoLoopActive) { loopButton.textContent = '停止自动挂机'; loopButton.className = 'welearn-button welearn-loop-active'; showLoopStatus(true); } else { loopButton.textContent = '开始自动挂机'; loopButton.className = 'welearn-button welearn-loop-button'; showLoopStatus(false); } } } function showLoopStatus(isActive) { let statusIndicator = document.getElementById('loopStatusIndicator'); if (!statusIndicator) return; if (isActive) { statusIndicator.innerHTML = ' 自动挂机中'; statusIndicator.style.display = 'flex'; const style = document.createElement('style'); style.id = 'loopStatusStyle'; style.textContent = ` @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } } `; if (!document.getElementById('loopStatusStyle')) { document.head.appendChild(style); } } else { statusIndicator.style.display = 'none'; } } async function toggleAutoLoop() { if (!isAutoLoopActive) { isAutoLoopActive = true; updateButtonsState(); showLoopStatus(true); await runAutoAnswerProcess(true); } else { stopAutoLoop(); } } function stopAutoLoop() { console.log('停止自动挂机'); isAutoLoopActive = false; if (autoLoopTimeout) { clearTimeout(autoLoopTimeout); autoLoopTimeout = null; } cancelWaitTimer(); updateButtonsState(); showLoopStatus(false); } async function runAutoAnswerProcess(isLoop) { if (!isLoop && isAutoLoopActive) { console.log('自动挂机已激活,单次执行被忽略'); return; } try { const answerButton = document.getElementById('autoAnswerButton'); if (isLoop) { if (answerButton) { answerButton.textContent = '等待中...'; answerButton.style.backgroundColor = 'orange'; } await executeWaitTimer(() => { if (answerButton) { answerButton.textContent = '开始答题...'; } }); if (!isAutoLoopActive) return; } if (answerButton) { answerButton.textContent = '检测环境...'; answerButton.style.backgroundColor = 'orange'; } const iframeFunctions = await ensureCorrectContext(); const selectAnswersFn = iframeFunctions ? iframeFunctions.autoSelectCorrectAnswers : autoSelectCorrectAnswers; const fillAnswersFn = iframeFunctions ? iframeFunctions.autoFillAnswers : autoFillAnswers; const selectDropdownsFn = iframeFunctions ? iframeFunctions.autoSelectDropdownAnswers : autoSelectDropdownAnswers; const matchLinesFn = iframeFunctions ? iframeFunctions.autoMatchLines : autoMatchLines; const submitAnswersFn = iframeFunctions ? iframeFunctions.submitAnswers : submitAnswers; const handlePickerQuestionsFn = iframeFunctions ? iframeFunctions.handlePickerQuestions : handlePickerQuestions; let hasQuestions = false; let doc = document; const contentFrame = document.getElementById('contentFrame'); if (contentFrame && contentFrame.contentDocument) { doc = contentFrame.contentDocument; } const questionSelectors = [ 'et-choice[et-index]', 'et-tof[et-index]', 'div[data-controltype="choice"]', 'div.white_frame_normal_choice', 'div[data-score]', 'ul[data-itemtype="options"]', 'span[autocapitalize="none"]', 'textarea.blank', 'span.key', 'div.key', 'input[data-itemtype="input"]', 'textarea[data-itemtype="input"]', 'textarea[data-itemtype="textarea"]', 'select[ng-model]', 'et-matching[et-index]', 'span.blank[ng-attr-tabindex]', ]; const checkForQuestions = (document) => { for (const selector of questionSelectors) { const elements = document.querySelectorAll(selector); if (elements.length > 0) { console.log(`找到题目类型 ${selector}:`, elements.length); return true; } } return false; }; hasQuestions = checkForQuestions(doc); if (!hasQuestions) { const iframes = document.getElementsByTagName('iframe'); for (const iframe of iframes) { try { if (iframe.contentDocument) { hasQuestions = checkForQuestions(iframe.contentDocument); if (hasQuestions) { doc = iframe.contentDocument; break; } } } catch (e) { console.log('检查iframe失败:', e); } } } if (answerButton) { answerButton.textContent = '检测题目...'; } const hasChoiceQuestions = ( doc.querySelectorAll('et-choice[et-index], et-tof[et-index], div[data-controltype="choice"], div.white_frame_normal_choice, div[data-score], ul[data-itemtype="options"]').length > 0 ) || ( window.frames['contentFrame']?.document.querySelectorAll('et-choice[et-index], et-tof[et-index], div[data-controltype="choice"], div.white_frame_normal_choice, div[data-score], ul[data-itemtype="options"]').length > 0 ); if (hasChoiceQuestions) { hasQuestions = true; await selectAnswersFn(); console.log('选择题和判断题处理完成'); await sleep(1000); } if (answerButton) { answerButton.textContent = '检测填空题...'; } const hasBlankQuestions = (doc.querySelectorAll('span[autocapitalize="none"], textarea.blank, span.key, div.key, input[data-solution], textarea[data-solution]').length > 0) || (window.frames['contentFrame']?.document.querySelectorAll('span[autocapitalize="none"], textarea.blank, span.key, div.key, input[data-solution], textarea[data-solution]').length > 0); if (hasBlankQuestions) { hasQuestions = true; await fillAnswersFn(); console.log('填空题处理完成'); await sleep(1000); } if (answerButton) { answerButton.textContent = '检测下拉框...'; } const hasDropdowns = (doc.querySelectorAll('select[ng-model]').length > 0) || (window.frames['contentFrame']?.document.querySelectorAll('select[ng-model]').length > 0); if (hasDropdowns) { hasQuestions = true; await selectDropdownsFn(); console.log('下拉框处理完成'); await sleep(1000); } if (answerButton) { answerButton.textContent = '检测连线题...'; } const hasMatchingQuestions = (doc.querySelectorAll('et-matching[et-index]').length > 0) || (window.frames['contentFrame']?.document.querySelectorAll('et-matching[et-index]').length > 0); if (hasMatchingQuestions) { hasQuestions = true; await matchLinesFn(); console.log('连线题处理完成'); await sleep(1000); } if (answerButton) { answerButton.textContent = '检测单元测试...'; } const hasUnitTest = (doc.querySelectorAll('span.unittestresult').length > 0) || (window.frames['contentFrame']?.document.querySelectorAll('span.unittestresult').length > 0); if (hasUnitTest) { hasQuestions = true; await handleUnitTestAnswers(); console.log('单元测试题处理完成'); await sleep(1000); } const hasTabExercise = (doc.querySelectorAll('li[ng-click*="tab.go"]').length > 0) || (window.frames['contentFrame']?.document.querySelectorAll('li[ng-click*="tab.go"]').length > 0); if (hasTabExercise) { hasQuestions = true; if (answerButton) { answerButton.textContent = '处理标签页练习...'; } await handleTabExercises(); console.log('标签页练习处理完成'); await sleep(1000); } if (answerButton) { answerButton.textContent = '检测选择框题目...'; } const hasPickerQuestions = (doc.querySelectorAll('span.blank[ng-attr-tabindex]').length > 0) || (window.frames['contentFrame']?.document.querySelectorAll('span.blank[ng-attr-tabindex]').length > 0); if (hasPickerQuestions) { hasQuestions = true; await handlePickerQuestions(); console.log('选择框题目处理完成'); await sleep(1000); } if (!hasQuestions) { console.log('未找到需要处理的题目,准备跳转到下一章节...'); if (answerButton) { answerButton.textContent = window.autoNextEnabled ? '跳转中...' : '已完成'; answerButton.style.backgroundColor = window.autoNextEnabled ? 'blue' : 'green'; } if (window.autoNextEnabled) { await autoNextSection(); } } else { await sleep(2000); if (answerButton) { answerButton.textContent = window.autoSubmitEnabled ? '提交中...' : '已完成'; } let submitResult = false; if (window.autoSubmitEnabled) { submitResult = await submitAnswersFn(); } else { console.log('自动提交已禁用,跳过提交'); } if (!submitResult) { if (answerButton) { answerButton.textContent = window.autoNextEnabled ? '跳转中...' : '已完成'; answerButton.style.backgroundColor = window.autoNextEnabled ? 'blue' : 'green'; } if (window.autoNextEnabled) { await autoNextSection(); } } } if (isLoop && isAutoLoopActive) { if (answerButton) { answerButton.textContent = '准备下一轮...'; answerButton.style.backgroundColor = 'purple'; } console.log('等待页面加载,准备下一轮答题...'); autoLoopTimeout = setTimeout(async () => { console.log('开始下一轮答题'); if (isAutoLoopActive) { await runAutoAnswerProcess(true); } }, 3000); } else { if (answerButton) { answerButton.textContent = '已完成'; answerButton.style.backgroundColor = 'green'; setTimeout(() => { if (answerButton && !isAutoLoopActive) { answerButton.textContent = '一键全自动'; answerButton.style.backgroundColor = 'rgb(0, 255, 127)'; } }, 3000); } } } catch (error) { console.error('自动化流程出错:', error); const answerButton = document.getElementById('autoAnswerButton'); if (answerButton) { answerButton.textContent = '出错了!'; answerButton.style.backgroundColor = 'red'; } if (isLoop && isAutoLoopActive) { console.log('自动挂机出错,10秒后重试...'); autoLoopTimeout = setTimeout(async () => { console.log('重新开始挂机'); if (isAutoLoopActive) { await runAutoAnswerProcess(true); } }, 10000); } else { setTimeout(() => { if (answerButton && !isAutoLoopActive) { answerButton.textContent = '一键全自动'; answerButton.style.backgroundColor = 'rgb(0, 255, 127)'; } }, 5000); } } } function removeExistingButtons() { const welearnPanel = document.getElementById('welearnHelperPanel'); if (welearnPanel && welearnPanel.parentNode) { welearnPanel.parentNode.removeChild(welearnPanel); } const oldElements = [ document.getElementById('autoAnswerButton'), document.getElementById('autoLoopButton'), document.getElementById('autoAnswerButtonContainer'), document.getElementById('autoAnswerInfoText'), document.getElementById('loopStatusIndicator'), document.getElementById('waitTimerContainer') ]; oldElements.forEach(element => { if (element && element.parentNode) { element.parentNode.removeChild(element); } }); const allFixedElements = document.querySelectorAll('*[style*="position: fixed"], *[style*="position:fixed"]'); for (const element of allFixedElements) { const computedStyle = window.getComputedStyle(element); const top = parseInt(computedStyle.top); const left = parseInt(computedStyle.left); if (top <= 50 && left <= 300 && !element.closest('#welearnHelperPanel') && (element.tagName === 'BUTTON' || element.tagName === 'DIV' || element.id.includes('auto') || element.id.includes('button') || (element.textContent && ( element.textContent.includes('一键') || element.textContent.includes('全自动') || element.textContent.includes('自动') || element.textContent.includes('挂机') || element.textContent.includes('答题') || element.textContent.includes('提交') )) )) { console.log('强制移除外部元素:', element.tagName, element.id || element.className, element.textContent?.substring(0, 20)); if (element.parentNode) { element.parentNode.removeChild(element); } } } const loopStyle = document.getElementById('loopStatusStyle'); if (loopStyle && loopStyle.parentNode) { loopStyle.parentNode.removeChild(loopStyle); } cancelWaitTimer(); console.log('移除已存在的UI元素'); } function clearExternalButtons() { const allButtons = document.querySelectorAll('button'); allButtons.forEach(button => { if (button.closest('#welearnHelperPanel')) { return; } if (button.textContent && ( button.textContent.includes('一键') || button.textContent.includes('全自动') || button.textContent.includes('自动') || button.textContent.includes('挂机') || button.textContent === '一键全自动' || button.textContent === '开始自动挂机' || button.textContent === '停止自动挂机' )) { console.log('强制移除外部按钮:', button.textContent); if (button.parentNode) { button.parentNode.removeChild(button); } } }); const containers = document.querySelectorAll('div[style*="position: fixed"], div[style*="position:fixed"]'); containers.forEach(container => { if (container.id === 'welearnHelperPanel' || container.closest('#welearnHelperPanel')) { return; } const style = window.getComputedStyle(container); const top = parseInt(style.top); const left = parseInt(style.left); if (top <= 50 && left <= 50) { const innerButtons = container.querySelectorAll('button'); if (innerButtons.length > 0) { console.log('移除外部按钮容器:', container.id || container.className); if (container.parentNode) { container.parentNode.removeChild(container); } } } }); const buttonContainer = document.getElementById('autoAnswerButtonContainer'); if (buttonContainer) { console.log('移除autoAnswerButtonContainer'); buttonContainer.parentNode.removeChild(buttonContainer); } } window.addEventListener('beforeunload', () => { stopAutoLoop(); }); let observer; function setupObserver() { if (observer) { observer.disconnect(); } observer = new MutationObserver((mutations) => { clearExternalButtons(); const hasPanel = document.getElementById('welearnHelperPanel'); const hasButton = document.getElementById('autoAnswerButton'); if ((!hasPanel || !hasButton) && window === window.top) { console.log('DOM变化检测到面板或按钮不存在,添加面板'); removeExistingButtons(); addButton(); } setTimeout(clearExternalButtons, 100); }); if (window === window.top) { observer.observe(document.body, { childList: true, subtree: true }); clearExternalButtons(); } } function setupPageListeners() { window.removeEventListener('load', handlePageLoad); window.addEventListener('load', handlePageLoad); if (window === window.top) { let lastUrl = window.location.href; const checkURLChange = () => { if (lastUrl !== window.location.href) { console.log('URL已变化,重新添加按钮'); lastUrl = window.location.href; setTimeout(() => { removeExistingButtons(); addButton(); }, 1000); } }; setInterval(checkURLChange, 1000); } } function handlePageLoad() { console.log('页面加载完成,检查按钮'); if (window === window.top) { removeExistingButtons(); addButton(); } } function initialize() { if (window.weLearnHelperInitialized) { console.log('助手已初始化,跳过'); return; } window.weLearnHelperInitialized = true; window.isTransitioning = false; console.log('初始化WeLearn助手'); if (window === window.top) { let lastTransitionTime = 0; const TRANSITION_COOLDOWN = 5000; window.addEventListener('message', function(event) { if (event.data && event.data.action === 'nextSection') { const currentTime = Date.now(); if (currentTime - lastTransitionTime < TRANSITION_COOLDOWN) { console.log('跳转冷却中,忽略重复请求'); return; } if (!window.autoNextEnabled) { console.log('自动跳转已禁用,忽略跳转请求'); return; } console.log('收到iframe的跳转请求'); lastTransitionTime = currentTime; try { if (typeof NextSCO === 'function' && !window.isTransitioning) { window.isTransitioning = true; NextSCO(); console.log('成功执行NextSCO'); setTimeout(() => { window.isTransitioning = false; }, 5000); } } catch(e) { console.error('执行NextSCO失败:', e); window.isTransitioning = false; } } }); } if (window === window.top) { removeExistingButtons(); addButton(); setupObserver(); setupPageListeners(); } } initialize(); async function simulateHTML5DragDrop(sourceElement, targetElement) { if (!sourceElement || !targetElement) return; console.log('使用HTML5拖放API模拟拖拽'); try { const dragStartEvent = new DragEvent('dragstart', { bubbles: true, cancelable: true, dataTransfer: new DataTransfer() }); dragStartEvent.dataTransfer.setData('text/plain', 'dragged'); sourceElement.dispatchEvent(dragStartEvent); await new Promise(resolve => setTimeout(resolve, 200)); const dragOverEvent = new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer: dragStartEvent.dataTransfer }); targetElement.dispatchEvent(dragOverEvent); await new Promise(resolve => setTimeout(resolve, 200)); const dropEvent = new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: dragStartEvent.dataTransfer }); targetElement.dispatchEvent(dropEvent); const dragEndEvent = new DragEvent('dragend', { bubbles: true, cancelable: true, dataTransfer: dragStartEvent.dataTransfer }); sourceElement.dispatchEvent(dragEndEvent); console.log('HTML5拖放事件序列完成'); } catch (e) { console.error('HTML5拖放模拟失败:', e); } } async function simulateMouseDrag(sourceElement, targetElement, coords) { if (!sourceElement || !targetElement) return; console.log('使用增强的鼠标事件模拟拖拽'); const { fromX, fromY, toX, toY } = coords; const dragVisual = document.createElement('div'); dragVisual.style.cssText = ` position: fixed; pointer-events: none; z-index: 10000; transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); opacity: 0; background: rgba(255, 255, 255, 0.95); border: 2px solid #4CAF50; border-radius: 6px; box-shadow: 0 4px 12px rgba(76, 175, 80, 0.2), 0 8px 24px rgba(0, 0, 0, 0.15); padding: 8px; transform-origin: center center; backdrop-filter: blur(4px); will-change: transform, opacity; `; if (sourceElement.tagName.toLowerCase() === 'circle') { dragVisual.style.width = '24px'; dragVisual.style.height = '24px'; dragVisual.style.borderRadius = '50%'; dragVisual.style.background = 'linear-gradient(135deg, #4CAF50, #45a049)'; dragVisual.style.border = '2px solid rgba(255, 255, 255, 0.8)'; dragVisual.style.boxShadow = '0 2px 8px rgba(76, 175, 80, 0.3), inset 0 2px 4px rgba(255, 255, 255, 0.3)'; } else { dragVisual.innerHTML = sourceElement.innerHTML; dragVisual.style.width = sourceElement.offsetWidth + 'px'; dragVisual.style.height = sourceElement.offsetHeight + 'px'; dragVisual.style.background = 'linear-gradient(135deg, rgba(255, 255, 255, 0.98), rgba(255, 255, 255, 0.92))'; } document.body.appendChild(dragVisual); try { requestAnimationFrame(() => { dragVisual.style.opacity = '1'; dragVisual.style.transform = 'scale(1.05) translateY(-2px)'; }); const mouseDownEvent = new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window, clientX: fromX, clientY: fromY, button: 0 }); sourceElement.dispatchEvent(mouseDownEvent); dragVisual.style.left = `${fromX}px`; dragVisual.style.top = `${fromY}px`; const dx = toX - fromX; const dy = toY - fromY; const distance = Math.sqrt(dx * dx + dy * dy); const curvatureHeight = -Math.min(distance * 0.3, 100); const controlX = (fromX + toX) / 2; const controlY = Math.min(fromY, toY) + curvatureHeight; const steps = 30; const stepDuration = 12; for (let i = 1; i <= steps; i++) { const progress = i / steps; const ease = easeInOutCubic(progress); const t = ease; const moveX = Math.pow(1-t, 2) * fromX + 2 * (1-t) * t * controlX + Math.pow(t, 2) * toX; const moveY = Math.pow(1-t, 2) * fromY + 2 * (1-t) * t * controlY + Math.pow(t, 2) * toY; const rotation = Math.sin(progress * Math.PI) * 2; const scale = 1.05 - Math.abs(progress - 0.5) * 0.1; dragVisual.style.transform = ` translate3d(${moveX - dragVisual.offsetWidth / 2}px, ${moveY - dragVisual.offsetHeight / 2}px, 0) scale(${scale}) rotate(${rotation}deg) `; const shadowBlur = 12 - Math.abs(progress - 0.5) * 8; const shadowOpacity = 0.2 + Math.abs(progress - 0.5) * 0.1; dragVisual.style.boxShadow = ` 0 ${shadowBlur}px ${shadowBlur * 2}px rgba(0, 0, 0, ${shadowOpacity}), 0 ${shadowBlur/2}px ${shadowBlur}px rgba(76, 175, 80, 0.2) `; const mouseMoveEvent = new MouseEvent('mousemove', { bubbles: true, cancelable: true, view: window, clientX: moveX, clientY: moveY, button: 0 }); document.elementFromPoint(moveX, moveY)?.dispatchEvent(mouseMoveEvent); await new Promise(resolve => setTimeout(resolve, stepDuration)); } const mouseUpEvent = new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window, clientX: toX, clientY: toY, button: 0 }); dragVisual.style.transition = 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)'; dragVisual.style.transform = 'scale(0.8) translateY(10px)'; dragVisual.style.opacity = '0'; targetElement.dispatchEvent(mouseUpEvent); await new Promise(resolve => setTimeout(resolve, 200)); document.body.removeChild(dragVisual); targetElement.style.transition = 'transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; targetElement.style.transform = 'scale(1.1)'; await new Promise(resolve => setTimeout(resolve, 100)); targetElement.style.transform = ''; console.log('增强的鼠标拖拽事件序列完成'); } catch (e) { console.error('增强的鼠标拖拽模拟失败:', e); if (document.body.contains(dragVisual)) { document.body.removeChild(dragVisual); } } } function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; } function bezierPoint(t, p0, p1, p2) { const oneMinusT = 1 - t; return Math.pow(oneMinusT, 2) * p0 + 2 * oneMinusT * t * p1 + Math.pow(t, 2) * p2; } async function simulateDragDrop(sourceElement, targetElement, coords) { if (!sourceElement || !targetElement) return; console.log('使用增强的组合事件模拟拖拽'); const { fromX, fromY, toX, toY } = coords; try { sourceElement.style.transition = 'transform 0.2s ease-out'; sourceElement.style.transform = 'scale(1.05)'; sourceElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window, clientX: fromX, clientY: fromY })); await new Promise(resolve => setTimeout(resolve, 100)); const dragStartEvent = new Event('dragstart', {bubbles: true, cancelable: true}); sourceElement.dispatchEvent(dragStartEvent); const steps = 20; const controlX = (fromX + toX) / 2; const controlY = Math.min(fromY, toY) - 40; for (let i = 1; i <= steps; i++) { const t = i / steps; const moveX = bezierPoint(t, fromX, controlX, toX); const moveY = bezierPoint(t, fromY, controlY, toY); document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, cancelable: true, view: window, clientX: moveX, clientY: moveY })); await new Promise(resolve => setTimeout(resolve, 15)); } targetElement.style.transition = 'transform 0.2s ease-out'; targetElement.style.transform = 'scale(1.1)'; targetElement.dispatchEvent(new Event('dragover', {bubbles: true, cancelable: true})); await new Promise(resolve => setTimeout(resolve, 100)); targetElement.dispatchEvent(new Event('drop', {bubbles: true, cancelable: true})); sourceElement.dispatchEvent(new Event('dragend', {bubbles: true, cancelable: true})); targetElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window, clientX: toX, clientY: toY })); sourceElement.style.transform = ''; targetElement.style.transform = ''; console.log('增强的组合拖拽事件序列完成'); } catch (e) { console.error('增强的组合拖拽模拟失败:', e); sourceElement.style.transform = ''; targetElement.style.transform = ''; } } async function handleTabExercises() { console.log('开始处理带标签页的练习题目'); try { const tabElements = document.querySelectorAll('li[ng-click*="tab.go"]'); if (tabElements.length === 0) { console.log('未找到标签页元素'); return false; } console.log(`找到${tabElements.length}个标签页`); for (let i = 0; i < tabElements.length; i++) { const tab = tabElements[i]; console.log(`切换到第${i + 1}个标签页`); try { tab.click(); await sleep(1000); if (typeof angular !== 'undefined') { const scope = angular.element(tab).scope(); if (scope) { scope.$apply(); } } await sleep(2000); await autoSelectCorrectAnswers(); await autoFillAnswers(); await autoSelectDropdownAnswers(); await autoMatchLines(); await handleUnitTestAnswers(); if (i === tabElements.length - 1) { console.log('到达最后一个标签页,准备提交答案'); await sleep(1000); if (window.autoSubmitEnabled) { console.log('准备提交答案'); const submitResult = await submitAnswers(); if (submitResult && !window.autoNextEnabled) { return true; } } else { console.log('自动提交已禁用,跳过提交'); } } else { await sleep(1000); } } catch (error) { console.error(`处理第${i + 1}个标签页时出错:`, error); } } return true; } catch (error) { console.error('处理标签页练习题目时出错:', error); return false; } } async function handlePickerQuestions() { console.log('开始处理选择框题目'); let answered = false; try { let doc = document; if (window !== window.top) { doc = document; } else { const contentFrame = document.getElementById('contentFrame'); if (contentFrame && contentFrame.contentDocument) { doc = contentFrame.contentDocument; } } const blankElements = Array.from(doc.querySelectorAll('span.blank[ng-attr-tabindex]')); const totalQuestions = blankElements.length; console.log('找到空白框数量:', totalQuestions); if (totalQuestions === 0) return false; const correctCount = Math.ceil((totalQuestions * window.defaultAccuracyRate) / 100); const wrongCount = totalQuestions - correctCount; console.log(`总题目: ${totalQuestions}, 正确数: ${correctCount}, 错误数: ${wrongCount}`); let allAnswers = []; if (wrongCount > 0) { for (const blank of blankElements) { const keySpan = blank.closest('et-blank')?.querySelector('span[ng-if="blank.hasKey"]'); if (keySpan) { allAnswers.push({ blank: blank, answer: keySpan.textContent.trim() }); } } if (allAnswers.length < 2) { console.log('答案数量不足,无法实现错误率要求'); return false; } if (wrongCount >= 2) { for (let i = allAnswers.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [allAnswers[i], allAnswers[j]] = [allAnswers[j], allAnswers[i]]; } const swapCount = Math.min(wrongCount, Math.floor(allAnswers.length / 2)); for (let i = 0; i < swapCount * 2; i += 2) { const temp = allAnswers[i].answer; allAnswers[i].answer = allAnswers[i + 1].answer; allAnswers[i + 1].answer = temp; } } } for (let i = 0; i < blankElements.length; i++) { const blankElement = blankElements[i]; try { const existingPicker = doc.querySelector('div.optionsPicker.visible'); if (existingPicker) { const closeButton = existingPicker.querySelector('a.close'); if (closeButton) { closeButton.click(); await sleep(500); } } console.log(`准备处理第${i + 1}个空白框`); if (!isElementVisible(blankElement)) { console.log('空白框不可见,跳过'); continue; } async function enhancedClick(element) { try { element.click(); await sleep(200); const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const eventTypes = ['mouseenter', 'mouseover', 'mousedown', 'mouseup', 'click']; for (const eventType of eventTypes) { const event = new Event(eventType, { bubbles: true, cancelable: true }); Object.defineProperties(event, { clientX: { value: centerX }, clientY: { value: centerY }, screenX: { value: centerX }, screenY: { value: centerY } }); element.dispatchEvent(event); await sleep(50); } ['focus', 'focusin'].forEach(eventType => { const event = new Event(eventType, { bubbles: true, cancelable: true }); element.dispatchEvent(event); }); await sleep(100); if (typeof angular !== 'undefined') { const scope = angular.element(element).scope(); if (scope && scope.blank) { if (typeof scope.blank.click === 'function') { scope.blank.click(); } if (typeof scope.blank.focus === 'function') { scope.blank.focus(); } scope.$apply(); } } const parentWrapper = element.closest('span.wrapper'); if (parentWrapper) { parentWrapper.click(); await sleep(100); } const etBlank = element.closest('et-blank'); if (etBlank) { etBlank.click(); await sleep(100); } } catch (e) { console.error('增强点击失败:', e); } } await enhancedClick(blankElement); await sleep(500); let optionsPicker = null; let attempts = 0; const maxAttempts = 5; while (!optionsPicker && attempts < maxAttempts) { optionsPicker = doc.querySelector('div.optionsPicker.visible'); if (!optionsPicker) { console.log(`等待选择框出现,尝试 ${attempts + 1}/${maxAttempts}`); attempts++; if (attempts > 2) { await enhancedClick(blankElement); } await sleep(500); } } if (!optionsPicker) { console.log('选择框未出现,跳过当前空白框'); continue; } let targetAnswer; if (wrongCount > 0 && allAnswers.length > 0) { const answerObj = allAnswers.find(a => a.blank === blankElement); if (answerObj) { targetAnswer = answerObj.answer; console.log('使用交换后的答案:', targetAnswer); } else { const keySpan = blankElement.closest('et-blank')?.querySelector('span[ng-if="blank.hasKey"]'); targetAnswer = keySpan ? keySpan.textContent.trim() : null; console.log('使用原始答案:', targetAnswer); } } else { const keySpan = blankElement.closest('et-blank')?.querySelector('span[ng-if="blank.hasKey"]'); targetAnswer = keySpan ? keySpan.textContent.trim() : null; console.log('使用原始答案:', targetAnswer); } if (!targetAnswer) { console.log('未找到答案,跳过当前空白框'); continue; } const optionsList = optionsPicker.querySelector('ul[type="a"]'); if (!optionsList) { console.log('未找到选项列表,跳过当前空白框'); continue; } const options = Array.from(optionsList.querySelectorAll('li[ng-click*="options.toggle"]')); let optionFound = false; for (const option of options) { try { const ngClickAttr = option.getAttribute('ng-click'); const toggleMatch = ngClickAttr.match(/toggle\('([^']+)'\)/); if (!toggleMatch) continue; const optionValue = toggleMatch[1]; console.log('检查选项:', optionValue); if (optionValue === targetAnswer) { console.log('找到匹配选项:', optionValue); option.click(); await sleep(300); if (typeof angular !== 'undefined') { const scope = angular.element(option).scope(); if (scope?.options?.toggle) { scope.options.toggle(optionValue); scope.$apply(); } } optionFound = true; answered = true; await sleep(500); break; } } catch (e) { console.error('处理选项时出错:', e); } } if (!optionFound) { console.log('未找到匹配选项'); } const closeButton = optionsPicker.querySelector('a.close'); if (closeButton) { closeButton.click(); await sleep(800); } } catch (error) { console.error('处理空白框时出错:', error); } } } catch (error) { console.error('处理选择框题目时出错:', error); } return answered; } async function _0x42fd(_0x456def) { if (!_0x456def) return; try { _0x456def.click(); const _0x789abc = new Event('click', { bubbles: true, cancelable: true }); _0x456def.dispatchEvent(_0x789abc); if (typeof angular !== 'undefined') { try { const _0x123def = angular.element(_0x456def).scope(); if (_0x123def) { if (_0x123def.blank) { console.log(decodeURIComponent('%E6%89%BE%E5%88%B0blank%20scope:'), _0x123def.blank); if (_0x123def.blank.tabIndex) { console.log(decodeURIComponent('%E5%BD%93%E5%89%8DtabIndex:'), _0x123def.blank.tabIndex); } } _0x123def.$apply(); } } catch (_0x234567) { console.log(decodeURIComponent('%E8%A7%A6%E5%8F%91%E4%BA%8B%E4%BB%B6%E5%A4%B1%E8%B4%A5:'), _0x234567); } } ['mousedown', 'mouseup', 'focus'].forEach(_0x345678 => { try { const _0x456789 = new Event(_0x345678, { bubbles: true, cancelable: true }); _0x456def.dispatchEvent(_0x456789); } catch (_0x567890) { console.log(decodeURIComponent('%E8%A7%A6%E5%8F%91') + _0x345678 + decodeURIComponent('%E4%BA%8B%E4%BB%B6%E5%A4%B1%E8%B4%A5:'), _0x567890); } }); } catch (_0x678901) { console.log(decodeURIComponent('%E7%82%B9%E5%87%BB%E4%BA%8B%E4%BB%B6%E6%89%A7%E8%A1%8C%E5%A4%B1%E8%B4%A5:'), _0x678901); throw _0x678901; } } window.clickElement = _0x42fd; const _0xwxpay = { showQRCode: function() { const existingModal = document.getElementById('wxPayModal'); if (existingModal) { existingModal.remove(); return; } const modal = document.createElement('div'); modal.id = 'wxPayModal'; modal.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(255, 255, 255, 0.95); padding: 20px; border-radius: 12px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2); z-index: 10001; text-align: center; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); min-width: 300px; `; const title = document.createElement('div'); title.textContent = decodeURIComponent('%E5%BE%AE%E4%BF%A1%E6%89%AB%E7%A0%81%E6%94%AF%E4%BB%98'); title.style.cssText = ` font-size: 16px; color: #333; margin-bottom: 15px; font-weight: bold; `; const closeBtn = document.createElement('div'); closeBtn.textContent = '×'; closeBtn.style.cssText = ` position: absolute; top: 10px; right: 15px; font-size: 24px; cursor: pointer; color: #666; line-height: 24px; width: 24px; height: 24px; text-align: center; border-radius: 12px; transition: all 0.3s ease; `; closeBtn.onmouseover = () => { closeBtn.style.background = 'rgba(0, 0, 0, 0.1)'; }; closeBtn.onmouseout = () => { closeBtn.style.background = 'transparent'; }; closeBtn.onclick = () => modal.remove(); const imgContainer = document.createElement('div'); imgContainer.style.cssText = ` width: 200px; height: 200px; margin: 0 auto 10px; border-radius: 8px; overflow: hidden; border: 1px solid rgba(0, 0, 0, 0.1); background: #fff; `; const qrcode = document.createElement('img'); qrcode.style.cssText = ` width: 100%; height: 100%; object-fit: contain; `; qrcode.onerror = () => { imgContainer.innerHTML = decodeURIComponent('%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%A4%B1%E8%B4%A5'); imgContainer.style.lineHeight = '200px'; imgContainer.style.color = '#999'; }; qrcode.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhkAAAH+BAMAAADDnQEfAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAJcEhZcwAAHYcAAB2HAY/l8WUAAAAeUExURf imgContainer.appendChild(qrcode); modal.appendChild(closeBtn); modal.appendChild(title); modal.appendChild(imgContainer); document.body.appendChild(modal); modal.onclick = (e) => { if (e.target === modal) { modal.remove(); } }; const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.3); backdrop-filter: blur(2px); z-index: 10000; `; overlay.onclick = () => { overlay.remove(); modal.remove(); }; document.body.appendChild(overlay); } }; const _0xaddPayButton = function() { const existingBtn = document.querySelector('.welearn-pay-btn'); if (existingBtn) { existingBtn.remove(); } const payBtn = document.createElement('div'); payBtn.className = 'welearn-pay-btn'; payBtn.textContent = decodeURIComponent('%E8%B5%9E%E8%B5%8F%E4%BD%9C%E8%80%85'); payBtn.style.cssText = ` color: #4CAF50; font-weight: bold; cursor: pointer; padding: 8px 12px; border-radius: 6px; background: rgba(76, 175, 80, 0.1); transition: all 0.3s ease; text-align: center; margin-top: 10px; user-select: none; `; payBtn.onmouseover = () => { payBtn.style.background = 'rgba(76, 175, 80, 0.2)'; }; payBtn.onmouseout = () => { payBtn.style.background = 'rgba(76, 175, 80, 0.1)'; }; payBtn.onclick = () => _0xwxpay.showQRCode(); const panel = document.getElementById('welearnHelperPanel'); if (panel) { panel.appendChild(payBtn); } }; const _0xobserver = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.id === 'welearnHelperPanel') { _0xaddPayButton(); } }); }); }); _0xobserver.observe(document.body, { childList: true, subtree: true }); window.addEventListener('load', () => { setTimeout(_0xaddPayButton, 1000); }); setInterval(() => { const panel = document.getElementById('welearnHelperPanel'); const payBtn = document.querySelector('.welearn-pay-btn'); if (panel && !payBtn) { _0xaddPayButton(); } }, 2000); })();