// ==UserScript== // @name 特种考试自动答题脚本-中安云教育 // @namespace http://tampermonkey.net/ // @version 5.2.0 // @description 特种考试自动答题脚本-中安云教育 | ⚠️ 此脚本仅供学习交流使用,请勿用于违规用途 // @author You // @match https://txsyaqpx.zhongancloud.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_info // @grant GM_notification // @grant unsafeWindow // @require https://lib.baomitu.com/jquery/3.6.0/jquery.min.js // @run-at document-start // ==/UserScript== // ========== 验证码验证模块 ========== (function() { 'use strict'; const VERIFY_API = 'https://qsy.iano.cn/index.php?s=/api/code/verify'; const STORAGE_KEY = 'zhongan_exam_valid_until'; const VERIFY_DATE_KEY = 'zhongan_exam_verify_date'; const SESSION_KEY = 'zhongan_exam_session'; const QRCODE_IMG = 'https://qsy.iano.cn/yzm.png'; // 域名验证 if (!window.location.hostname.includes('zhongancloud.com')) { console.error('❌ 脚本仅在中安云教育平台使用'); return; } // 获取今天的日期字符串 YYYY-MM-DD function getTodayStr() { const d = new Date(); return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0'); } // 检查是否已验证 function isVerified() { // 检查是否是同一会话(浏览器未关闭) if (sessionStorage.getItem(SESSION_KEY)) { // 同一会话内,检查24小时有效期 const validUntil = GM_getValue(STORAGE_KEY, 0); if (validUntil > Date.now() / 1000) { return true; } } // 新会话(浏览器已关闭重新打开):检查是否跨天 const verifyDate = GM_getValue(VERIFY_DATE_KEY, ''); const today = getTodayStr(); if (verifyDate === today) { // 同一天,标记会话并允许使用 sessionStorage.setItem(SESSION_KEY, '1'); return true; } // 跨天了,需要重新验证 return false; } // 显示验证弹窗 function showVerifyDialog() { const overlay = document.createElement('div'); overlay.id = '_verify_overlay'; overlay.innerHTML = `
🔐 验证码验证
扫码观看广告获取验证码
验证后免费使用24小时
小程序码
`; (document.body || document.documentElement).appendChild(overlay); const input = document.getElementById('_verify_code'); const btn = document.getElementById('_verify_submit'); const errorEl = document.getElementById('_verify_error'); btn.onclick = function() { const code = input.value.trim(); if (!/^\d{4}$/.test(code)) { errorEl.textContent = '请输入4位验证码'; errorEl.style.display = 'block'; errorEl.classList.remove('shake'); void errorEl.offsetWidth; errorEl.classList.add('shake'); return; } btn.disabled = true; btn.textContent = '验证中...'; errorEl.style.display = 'none'; GM_xmlhttpRequest({ method: 'POST', url: VERIFY_API, timeout: 10000, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data: 'code=' + encodeURIComponent(code), onload: function(res) { try { const data = JSON.parse(res.responseText); if (data.code === 1 && data.data.valid) { GM_setValue(STORAGE_KEY, data.data.valid_until); GM_setValue(VERIFY_DATE_KEY, getTodayStr()); sessionStorage.setItem(SESSION_KEY, '1'); overlay.remove(); GM_notification({ text: '验证成功!24小时内免费使用', title: '自动答题助手', timeout: 3000 }); location.reload(); } else { errorEl.textContent = data.msg || '验证码无效或已过期'; errorEl.style.display = 'block'; errorEl.classList.remove('shake'); void errorEl.offsetWidth; errorEl.classList.add('shake'); btn.disabled = false; btn.textContent = '立即验证'; } } catch(e) { errorEl.textContent = '验证失败,请重试'; errorEl.style.display = 'block'; errorEl.classList.remove('shake'); void errorEl.offsetWidth; errorEl.classList.add('shake'); btn.disabled = false; btn.textContent = '立即验证'; } }, onerror: function() { errorEl.textContent = '网络错误,请重试'; errorEl.style.display = 'block'; errorEl.classList.remove('shake'); void errorEl.offsetWidth; errorEl.classList.add('shake'); btn.disabled = false; btn.textContent = '立即验证'; } }); }; input.onkeypress = function(e) { if (e.key === 'Enter') btn.click(); }; setTimeout(() => input.focus(), 300); } // 主逻辑:检查验证状态 if (!isVerified()) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', showVerifyDialog); } else { showVerifyDialog(); } return; // 未验证则阻止脚本继续执行 } })(); // ========== 验证码验证模块结束 ========== (function() { 'use strict'; // 全局配置 const CONFIG = { delay: 1500, // 优化:默认延时从2000ms减少到1500ms stop: true, minDelay: 800, // 优化:最小延时从1000ms减少到800ms autoSubmit: false, // 自动提交试卷 // 设备类型检测 isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent), isTablet: /iPad|Android.*(?=.*\b\d+X\d+\b)/i.test(navigator.userAgent) || (navigator.userAgent.includes('Android') && !navigator.userAgent.includes('Mobile')), // 智谱AI配置(密钥已加密) ZHIPU_CONFIG: { // 加密的API密钥(Base64编码) _key: 'ZjkwNTNkZTc1NmUwNDFmNWEzNjEzZjMzY2YyMmY4NzguaEhXMjRNUkRITGdQTHE3SQ==', application_id: '1975919497449705472', // 智能体ID knowledge_base_id: '1975919768523378688', // 知识库ID base_url: 'https://open.bigmodel.cn/api/llm-application/open', // 解密函数 get api_key() { // 域名验证 if (!window.location.hostname.includes('zhongancloud.com')) { console.error('❌ 域名验证失败'); return ''; } // Base64解码 try { return atob(this._key); } catch(e) { console.error('❌ 密钥解密失败'); return ''; } } } }; let logContainer; let stats = { total: 0, processed: 0, success: 0, failed: 0, knowledgeHits: 0, aiBackup: 0 }; // 答题进度管理 let progressManager = { storageKey: 'exam_progress_' + window.location.pathname, // 保存进度 saveProgress: function(currentIndex, totalQuestions) { const progress = { currentIndex: currentIndex, totalQuestions: totalQuestions, timestamp: Date.now(), url: window.location.href, stats: {...stats} }; GM_setValue(this.storageKey, JSON.stringify(progress)); log(`💾 已保存答题进度: ${currentIndex + 1}/${totalQuestions}`); }, // 获取保存的进度 getProgress: function() { try { const saved = GM_getValue(this.storageKey, null); if (saved) { const progress = JSON.parse(saved); // 检查进度是否过期(24小时) if (Date.now() - progress.timestamp < 24 * 60 * 60 * 1000) { return progress; } } } catch (e) { log(`⚠️ 读取进度失败: ${e.message}`); } return null; }, // 清除进度 clearProgress: function() { GM_setValue(this.storageKey, null); log(`🗑️ 已清除答题进度`); }, // 检查是否有可恢复的进度 hasProgress: function() { const progress = this.getProgress(); return progress && progress.currentIndex > 0; } }; // 后台运行相关变量 let isRunning = false; let keepAliveInterval = null; let visibilityChangeCount = 0; let lastActiveTime = Date.now(); let focusChangeTimeout = null; // 防止后台暂停机制(平板优化版) function setupBackgroundKeepAlive() { const debounceTime = CONFIG.isTablet ? 3000 : 1000; // 平板设备使用更长的防抖时间 // 页面可见性变化监听 document.addEventListener('visibilitychange', function() { visibilityChangeCount++; log(`📱 页面可见性变化: ${document.hidden ? '隐藏' : '显示'} (第${visibilityChangeCount}次)`); if (document.hidden) { if (isRunning) { log('🛡️ 页面进入后台,启动保活机制'); startKeepAlive(); } } else { if (keepAliveInterval) { log('🛡️ 页面回到前台,停止保活机制'); clearInterval(keepAliveInterval); keepAliveInterval = null; } lastActiveTime = Date.now(); } }); // 窗口焦点变化监听(平板优化防抖) window.addEventListener('blur', function() { if (focusChangeTimeout) { clearTimeout(focusChangeTimeout); } focusChangeTimeout = setTimeout(() => { if (isRunning && !keepAliveInterval) { log('🛡️ 窗口失去焦点,启动保活机制'); startKeepAlive(); } }, debounceTime); // 平板使用更长的防抖时间 }); window.addEventListener('focus', function() { if (focusChangeTimeout) { clearTimeout(focusChangeTimeout); focusChangeTimeout = null; } if (keepAliveInterval) { log('🛡️ 窗口获得焦点,停止保活机制'); clearInterval(keepAliveInterval); keepAliveInterval = null; } lastActiveTime = Date.now(); }); // 移动设备特殊事件监听 if (CONFIG.isMobile || CONFIG.isTablet) { // 监听触摸事件 ['touchstart', 'touchmove', 'touchend'].forEach(event => { document.addEventListener(event, function() { lastActiveTime = Date.now(); }, { passive: true }); }); // 监听方向变化 window.addEventListener('orientationchange', function() { log('📱 屏幕方向发生变化,重置活跃时间'); lastActiveTime = Date.now(); // 延迟重启保活机制,给设备时间适应 setTimeout(() => { if (isRunning && document.hidden) { startKeepAlive(); } }, 2000); }); } } // 启动保活机制(平板优化版) function startKeepAlive() { if (keepAliveInterval) { return; } const keepAliveDelay = CONFIG.isTablet ? 2000 : 3000; // 平板使用更频繁的保活 keepAliveInterval = setInterval(() => { // 执行轻量级操作保持页面活跃 lastActiveTime = Date.now(); // 模拟用户活动 try { // 移动设备优先使用触摸事件 if (CONFIG.isMobile || CONFIG.isTablet) { const touchEvent = new TouchEvent('touchstart', { bubbles: true, cancelable: true, touches: [] }); document.dispatchEvent(touchEvent); } else { const event = new Event('mousemove', { bubbles: true }); document.dispatchEvent(event); } // 触发一个轻量级的DOM操作 const dummy = document.createElement('div'); dummy.style.display = 'none'; document.body.appendChild(dummy); document.body.removeChild(dummy); // 平板设备额外的保活操作 if (CONFIG.isTablet) { // 轻微滚动页面 const currentScroll = window.pageYOffset; window.scrollTo(0, currentScroll + 1); window.scrollTo(0, currentScroll); } } catch (e) { // 忽略错误,但记录日志 log(`⚠️ 保活操作出错: ${e.message}`); } // 更新页面标题显示运行状态 if (isRunning) { const now = new Date(); const timeStr = `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`; const deviceType = CONFIG.isTablet ? '📱' : '🤖'; document.title = `${deviceType} 后台答题中... ${timeStr}`; } if (Date.now() - lastActiveTime > 30000) { lastActiveTime = Date.now(); } }, keepAliveDelay); log(`🛡️ 保活机制已启动 (间隔: ${keepAliveDelay}ms, 设备: ${CONFIG.isTablet ? '平板' : '桌面'})`); } // 停止保活机制 function stopKeepAlive() { if (keepAliveInterval) { clearInterval(keepAliveInterval); keepAliveInterval = null; } // 恢复原始标题 document.title = document.title.replace(/🤖 后台答题中.*/, '').trim() || '中安云教育'; } // 后台稳定延时函数(平板优化版) function backgroundSafeDelay(ms) { return new Promise(resolve => { const startTime = Date.now(); const minCheckInterval = CONFIG.isTablet ? 200 : 100; // 平板使用更稳定的检查间隔 log(`⏱️ 开始延时 ${ms}ms (设备: ${CONFIG.isTablet ? '平板' : '桌面'})`); const checkDelay = () => { const elapsed = Date.now() - startTime; if (elapsed >= ms) { log(`✅ 延时完成,实际用时: ${elapsed}ms`); resolve(); } else { const remaining = ms - elapsed; const nextCheck = Math.min(minCheckInterval, remaining); // 平板设备在后台时使用更可靠的延时策略 if (document.hidden || CONFIG.isTablet) { // 后台或平板设备优先使用setTimeout setTimeout(checkDelay, nextCheck); } else { // 前台桌面设备使用requestAnimationFrame if (remaining > 16) { // 超过一帧的时间才使用RAF requestAnimationFrame(checkDelay); } else { setTimeout(checkDelay, nextCheck); } } } }; // 移动设备立即启动,避免RAF的延迟 if (CONFIG.isMobile || CONFIG.isTablet) { setTimeout(checkDelay, 0); } else { checkDelay(); } }); } // 日志函数 function log(message) { const time = new Date().toLocaleTimeString(); const logMessage = `[${time}] ${message}`; console.log(logMessage); if (logContainer) { // 创建新的日志条目 const logEntry = document.createElement('div'); logEntry.style.cssText = 'margin-bottom: 5px; word-wrap: break-word; white-space: pre-wrap; line-height: 1.7; padding: 3px 0; font-size: 12px; min-height: 20px;'; logEntry.textContent = logMessage; logContainer.appendChild(logEntry); // 限制日志条目数量,避免过多影响性能 const maxLogs = 200; while (logContainer.children.length > maxLogs) { logContainer.removeChild(logContainer.firstChild); } // 强制滚动到底部,确保新内容可见 requestAnimationFrame(() => { logContainer.scrollTop = logContainer.scrollHeight; // 双重确保滚动到底部 setTimeout(() => { logContainer.scrollTop = logContainer.scrollHeight; }, 50); }); } } // 网络状态检测 function isNetworkAvailable() { return navigator.onLine; } // 网络重试机制(平板优化版) async function retryApiCall(apiFunction, maxRetries = null) { // 平板设备使用更多重试次数和更长超时 if (maxRetries === null) { maxRetries = CONFIG.isTablet ? 4 : 2; } for (let i = 0; i <= maxRetries; i++) { try { if (!isNetworkAvailable()) { log(`🌐 网络不可用,等待恢复... (第${i + 1}次重试)`); await backgroundSafeDelay(3000); continue; } log(`🔄 API调用 (第${i + 1}次尝试)`); return await apiFunction(); } catch (error) { log(`❌ API调用失败 (第${i + 1}次): ${error.message}`); if (i === maxRetries) { throw error; } const isTimeout = error.message.includes('timeout') || error.message.includes('超时'); const isNetworkError = error.message.includes('网络') || error.message.includes('network'); // 平板设备使用更长的重试延迟 let retryDelay; if (isTimeout || isNetworkError) { retryDelay = CONFIG.isTablet ? 3000 * (i + 1) : 2000 * (i + 1); } else { retryDelay = CONFIG.isTablet ? 2000 * (i + 1) : 1000 * (i + 1); } log(`⏳ ${retryDelay}ms后重试...`); await backgroundSafeDelay(retryDelay); } } } // 调用智谱应用API(使用v3接口 + 新密钥) async function callKnowledgeBaseAPI(question, options) { const query = `请回答这道低压电工题目,严格按照格式返回: 题目:${question} 选项: ${options.map((opt, i) => `${String.fromCharCode(65 + i)}. ${opt}`).join('\n')} 要求: 1. 基于低压电工专业知识选择正确答案 2. 严格按照格式:选项字母,选项原文 3. 选项原文必须与上面选项完全一致 4. 不要添加解释或额外内容 格式示例:A,正确 或 B,错误 或 C,竖放 答案:`; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'POST', url: `${CONFIG.ZHIPU_CONFIG.base_url}/v3/application/invoke`, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${CONFIG.ZHIPU_CONFIG.api_key}` }, data: JSON.stringify({ app_id: CONFIG.ZHIPU_CONFIG.application_id, stream: false, messages: [ { role: "user", content: [ { type: "input", value: query } ] } ] }), timeout: CONFIG.isTablet ? 20000 : 12000, // 优化:减少超时时间以加快失败重试 onload: function(response) { try { if (response.status !== 200) { reject(new Error(`知识库API错误: ${response.status}`)); return; } const result = JSON.parse(response.responseText); if (result.choices && result.choices[0] && result.choices[0].messages) { const messages = result.choices[0].messages; const content = messages.content; if (content && content.type === "text" && content.msg) { const answer = content.msg.trim(); stats.knowledgeHits++; resolve(answer); } else { reject(new Error('智能体响应内容格式错误')); } } else { reject(new Error(result.message || '智能体API调用失败')); } } catch (e) { reject(new Error('知识库响应解析失败: ' + e.message)); } }, onerror: function(error) { reject(new Error('知识库网络请求失败')); } }); }); } // 备用AI调用(使用v4标准API) async function callBackupAI(question, options) { const prompt = `请回答这道${options.length === 2 ? '判断' : '选择'}题,严格按照格式返回: 题目:${question} 选项: ${options.map((opt, i) => `${String.fromCharCode(65 + i)}. ${opt}`).join('\n')} 要求: 1. 选择正确答案 2. 格式:选项字母,选项原文 3. 选项原文必须与上面选项完全一致 4. 不要解释 答案:`; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'POST', url: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${CONFIG.ZHIPU_CONFIG.api_key}` }, data: JSON.stringify({ model: 'glm-4-flash', messages: [ { role: "system", content: "你是专业的低压电工,只回答选项字母和内容,不要解释。" }, { role: "user", content: prompt } ], temperature: 0.3, max_tokens: 50 }), timeout: CONFIG.isTablet ? 20000 : 12000, onload: function(response) { try { const result = JSON.parse(response.responseText); if (result.choices && result.choices[0] && result.choices[0].message) { const answer = result.choices[0].message.content.trim(); stats.aiBackup++; resolve(answer); } else if (result.error) { reject(new Error(result.error.message || '备用AI响应错误')); } else { reject(new Error('备用AI响应格式错误')); } } catch (e) { reject(new Error('备用AI解析失败: ' + e.message)); } }, onerror: () => reject(new Error('备用AI网络错误')) }); }); } // 智能获取答案 async function getSmartAnswer(question, options) { try { const knowledgeAnswer = await retryApiCall(() => callKnowledgeBaseAPI(question, options)); return knowledgeAnswer; } catch (error) { try { const aiAnswer = await retryApiCall(() => callBackupAI(question, options)); return aiAnswer; } catch (aiError) { throw new Error('所有答案获取方式都失败'); } } } // 更新时间预估 function updateTimeEstimate() { const delayInput = document.getElementById('delayInput'); const timeEstimate = document.getElementById('timeEstimate'); if (delayInput && timeEstimate) { const delaySeconds = parseInt(delayInput.value) || 3; const containers = document.querySelectorAll('.ques-type-item'); let questionCount = containers.length; // 如果还没检测到题目,使用默认值并标注 let isEstimated = false; if (questionCount === 0) { questionCount = 100; isEstimated = true; } // 计算总时间(延时 + 处理时间) const processingTimePerQuestion = 1.2; // 每题处理时间约1.2秒(优化后) const totalTimePerQuestion = delaySeconds + processingTimePerQuestion; const totalSeconds = questionCount * totalTimePerQuestion; const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; let timeText = ''; if (minutes > 0) { timeText = `${minutes}分${seconds}秒`; } else { timeText = `${totalSeconds}秒`; } const estimateText = isEstimated ? `预计完成时间: ${timeText} (预估${questionCount}题)` : `预计完成时间: ${timeText} (${questionCount}题)`; timeEstimate.textContent = estimateText; timeEstimate.style.color = isEstimated ? '#a0aec0' : '#718096'; } } // 更新继续答题按钮状态 function updateResumeButton() { const resumeBtn = document.getElementById('resumeBtn'); if (!resumeBtn) return; const hasProgress = progressManager.hasProgress(); const containers = document.querySelectorAll('.ques-type-item'); const { answeredCount } = detectAnsweredQuestions(containers); if (hasProgress || answeredCount > 0) { resumeBtn.style.display = 'block'; if (hasProgress) { const progress = progressManager.getProgress(); const savedTime = new Date(progress.timestamp).toLocaleTimeString(); resumeBtn.innerHTML = `🔄 继续答题 (第${progress.currentIndex + 1}题 ${savedTime})`; resumeBtn.title = `恢复到第${progress.currentIndex + 1}题继续答题`; } else if (answeredCount > 0) { resumeBtn.innerHTML = `🔄 继续答题 (已答${answeredCount}题)`; resumeBtn.title = `跳过已答的${answeredCount}题,继续答题`; } } else { resumeBtn.style.display = 'none'; } } // 设置全局函数(在面板创建前) function setupGlobalFunctions() { window.updateTimeEstimate = updateTimeEstimate; window.updateResumeButton = updateResumeButton; } // 自动提交试卷 async function autoSubmitExam() { try { const submitSelectors = [ 'button[type="submit"]', '.submit-btn', '.btn-submit', 'input[type="submit"]', '.exam-submit', '#submitBtn', '.btn-primary', '.submit-button', 'button[style*="background-color: rgb(24, 144, 255)"]', 'button[style*="background: rgb(24, 144, 255)"]', '.ant-btn-primary', '[class*="submit"]', '[class*="primary"]' ]; let submitBtn = null; for (const selector of submitSelectors) { try { submitBtn = document.querySelector(selector); if (submitBtn) { break; } } catch (e) { continue; } } if (!submitBtn) { const buttons = document.querySelectorAll('button, input[type="button"], a, .btn, [role="button"], div[role="button"]'); for (const btn of buttons) { const text = (btn.textContent || btn.value || btn.innerText || '').trim(); if (text === '提交试卷' || text === '提交答案' || text === '提交考试') { submitBtn = btn; break; } if (text.includes('提交') || text.includes('完成') || text.includes('结束') || text.includes('交卷') || text.includes('确认') || text.includes('保存') || text.includes('submit') || text.includes('finish') || text.includes('complete')) { submitBtn = btn; break; } } } if (!submitBtn) { const blueButtons = document.querySelectorAll('button, .btn, [style*="background"], [class*="primary"], [class*="blue"]'); for (const btn of blueButtons) { const rect = btn.getBoundingClientRect(); const isRightSide = rect.right > window.innerWidth * 0.7; const isBottomSide = rect.bottom > window.innerHeight * 0.7; if (isRightSide && isBottomSide) { const text = (btn.textContent || btn.value || '').trim(); if (text.length > 0) { submitBtn = btn; break; } } } } if (submitBtn) { await new Promise(resolve => setTimeout(resolve, 2000)); submitBtn.click(); log('🎉 试卷已自动提交'); return true; } else { return false; } } catch (error) { return false; } } // 解析答案(增强版)- 返回详细信息 function parseAnswer(answer, options = []) { const cleanAnswer = answer.trim(); // 1. 解析"字母,内容"格式(最优先) const commaMatch = cleanAnswer.match(/^([A-D])[,,]\s*(.+)$/i); if (commaMatch) { const letter = commaMatch[1].toUpperCase(); const content = commaMatch[2].trim(); // 通过内容匹配找到正确的选项索引 let bestMatch = null; let bestScore = 0; for (let i = 0; i < options.length; i++) { const option = options[i].trim(); let score = 0; // 完全匹配(最高优先级) if (option === content) { score = 1.0; } // 选项包含AI内容 else if (option.includes(content)) { score = 0.9; } // AI内容包含选项 else if (content.includes(option)) { score = 0.8; } // 相似度匹配 else { score = parseAnswer.contentSimilarity(option, content); } if (score > bestScore && score > 0.6) { bestScore = score; bestMatch = { letter: String.fromCharCode(65 + i), index: i, content: option, source: 'format_content_match', aiLetter: letter, aiContent: content, matchScore: score }; } } if (bestMatch) { return bestMatch; } // 如果内容匹配失败,尝试使用AI提供的字母(但要验证) const aiIndex = letter.charCodeAt(0) - 65; if (aiIndex >= 0 && aiIndex < options.length) { const result = { letter: letter, index: aiIndex, content: options[aiIndex], source: 'format_letter_fallback', aiContent: content }; return result; } } // 2. 直接匹配单个字母 const upperAnswer = cleanAnswer.toUpperCase(); if (/^[A-Z]$/.test(upperAnswer)) { const index = upperAnswer.charCodeAt(0) - 65; if (index >= 0 && index < options.length) { const result = { letter: upperAnswer, index: index, content: options[index], source: 'direct_letter' }; return result; } } // 3. 提取第一个字母 const letterMatch = upperAnswer.match(/[A-Z]/); if (letterMatch) { const letter = letterMatch[0]; const index = letter.charCodeAt(0) - 65; if (index >= 0 && index < options.length) { const result = { letter: letter, index: index, content: options[index], source: 'extract_letter' }; return result; } } // 4. 判断题关键词匹配 if (upperAnswer.includes('正确') || upperAnswer.includes('对') || upperAnswer.includes('TRUE')) { // 找到包含"正确"的选项 for (let i = 0; i < options.length; i++) { if (options[i].includes('正确') || options[i].includes('对')) { const result = { letter: String.fromCharCode(65 + i), index: i, content: options[i], source: 'keyword_correct' }; return result; } } } else if (upperAnswer.includes('错误') || upperAnswer.includes('错') || upperAnswer.includes('FALSE')) { // 找到包含"错误"的选项 for (let i = 0; i < options.length; i++) { if (options[i].includes('错误') || options[i].includes('错')) { const result = { letter: String.fromCharCode(65 + i), index: i, content: options[i], source: 'keyword_wrong' }; return result; } } } // 5. 选项内容关键词匹配 if (options.length > 0) { for (let i = 0; i < options.length; i++) { const option = options[i].trim(); const optionWords = option.split(/[\s,。、]/); for (const word of optionWords) { if (word.length >= 2 && upperAnswer.includes(word.toUpperCase())) { const letter = String.fromCharCode(65 + i); const result = { letter: letter, index: i, content: option, source: 'content_match' }; return result; } } } } return null; } // 内容相似度计算(简单版) parseAnswer.contentSimilarity = function(str1, str2) { const s1 = str1.toLowerCase().replace(/[^\w\u4e00-\u9fff]/g, ''); const s2 = str2.toLowerCase().replace(/[^\w\u4e00-\u9fff]/g, ''); if (s1 === s2) return 1; if (s1.includes(s2) || s2.includes(s1)) return 0.8; // 简单的字符重叠度计算 let overlap = 0; const minLen = Math.min(s1.length, s2.length); for (let i = 0; i < minLen; i++) { if (s1[i] === s2[i]) overlap++; } return overlap / Math.max(s1.length, s2.length); }; // 处理单个题目 async function processQuestion(container, index) { try { log(`📝 开始处理第${index + 1}题`); const questionEl = container.querySelector('.question-name .content p'); if (!questionEl) { log(`❌ 第${index + 1}题: 无法找到题目元素`); return false; } const question = questionEl.textContent.trim(); const optionGroups = container.querySelectorAll('.option-group'); const options = []; optionGroups.forEach(group => { const content = group.querySelector('.option-content p'); if (content) { const text = content.textContent.trim(); if (text && !options.includes(text)) { options.push(text); } } }); if (options.length === 0) { log(`❌ 第${index + 1}题: 无法找到选项`); return false; } log(`🤔 第${index + 1}题: ${question.substring(0, 30)}... (${options.length}个选项)`); const answer = await getSmartAnswer(question, options); log(`🤖 第${index + 1}题: AI回答 "${answer}"`); const parseResult = parseAnswer(answer, options); if (parseResult && parseResult.index >= 0 && parseResult.index < optionGroups.length) { log(`✅ 第${index + 1}题: 选择${parseResult.letter}选项 "${parseResult.content}" (匹配方式: ${parseResult.source})`); const targetGroup = optionGroups[parseResult.index]; const radioInput = targetGroup.querySelector('input[type="radio"]'); if (radioInput) { radioInput.checked = true; radioInput.dispatchEvent(new Event('change', { bubbles: true })); targetGroup.click(); stats.success++; log(`✅ 第${index + 1}题: 已成功选中答案`); return true; } else { log(`❌ 第${index + 1}题: 找不到单选按钮`); } } else { log(`❌ 第${index + 1}题: 无法解析答案 "${answer}"`); } stats.failed++; return false; } catch (error) { log(`❌ 第${index + 1}题: 处理出错 - ${error.message}`); stats.failed++; return false; } finally { stats.processed++; } } // 显示打赏弹窗 function showDonateModal() { // 创建遮罩层 const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 20000; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(5px); `; // 创建弹窗 const modal = document.createElement('div'); modal.style.cssText = ` background: #f0f2f5; border-radius: 20px; padding: 30px; max-width: 400px; text-align: center; box-shadow: 20px 20px 40px rgba(0,0,0,0.2), -20px -20px 40px rgba(255,255,255,0.9); position: relative; `; modal.innerHTML = `
❤️
感谢支持
如果脚本对您有帮助,请考虑打赏支持作者
赞赏码
赞赏码加载中...
图片加载失败
`; overlay.className = 'donate-overlay'; overlay.appendChild(modal); document.body.appendChild(overlay); // 绑定按钮事件 setTimeout(() => { const closeBtn = document.getElementById('closeModalBtn'); const contactBtn = document.getElementById('contactBtn'); if (closeBtn) { closeBtn.onclick = () => overlay.remove(); } if (contactBtn) { contactBtn.onclick = () => copyWechatId(contactBtn); } }, 100); // 点击遮罩关闭 overlay.onclick = (e) => { if (e.target === overlay) { overlay.remove(); } }; } // 全局函数已在setupGlobalFunctions中设置 // 检测已答题目 function detectAnsweredQuestions(containers) { let answeredCount = 0; const answeredQuestions = []; containers.forEach((container, index) => { const radioInputs = container.querySelectorAll('input[type="radio"]'); let isAnswered = false; radioInputs.forEach(radio => { if (radio.checked) { isAnswered = true; } }); if (isAnswered) { answeredCount++; answeredQuestions.push(index); } }); return { answeredCount, answeredQuestions }; } // 开始答题 function startAnswering(resumeFromIndex = 0) { if (!CONFIG.stop) return; CONFIG.stop = false; isRunning = true; // 设置运行状态 // 如果是继续答题,保留之前的统计数据 if (resumeFromIndex === 0) { stats = { total: 0, processed: 0, success: 0, failed: 0, knowledgeHits: 0, aiBackup: 0 }; } // 获取延时和自动提交设置 const delaySeconds = parseInt(document.getElementById('delayInput')?.value || 3); const delay = delaySeconds * 1000; // 转换为毫秒 CONFIG.autoSubmit = document.getElementById('autoSubmitCheck')?.checked || false; const containers = document.querySelectorAll('.ques-type-item'); stats.total = containers.length; // 检测已答题目 const { answeredCount, answeredQuestions } = detectAnsweredQuestions(containers); if (resumeFromIndex === 0) { log('🚀 开始AI智能答题'); } else { log(`🔄 继续答题 (从第${resumeFromIndex + 1}题开始)`); } log(`⚠️ 此脚本仅供学习交流使用`); log(`📱 设备类型: ${CONFIG.isTablet ? '平板设备' : CONFIG.isMobile ? '手机设备' : '桌面设备'}`); log(`📚 使用知识库: ${CONFIG.ZHIPU_CONFIG.knowledge_base_id}`); log(`🤖 使用模型: ${CONFIG.ZHIPU_CONFIG.model}`); log(`⏱️ 答题延时: ${delaySeconds}秒/题`); log(`📋 自动提交: ${CONFIG.autoSubmit ? '已启用' : '已禁用'}`); log(`📝 题目状态: 总计${containers.length}题, 已答${answeredCount}题, 剩余${containers.length - answeredCount}题`); log('🛡️ 后台运行保护已激活 (平板优化)'); // 更新状态显示 const statusElement = document.getElementById('backgroundStatus'); if (statusElement) { statusElement.textContent = document.hidden ? '🌙 后台运行中...' : '🚀 前台运行中...'; statusElement.style.color = '#38a169'; } // 计算预计完成时间(包含处理时间) const remainingQuestions = containers.length - Math.max(resumeFromIndex, answeredCount); const processingTimePerQuestion = 1.2; // 每题处理时间约1.2秒(优化后) const totalTimePerQuestion = delaySeconds + processingTimePerQuestion; const totalSeconds = remainingQuestions * totalTimePerQuestion; const minutes = Math.floor(totalSeconds / 60); const remainingSeconds = Math.round(totalSeconds % 60); const timeText = minutes > 0 ? `${minutes}分${remainingSeconds}秒` : `${totalSeconds}秒`; log(`⏰ 预计剩余时间: ${timeText} (${remainingQuestions}题)`); (async () => { const startTime = Date.now(); let actualStartIndex = resumeFromIndex; // 如果有已答题目,从最后一个已答题目的下一题开始 if (answeredCount > 0 && resumeFromIndex === 0) { actualStartIndex = Math.max(...answeredQuestions) + 1; log(`🔍 检测到已答题目,从第${actualStartIndex + 1}题开始`); } for (let i = actualStartIndex; i < containers.length && !CONFIG.stop; i++) { // 检查当前题目是否已经答过 const radioInputs = containers[i].querySelectorAll('input[type="radio"]'); let isAlreadyAnswered = false; radioInputs.forEach(radio => { if (radio.checked) { isAlreadyAnswered = true; } }); if (isAlreadyAnswered) { log(`⏭️ 第${i + 1}题已答,跳过`); stats.processed++; stats.success++; continue; } await processQuestion(containers[i], i); // 每5题保存一次进度 if ((i + 1) % 5 === 0) { progressManager.saveProgress(i, containers.length); } const progress = Math.round((i + 1) / containers.length * 100); const accuracy = stats.processed > 0 ? Math.round(stats.success / stats.processed * 100) : 0; const knowledgeRate = stats.processed > 0 ? Math.round(stats.knowledgeHits / stats.processed * 100) : 0; const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); // 平板设备每10题显示一次详细进度 if (CONFIG.isTablet && (i + 1) % 10 === 0) { log(`📊 平板进度报告: ${i + 1}/${containers.length} (${progress}%) | 准确率: ${accuracy}% | 用时: ${elapsed}s`); } if (i < containers.length - 1) { await backgroundSafeDelay(delay); } } const finalScore = Math.round(stats.success / stats.total * 100); const knowledgeUsage = Math.round(stats.knowledgeHits / stats.processed * 100); const totalTime = ((Date.now() - startTime) / 1000).toFixed(1); log(`✅ 答题完成: ${stats.success}/${stats.total} (预估${finalScore}分)`); // 清除进度记录 progressManager.clearProgress(); // 自动提交试卷 if (CONFIG.autoSubmit) { log(`\n🎯 准备自动提交试卷...`); await autoSubmitExam(); } CONFIG.stop = true; isRunning = false; // 设置停止状态 stopKeepAlive(); // 停止后台保活 })(); } // 继续答题 function resumeAnswering() { const progress = progressManager.getProgress(); if (progress) { // 恢复统计数据 stats = {...progress.stats}; log(`🔄 恢复答题进度: 第${progress.currentIndex + 1}题 (${new Date(progress.timestamp).toLocaleString()})`); startAnswering(progress.currentIndex + 1); } else { log('❌ 没有找到可恢复的进度,将从头开始'); startAnswering(0); } } // 停止答题 function stopAnswering() { CONFIG.stop = true; isRunning = false; // 设置停止状态 stopKeepAlive(); // 停止后台保活 // 更新状态显示 const statusElement = document.getElementById('backgroundStatus'); if (statusElement) { statusElement.textContent = '🛡️ 后台运行保护已就绪'; statusElement.style.color = '#4a5568'; } log('⏹️ 停止答题'); } // 创建控制面板 function createPanel() { const panel = document.createElement('div'); panel.id = 'knowledgePanel'; panel.style.cssText = ` position: fixed; top: 30px; right: 20px; width: 360px; height: auto; min-width: 300px; min-height: 450px; max-width: 600px; max-height: 95vh; background: #f0f2f5; border: none; border-radius: 20px; box-shadow: 20px 20px 40px rgba(0,0,0,0.1), -20px -20px 40px rgba(255,255,255,0.8), inset 0 0 0 1px rgba(255,255,255,0.3); z-index: 10000; font-family: 'Microsoft YaHei', Arial, sans-serif; transition: none; backdrop-filter: blur(10px); overflow-y: auto; overflow-x: hidden; `; panel.innerHTML = `
🧠
自动答题助手
AI-Powered Exam Assistant
预计完成时间: 计算中...
完成后自动提交
💬 定制脚本联系微信:C919irt
${CONFIG.isTablet ? '📱 平板设备 (已优化)' : CONFIG.isMobile ? '📱 手机设备' : '🖥️ 桌面设备'}
${CONFIG.isTablet ? '保活间隔2s | 超时25s | 重试4次' : '标准配置'}
进度
0/0
准确率
0%
答题助手已就绪...
⚠️ 此脚本仅供学习交流使用
📱 设备: ${CONFIG.isTablet ? '平板设备 (已启用优化)' : CONFIG.isMobile ? '手机设备' : '桌面设备'}
🛡️ 后台保护: ${CONFIG.isTablet ? '平板专用保活机制' : '标准机制'}
💾 进度保存: 每5题自动保存,支持断点续答
`; document.body.appendChild(panel); logContainer = document.getElementById('logArea'); // 创建最小化悬浮窗 createFloatingPet(); // 绑定事件 setTimeout(() => { const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); const resumeBtn = document.getElementById('resumeBtn'); const minimizeBtn = document.getElementById('minimizeBtn'); const closeBtn = document.getElementById('closeBtn'); const autoSubmitCheck = document.getElementById('autoSubmitCheck'); const checkboxDisplay = document.getElementById('checkboxDisplay'); if (startBtn) startBtn.onclick = () => startAnswering(0); if (stopBtn) stopBtn.onclick = stopAnswering; if (resumeBtn) resumeBtn.onclick = resumeAnswering; if (minimizeBtn) minimizeBtn.onclick = minimizePanel; if (closeBtn) closeBtn.onclick = closePanel; // 检查是否有可恢复的进度 updateResumeButton(); // 复选框交互 if (autoSubmitCheck && checkboxDisplay) { const updateCheckbox = () => { const isChecked = autoSubmitCheck.checked; const indicator = checkboxDisplay.querySelector('div'); if (indicator) { indicator.style.transform = isChecked ? 'scale(1)' : 'scale(0)'; } checkboxDisplay.style.boxShadow = isChecked ? 'inset 6px 6px 12px rgba(0,0,0,0.15), inset -6px -6px 12px rgba(255,255,255,0.9)' : 'inset 4px 4px 8px rgba(0,0,0,0.1), inset -4px -4px 8px rgba(255,255,255,0.8)'; }; autoSubmitCheck.onchange = updateCheckbox; checkboxDisplay.onclick = () => { autoSubmitCheck.checked = !autoSubmitCheck.checked; updateCheckbox(); }; // 初始状态 updateCheckbox(); } // 拖拽功能 setupDragFunctionality(); // 初始化时间预估和继续按钮状态 setTimeout(() => { updateTimeEstimate(); updateResumeButton(); setInterval(() => { updateTimeEstimate(); updateResumeButton(); }, 2000); }, 500); }, 100); // 实时更新统计 setInterval(() => { const statsArea = document.getElementById('statsArea'); const pet = document.getElementById('floatingPet'); if (statsArea && stats.total > 0) { const progress = Math.round((stats.processed / stats.total) * 100); const accuracy = stats.processed > 0 ? Math.round((stats.success / stats.processed) * 100) : 0; const knowledgeRate = stats.processed > 0 ? Math.round((stats.knowledgeHits / stats.processed) * 100) : 0; const aiRate = stats.processed > 0 ? Math.round((stats.aiBackup / stats.processed) * 100) : 0; statsArea.innerHTML = `
进度
${stats.processed}/${stats.total}
准确率
${accuracy}%
`; // 同时更新悬浮宠物状态 if (pet && pet.style.display === 'flex') { pet.className = ''; // 清除之前的状态类 if (CONFIG.stop === false && stats.processed > 0) { // 答题进行中 pet.className = 'pet-working'; pet.innerHTML = `
${progress}%
进行中
`; pet.title = `🚀 答题进行中: ${stats.processed}/${stats.total} (准确率${accuracy}%) - 点击展开面板`; } else if (stats.processed > 0) { // 答题完成 if (accuracy >= 90) { pet.className = 'pet-success'; pet.innerHTML = `
🎉
${accuracy}分
`; } else { pet.className = 'pet-warning'; pet.innerHTML = `
📊
${accuracy}分
`; } pet.title = `✅ 答题完成: ${accuracy}分 (${stats.success}/${stats.total}) - 点击展开面板`; } else { // 待机状态 pet.innerHTML = `
🧠
AI
`; pet.title = '🤖 自动答题助手 - 点击展开面板'; } } } }, 1000); } // 创建悬浮小宠物 function createFloatingPet() { const pet = document.createElement('div'); pet.id = 'floatingPet'; pet.style.cssText = ` position: fixed; top: 50px; right: 20px; width: 75px; height: 75px; background: #f0f2f5; border-radius: 50%; box-shadow: 12px 12px 24px rgba(0,0,0,0.15), -12px -12px 24px rgba(255,255,255,0.9); z-index: 10001; cursor: pointer; display: none; align-items: center; justify-content: center; font-size: 28px; color: #4a5568; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); user-select: none; animation: petFloat 4s ease-in-out infinite; border: none; `; pet.innerHTML = `
🧠
AI
`; pet.title = '自动答题助手 - 点击展开'; pet.onclick = restorePanel; // 添加悬浮动画和样式 const style = document.createElement('style'); style.textContent = ` /* 强制显示滚动条样式 */ #logArea { scrollbar-width: thin !important; scrollbar-color: #a0aec0 #f0f2f5 !important; overflow-y: scroll !important; overflow-x: hidden !important; } #logArea::-webkit-scrollbar { width: 12px !important; height: 12px !important; display: block !important; } #logArea::-webkit-scrollbar-track { background: #e2e8f0 !important; border-radius: 6px !important; box-shadow: inset 3px 3px 6px rgba(0,0,0,0.1), inset -3px -3px 6px rgba(255,255,255,0.8) !important; border: 1px solid #cbd5e0 !important; } #logArea::-webkit-scrollbar-thumb { background: linear-gradient(135deg, #a0aec0, #718096) !important; border-radius: 6px !important; box-shadow: 2px 2px 4px rgba(0,0,0,0.2), -2px -2px 4px rgba(255,255,255,0.9) !important; border: 2px solid #f0f2f5 !important; min-height: 30px !important; } #logArea::-webkit-scrollbar-thumb:hover { background: linear-gradient(135deg, #718096, #4a5568) !important; box-shadow: inset 2px 2px 4px rgba(0,0,0,0.15), inset -2px -2px 4px rgba(255,255,255,0.9) !important; } #logArea::-webkit-scrollbar-thumb:active { background: linear-gradient(135deg, #4a5568, #2d3748) !important; box-shadow: inset 3px 3px 6px rgba(0,0,0,0.2), inset -3px -3px 6px rgba(255,255,255,0.8) !important; } #logArea::-webkit-scrollbar-corner { background: #f0f2f5 !important; } @keyframes petFloat { 0%, 100% { transform: translateY(0px) rotate(0deg); box-shadow: 12px 12px 24px rgba(0,0,0,0.15), -12px -12px 24px rgba(255,255,255,0.9); } 25% { transform: translateY(-6px) rotate(1deg); box-shadow: 15px 15px 30px rgba(0,0,0,0.2), -15px -15px 30px rgba(255,255,255,0.95); } 50% { transform: translateY(-10px) rotate(0deg); box-shadow: 18px 18px 36px rgba(0,0,0,0.25), -18px -18px 36px rgba(255,255,255,1); } 75% { transform: translateY(-6px) rotate(-1deg); box-shadow: 15px 15px 30px rgba(0,0,0,0.2), -15px -15px 30px rgba(255,255,255,0.95); } } @keyframes petPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } #floatingPet:hover { transform: scale(1.1) translateY(-3px) !important; box-shadow: inset 6px 6px 12px rgba(0,0,0,0.1), inset -6px -6px 12px rgba(255,255,255,0.8) !important; animation: petPulse 1s ease-in-out infinite !important; } #floatingPet:active { transform: scale(0.95) !important; transition: all 0.1s ease !important; box-shadow: inset 8px 8px 16px rgba(0,0,0,0.15), inset -8px -8px 16px rgba(255,255,255,0.9) !important; } /* 状态指示器样式 */ .pet-working { background: #e6fffa !important; color: #38a169 !important; animation: petFloat 2s ease-in-out infinite, petPulse 1.5s ease-in-out infinite !important; box-shadow: 12px 12px 24px rgba(56, 161, 105, 0.2), -12px -12px 24px rgba(255,255,255,0.9) !important; } .pet-success { background: #ebf8ff !important; color: #3182ce !important; box-shadow: 12px 12px 24px rgba(49, 130, 206, 0.2), -12px -12px 24px rgba(255,255,255,0.9) !important; } .pet-warning { background: #fffaf0 !important; color: #ed8936 !important; box-shadow: 12px 12px 24px rgba(237, 137, 54, 0.2), -12px -12px 24px rgba(255,255,255,0.9) !important; } `; document.head.appendChild(style); document.body.appendChild(pet); } // 设置拖拽和调整大小功能 function setupDragFunctionality() { const panel = document.getElementById('knowledgePanel'); const header = document.getElementById('panelHeader'); const pet = document.getElementById('floatingPet'); let isDragging = false; let dragOffset = { x: 0, y: 0 }; // 移除调整大小控制点(用户要求取消) // addResizeHandles(panel); // 面板拖拽 if (header) { header.onmousedown = (e) => { // 如果点击的是按钮,不触发拖拽 if (e.target.id === 'minimizeBtn' || e.target.id === 'closeBtn') { return; } isDragging = true; dragOffset.x = e.clientX - panel.offsetLeft; dragOffset.y = e.clientY - panel.offsetTop; header.style.cursor = 'grabbing'; document.body.style.userSelect = 'none'; // 防止选中文本 e.preventDefault(); }; } // 悬浮宠物拖拽 if (pet) { pet.onmousedown = (e) => { if (e.detail === 1) { // 单击时不拖拽,双击时拖拽 setTimeout(() => { if (e.detail === 1) return; // 如果是单击就返回 isDragging = true; dragOffset.x = e.clientX - pet.offsetLeft; dragOffset.y = e.clientY - pet.offsetTop; pet.style.cursor = 'grabbing'; document.body.style.userSelect = 'none'; e.preventDefault(); e.stopPropagation(); }, 200); } }; } // 优化的鼠标移动事件(使用requestAnimationFrame) let animationId = null; document.onmousemove = (e) => { if (isDragging) { if (animationId) { cancelAnimationFrame(animationId); } animationId = requestAnimationFrame(() => { if (isDragging) { const activeElement = panel.style.display !== 'none' ? panel : pet; if (activeElement) { const newX = e.clientX - dragOffset.x; const newY = e.clientY - dragOffset.y; // 限制在屏幕范围内 const maxX = window.innerWidth - activeElement.offsetWidth; const maxY = window.innerHeight - activeElement.offsetHeight; activeElement.style.left = Math.max(0, Math.min(newX, maxX)) + 'px'; activeElement.style.top = Math.max(0, Math.min(newY, maxY)) + 'px'; activeElement.style.right = 'auto'; activeElement.style.bottom = 'auto'; } } }); } }; // 全局鼠标释放事件 document.onmouseup = () => { if (isDragging) { isDragging = false; if (header) header.style.cursor = 'move'; if (pet) pet.style.cursor = 'pointer'; document.body.style.userSelect = ''; } if (animationId) { cancelAnimationFrame(animationId); animationId = null; } }; } // 最小化面板 function minimizePanel() { const panel = document.getElementById('knowledgePanel'); const pet = document.getElementById('floatingPet'); if (panel && pet) { panel.style.display = 'none'; pet.style.display = 'flex'; // 悬浮宠物显示状态 if (stats.processed > 0) { const accuracy = Math.round((stats.success / stats.processed) * 100); pet.innerHTML = `${accuracy}%`; pet.title = `答题进度: ${stats.processed}/${stats.total} (${accuracy}%) - 点击展开`; } else { pet.innerHTML = '📚'; pet.title = '自动答题助手 - 点击展开'; } log('📱 已最小化为悬浮小宠物'); } } // 恢复面板 function restorePanel() { const panel = document.getElementById('knowledgePanel'); const pet = document.getElementById('floatingPet'); if (panel && pet) { panel.style.display = 'block'; pet.style.display = 'none'; log('📱 已恢复面板显示'); } } // 关闭面板 function closePanel() { const panel = document.getElementById('knowledgePanel'); const pet = document.getElementById('floatingPet'); if (confirm('确定要关闭自动答题助手吗?')) { if (panel) panel.remove(); if (pet) pet.remove(); // 停止答题 CONFIG.stop = true; log('❌ 答题助手已关闭'); console.log('📚 自动答题助手已关闭'); } } // 初始化 function init() { if (!location.href.includes('txsyaqpx.zhongancloud.com')) { return; } const checkReady = () => { if (document.querySelector('.ques-type-item')) { setupGlobalFunctions(); setupBackgroundKeepAlive(); createPanel(); } else { setTimeout(checkReady, 1000); } }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', checkReady); } else { setTimeout(checkReady, 1000); } } // 启动 init(); })();