// ==UserScript== // @name 柠檬文才学堂全功能助手 // @namespace http://tampermonkey.net/ // @version 3.0 // @description 考试自动答题 + 答案提取 + 题库管理 // @author Your Name // @match *://*.wencaischool.net/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_notification // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant unsafeWindow // @require https://code.jquery.com/jquery-3.6.0.min.js // @run-at document-idle // ==/UserScript== (function() { 'use strict'; // 全局配置 const CONFIG = { debug: true, autoDetectPageType: true, autoStart: true, showControlPanel: true, bypassSecurity: true, saveAnswers: true, questionBankKey: 'lemonysoft_question_bank', answerHistoryKey: 'lemonysoft_answer_history' }; // 页面类型检测 const PageType = { UNKNOWN: 0, EXAM: 1, // 考试界面 REVIEW: 2, // 试卷回顾 LIST: 3, // 考试列表 LOGIN: 4 // 登录页面 }; // 主控制器 class LemonysoftHelper { constructor() { this.pageType = PageType.UNKNOWN; this.examHelper = null; this.answerExtractor = null; this.questionBank = null; this.controlPanel = null; this.isInitialized = false; this.init(); } init() { console.log('🍋 柠檬文才学堂助手启动'); // 检测页面类型 this.detectPageType(); // 加载题库 this.loadQuestionBank(); // 根据页面类型初始化相应功能 this.initializeForPageType(); // 添加控制面板 if (CONFIG.showControlPanel) { this.addControlPanel(); } // 添加全局快捷键 this.addKeyboardShortcuts(); this.isInitialized = true; this.log(`页面类型: ${this.getPageTypeName()}`, 'success'); } // 检测页面类型 detectPageType() { const url = window.location.href; const html = document.body.innerHTML; // 考试界面特征 const isExamPage = ( url.includes('online-exam/exam') || url.includes('oe-web/online-exam/exam') || html.includes('正在答题') || html.includes('在线考试') || html.includes('tblItem_') || html.includes('lemonysoft_item_') ) && !html.includes('参考答案:'); // 试卷回顾特征 const isReviewPage = ( url.includes('review') || url.includes('查看考卷') || html.includes('参考答案:') || html.includes('当前得分:') || html.includes('得分: { this.examHelper.extractQuestions(); this.examHelper.autoFillAnswers(); }, 2000); } } // 初始化答案提取器 initAnswerExtractor() { if (this.answerExtractor) return; this.log('初始化答案提取器...'); this.answerExtractor = new AnswerExtractor(this); // 自动提取答案 if (CONFIG.autoStart) { setTimeout(() => { this.answerExtractor.extractAllAnswers(); }, 1500); } } // 初始化考试列表助手 initExamListHelper() { this.log('检测到考试列表页面'); // 可以在这里添加自动跳转、批量处理等功能 } // 初始化登录助手 initLoginHelper() { this.log('检测到登录页面'); // 可以在这里添加自动登录、密码保存等功能 } // 恢复键盘功能(绕过安全限制) restoreKeyboard() { this.log('恢复键盘功能...'); // 解除键盘限制 document.onkeydown = null; document.onkeyup = null; document.onkeypress = null; // 解除复制限制 document.onselectstart = null; document.oncopy = null; document.oncut = null; document.onpaste = null; // 恢复所有元素的复制功能 document.querySelectorAll('*').forEach(element => { element.onselectstart = null; element.oncopy = null; element.oncut = null; element.onpaste = null; }); // 添加CSS样式解除选择限制 GM_addStyle(` * { user-select: text !important; -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; } input, textarea, select { user-select: auto !important; } `); } // 加载题库 loadQuestionBank() { try { const saved = GM_getValue(CONFIG.questionBankKey); if (saved) { this.questionBank = JSON.parse(saved); this.log(`题库已加载: ${this.questionBank.questions?.length || 0} 道题目`); return this.questionBank; } } catch (error) { this.log('加载题库失败', 'error'); } // 如果不存在,初始化空题库 this.questionBank = { platform: 'lemonysoft', course: '', examName: '', examId: '', totalQuestions: 0, totalScore: 0, createdDate: new Date().toISOString(), updatedDate: new Date().toISOString(), questions: [] }; return this.questionBank; } // 保存题库 saveQuestionBank() { try { this.questionBank.updatedDate = new Date().toISOString(); GM_setValue(CONFIG.questionBankKey, JSON.stringify(this.questionBank)); this.log(`题库已保存: ${this.questionBank.questions.length} 道题目`, 'success'); return true; } catch (error) { this.log(`保存题库失败: ${error.message}`, 'error'); return false; } } // 合并题库 mergeQuestionBank(newQuestions) { if (!newQuestions || !Array.isArray(newQuestions)) return; let addedCount = 0; let updatedCount = 0; newQuestions.forEach(newQuestion => { // 查找是否已存在相同题目 const existingIndex = this.questionBank.questions.findIndex(q => q.text === newQuestion.text || q.id === newQuestion.id ); if (existingIndex === -1) { // 添加新题目 this.questionBank.questions.push(newQuestion); addedCount++; } else { // 更新现有题目 this.questionBank.questions[existingIndex] = { ...this.questionBank.questions[existingIndex], ...newQuestion, updated: new Date().toISOString() }; updatedCount++; } }); this.questionBank.totalQuestions = this.questionBank.questions.length; if (addedCount > 0 || updatedCount > 0) { this.saveQuestionBank(); this.log(`题库合并完成: 新增 ${addedCount} 题, 更新 ${updatedCount} 题`, 'success'); } return { added: addedCount, updated: updatedCount }; } // 搜索题目 searchQuestion(keyword) { if (!keyword || !this.questionBank.questions.length) return []; keyword = keyword.toLowerCase(); return this.questionBank.questions.filter(question => question.text.toLowerCase().includes(keyword) || (question.options && question.options.some(opt => opt.text.toLowerCase().includes(keyword) )) ); } // 获取题目答案 getQuestionAnswer(questionText) { if (!questionText || !this.questionBank.questions.length) return null; const question = this.questionBank.questions.find(q => q.text.includes(questionText) || questionText.includes(q.text) ); return question ? question.answer : null; } // 添加控制面板 addControlPanel() { if (this.controlPanel) return; const panel = document.createElement('div'); panel.id = 'lemonysoft-helper-panel'; panel.innerHTML = `
🍋 柠檬助手 ${this.getPageTypeName()}
📊 状态信息
加载中...
🎯 功能操作
🔍 题库搜索
⚙️ 设置
`; document.body.appendChild(panel); this.controlPanel = panel; // 添加事件监听 this.setupPanelEvents(); // 根据页面类型更新按钮 this.updatePanelButtons(); // 初始化面板拖动 this.initPanelDrag(); this.log('控制面板已添加'); } // 设置面板事件 setupPanelEvents() { const panel = this.controlPanel; // 关闭按钮 panel.querySelector('#close-panel').addEventListener('click', () => { panel.style.display = 'none'; }); // 搜索功能 const searchInput = panel.querySelector('#search-input'); const searchResults = panel.querySelector('#search-results'); searchInput.addEventListener('input', (e) => { const keyword = e.target.value.trim(); if (keyword.length < 2) { searchResults.innerHTML = ''; return; } const results = this.searchQuestion(keyword); if (results.length > 0) { let html = ''; results.slice(0, 10).forEach(question => { html += `
${question.index || ''}题: ${question.text.substring(0, 50)}...
答案: ${question.answer}
`; }); searchResults.innerHTML = html; } else { searchResults.innerHTML = '
未找到相关题目
'; } }); // 设置按钮 panel.querySelector('#btn-settings').addEventListener('click', () => { this.showSettingsDialog(); }); // 帮助按钮 panel.querySelector('#btn-help').addEventListener('click', () => { this.showHelpDialog(); }); // 双击标题栏最小化 panel.querySelector('#panel-header').addEventListener('dblclick', () => { const body = panel.querySelector('.panel-body'); body.style.display = body.style.display === 'none' ? 'block' : 'none'; }); } // 更新面板按钮(根据页面类型) updatePanelButtons() { const buttonContainer = this.controlPanel.querySelector('#function-buttons'); let buttons = ''; switch (this.pageType) { case PageType.EXAM: buttons = `
`; break; case PageType.REVIEW: buttons = `
`; break; default: buttons = ` `; } buttonContainer.innerHTML = buttons; // 重新绑定事件 this.bindFunctionButtons(); } // 绑定功能按钮事件 bindFunctionButtons() { const panel = this.controlPanel; // 考试界面按钮 if (this.pageType === PageType.EXAM) { if (panel.querySelector('#btn-extract')) { panel.querySelector('#btn-extract').addEventListener('click', () => { if (this.examHelper) { this.examHelper.extractQuestions(); } }); } if (panel.querySelector('#btn-auto-answer')) { panel.querySelector('#btn-auto-answer').addEventListener('click', () => { if (this.examHelper) { this.examHelper.autoFillAnswers(); } }); } if (panel.querySelector('#btn-bypass')) { panel.querySelector('#btn-bypass').addEventListener('click', () => { this.restoreKeyboard(); this.showNotification('安全限制已解除', '键盘和复制功能已恢复'); }); } if (panel.querySelector('#btn-search-answer')) { panel.querySelector('#btn-search-answer').addEventListener('click', () => { this.showSearchDialog(); }); } if (panel.querySelector('#btn-submit')) { panel.querySelector('#btn-submit').addEventListener('click', () => { if (this.examHelper) { this.examHelper.submitExam(); } }); } } // 回顾界面按钮 if (this.pageType === PageType.REVIEW) { if (panel.querySelector('#btn-extract-answers')) { panel.querySelector('#btn-extract-answers').addEventListener('click', () => { if (this.answerExtractor) { this.answerExtractor.extractAllAnswers(); } }); } if (panel.querySelector('#btn-save-bank')) { panel.querySelector('#btn-save-bank').addEventListener('click', () => { this.saveQuestionBank(); }); } if (panel.querySelector('#btn-export-json')) { panel.querySelector('#btn-export-json').addEventListener('click', () => { this.exportQuestionBank('json'); }); } if (panel.querySelector('#btn-export-csv')) { panel.querySelector('#btn-export-csv').addEventListener('click', () => { this.exportQuestionBank('csv'); }); } if (panel.querySelector('#btn-merge-bank')) { panel.querySelector('#btn-merge-bank').addEventListener('click', () => { this.mergeQuestionBank(this.answerExtractor?.questionBank?.questions || []); }); } } // 通用按钮 if (panel.querySelector('#btn-general-help')) { panel.querySelector('#btn-general-help').addEventListener('click', () => { this.showHelpDialog(); }); } if (panel.querySelector('#btn-manage-bank')) { panel.querySelector('#btn-manage-bank').addEventListener('click', () => { this.showQuestionBankManager(); }); } } // 初始化面板拖动 initPanelDrag() { const panel = this.controlPanel; const header = panel.querySelector('#panel-header'); let isDragging = false; let offsetX, offsetY; header.addEventListener('mousedown', startDrag); function startDrag(e) { if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT') return; isDragging = true; offsetX = e.clientX - panel.offsetLeft; offsetY = e.clientY - panel.offsetTop; document.addEventListener('mousemove', drag); document.addEventListener('mouseup', stopDrag); panel.style.cursor = 'move'; } function drag(e) { if (!isDragging) return; const x = e.clientX - offsetX; const y = e.clientY - offsetY; // 限制在窗口范围内 const maxX = window.innerWidth - panel.offsetWidth; const maxY = window.innerHeight - panel.offsetHeight; panel.style.left = Math.max(0, Math.min(x, maxX)) + 'px'; panel.style.top = Math.max(0, Math.min(y, maxY)) + 'px'; panel.style.right = 'auto'; } function stopDrag() { isDragging = false; document.removeEventListener('mousemove', drag); document.removeEventListener('mouseup', stopDrag); panel.style.cursor = 'default'; } } // 更新状态显示 updateStatus() { const statusElement = this.controlPanel?.querySelector('#status-display'); if (!statusElement) return; let statusHtml = ''; switch (this.pageType) { case PageType.EXAM: const examStats = this.examHelper?.getStats() || { total: 0, answered: 0 }; statusHtml = `
题目总数: ${examStats.total}
已答题目: ${examStats.answered}
答题进度: ${examStats.total ? Math.round(examStats.answered/examStats.total*100) : 0}%
`; // 更新进度条 const progressBar = this.controlPanel.querySelector('#progress-fill'); if (progressBar && examStats.total > 0) { progressBar.style.width = `${examStats.answered/examStats.total*100}%`; } break; case PageType.REVIEW: const extractStats = this.answerExtractor?.getStats() || { total: 0, extracted: 0 }; statusHtml = `
提取题目: ${extractStats.extracted}/${extractStats.total}
题库总数: ${this.questionBank.questions.length}
最后更新: ${new Date(this.questionBank.updatedDate).toLocaleDateString()}
`; break; default: statusHtml = `
题库总数: ${this.questionBank.questions.length}
页面类型: ${this.getPageTypeName()}
`; } statusElement.innerHTML = statusHtml; } // 显示设置对话框 showSettingsDialog() { // 创建设置对话框 const dialog = document.createElement('div'); dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border: 2px solid #3498db; border-radius: 10px; padding: 20px; z-index: 100000; min-width: 300px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); `; dialog.innerHTML = `

⚙️ 助手设置

`; document.body.appendChild(dialog); // 添加事件监听 dialog.querySelector('#settings-save').addEventListener('click', () => { CONFIG.debug = dialog.querySelector('#setting-debug').checked; CONFIG.autoStart = dialog.querySelector('#setting-auto-start').checked; CONFIG.bypassSecurity = dialog.querySelector('#setting-bypass').checked; CONFIG.saveAnswers = dialog.querySelector('#setting-save-answers').checked; this.log('设置已保存', 'success'); dialog.remove(); }); dialog.querySelector('#settings-cancel').addEventListener('click', () => { dialog.remove(); }); // 点击背景关闭 dialog.addEventListener('click', (e) => { if (e.target === dialog) { dialog.remove(); } }); } // 显示帮助对话框 showHelpDialog() { const helpText = `

🍋 柠檬文才学堂助手使用说明

📝 主要功能: 🎯 使用方法:
  1. 在考试界面点击"自动答题"开始自动填写答案
  2. 在回顾界面点击"提取答案"保存正确答案到题库
  3. 使用搜索框查找题库中的题目和答案
  4. 导出题库数据用于复习或备份
⚠️ 注意事项: 📱 快捷键: `; const dialog = document.createElement('div'); dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border: 2px solid #3498db; border-radius: 10px; padding: 20px; z-index: 100000; max-width: 500px; max-height: 80vh; overflow-y: auto; box-shadow: 0 10px 30px rgba(0,0,0,0.3); `; dialog.innerHTML = helpText + `
`; document.body.appendChild(dialog); dialog.querySelector('#help-close').addEventListener('click', () => { dialog.remove(); }); // 点击背景关闭 dialog.addEventListener('click', (e) => { if (e.target === dialog) { dialog.remove(); } }); } // 显示搜索对话框 showSearchDialog() { const dialog = document.createElement('div'); dialog.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border: 2px solid #3498db; border-radius: 10px; padding: 20px; z-index: 100000; width: 400px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); `; dialog.innerHTML = `

🔍 题库搜索

`; document.body.appendChild(dialog); const searchInput = dialog.querySelector('#dialog-search'); const resultsDiv = dialog.querySelector('#dialog-results'); searchInput.focus(); searchInput.addEventListener('input', (e) => { const keyword = e.target.value.trim(); if (keyword.length < 2) { resultsDiv.innerHTML = '
请输入至少2个字符
'; return; } const results = this.searchQuestion(keyword); if (results.length > 0) { let html = ''; results.slice(0, 20).forEach(question => { html += `
${question.text.substring(0, 80)}...
答案: ${question.answer}
${question.score ? `
分值: ${question.score}
` : ''}
`; }); resultsDiv.innerHTML = html; } else { resultsDiv.innerHTML = '
未找到相关题目
'; } }); dialog.querySelector('#search-close').addEventListener('click', () => { dialog.remove(); }); // 点击背景关闭 dialog.addEventListener('click', (e) => { if (e.target === dialog) { dialog.remove(); } }); } // 显示题库管理器 showQuestionBankManager() { // 这里可以添加更复杂的题库管理功能 this.showNotification('题库管理', `当前题库共有 ${this.questionBank.questions.length} 道题目`); } // 导出题库 exportQuestionBank(format) { let content = ''; let filename = ''; switch (format) { case 'json': content = JSON.stringify(this.questionBank, null, 2); filename = `题库_${this.questionBank.examName || '未命名'}_${Date.now()}.json`; break; case 'csv': content = this.convertToCSV(); filename = `题库_${this.questionBank.examName || '未命名'}_${Date.now()}.csv`; break; } // 下载文件 this.downloadFile(content, filename, format === 'json' ? 'application/json' : 'text/csv'); this.log(`题库已导出为 ${format.toUpperCase()} 格式`, 'success'); } // 转换为CSV格式 convertToCSV() { let csv = '序号,题型,题目,答案,分值\n'; this.questionBank.questions.forEach(question => { const row = [ question.index || '', question.type === 'single-choice' ? '单选题' : '多选题', `"${(question.text || '').replace(/"/g, '""')}"`, question.answer || '', question.score || '' ].join(','); csv += row + '\n'; }); return csv; } // 下载文件 downloadFile(content, filename, mimeType = 'text/plain') { const blob = new Blob([content], { type: `${mimeType};charset=utf-8` }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; link.style.display = 'none'; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } // 添加全局快捷键 addKeyboardShortcuts() { document.addEventListener('keydown', (e) => { // Ctrl+Shift+L: 显示/隐藏控制面板 if (e.ctrlKey && e.shiftKey && e.key === 'L') { e.preventDefault(); if (this.controlPanel) { this.controlPanel.style.display = this.controlPanel.style.display === 'none' ? 'block' : 'none'; } } // Ctrl+Shift+A: 自动答题(考试界面) if (e.ctrlKey && e.shiftKey && e.key === 'A') { e.preventDefault(); if (this.pageType === PageType.EXAM && this.examHelper) { this.examHelper.autoFillAnswers(); } } // Ctrl+Shift+S: 搜索题目 if (e.ctrlKey && e.shiftKey && e.key === 'S') { e.preventDefault(); this.showSearchDialog(); } }); } // 显示通知 showNotification(title, message, type = 'info') { if (typeof GM_notification === 'function') { GM_notification({ title: title, text: message, timeout: 3000 }); } else { // 使用自定义通知 const notification = document.createElement('div'); notification.style.cssText = ` position: fixed; top: 20px; right: 20px; background: ${type === 'success' ? '#27ae60' : type === 'error' ? '#e74c3c' : '#3498db'}; color: white; padding: 12px 20px; border-radius: 6px; z-index: 100000; box-shadow: 0 4px 12px rgba(0,0,0,0.2); max-width: 300px; animation: slideIn 0.3s ease; `; // 添加CSS动画 if (!document.querySelector('#notification-style')) { const style = document.createElement('style'); style.id = 'notification-style'; style.textContent = ` @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } `; document.head.appendChild(style); } notification.innerHTML = `${title}
${message}`; document.body.appendChild(notification); setTimeout(() => { notification.style.opacity = '0'; notification.style.transform = 'translateX(100%)'; setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 300); }, 3000); } } // 日志函数 log(message, level = 'info', data = null) { if (!CONFIG.debug) return; const timestamp = new Date().toLocaleTimeString(); const prefix = `[LemonyHelper ${timestamp}]`; switch (level) { case 'error': console.error(prefix, message, data || ''); break; case 'warn': console.warn(prefix, message, data || ''); break; case 'success': console.log(`%c${prefix} ${message}`, 'color: #27ae60', data || ''); break; default: console.log(prefix, message, data || ''); } } } // ==================== 考试助手模块 ==================== class ExamHelper { constructor(main) { this.main = main; this.questions = []; this.answers = {}; this.examData = { id: '', name: '', courseId: '', totalQuestions: 0, answeredQuestions: 0 }; this.init(); } init() { this.log('考试助手初始化'); // 提取考试信息 this.extractExamInfo(); // 监听页面变化 this.setupObservers(); } // 提取考试信息 extractExamInfo() { // 从URL提取考试ID const urlParams = new URLSearchParams(window.location.search); this.examData.id = urlParams.get('exam_id') || ''; // 从页面提取考试名称 const titleElements = document.querySelectorAll('div.fnt_lrg_b, h1, h2'); titleElements.forEach(el => { if (el.textContent && el.textContent.trim()) { this.examData.name = el.textContent.trim(); } }); this.log(`考试信息: ${this.examData.name} (ID: ${this.examData.id})`); } // 提取所有题目 extractQuestions() { this.questions = []; // 方法1: 从表格中提取 const questionTables = document.querySelectorAll('table[id^="tblItem_"]'); questionTables.forEach((table, index) => { if (table.getAttribute('IsLabel') !== '1') { const question = this.parseQuestionTable(table, index); if (question) { this.questions.push(question); } } }); // 方法2: 从题目ID数组中提取(如果存在) if (typeof aItemId !== 'undefined' && Array.isArray(aItemId)) { aItemId.forEach((itemId, index) => { if (itemId) { const table = document.getElementById(`tblItem_${itemId}`); if (table && table.getAttribute('IsLabel') !== '1') { const question = this.parseQuestionTable(table, index); if (question && !this.questions.find(q => q.id === itemId)) { this.questions.push(question); } } } }); } this.examData.totalQuestions = this.questions.length; this.log(`提取了 ${this.questions.length} 道题目`); // 更新主控状态 this.main.updateStatus(); return this.questions; } // 解析题目表格 parseQuestionTable(table, index) { try { const questionId = table.id.replace('tblItem_', ''); const keyList = table.getAttribute('KeyList'); const keys = keyList ? keyList.split(',') : []; // 提取题目内容 let questionText = ''; const textElements = table.querySelectorAll('td'); textElements.forEach(td => { const text = td.textContent?.trim(); if (text && text.length > 10 && !questionText) { questionText = text; } }); // 提取选项 const options = []; keys.forEach(key => { const inputs = document.querySelectorAll(`input[name="${key}"]`); inputs.forEach((input, optIndex) => { const label = document.querySelector(`label[for="${input.id}"]`); const optionText = label ? label.textContent.trim() : `选项${String.fromCharCode(65 + optIndex)}`; options.push({ id: input.id, name: input.name, value: input.value, type: input.type, text: optionText, element: input }); }); }); // 判断题型 let questionType = 'unknown'; if (options.length > 0) { questionType = options[0].type === 'radio' ? 'single-choice' : 'multi-choice'; } const question = { id: questionId, index: index + 1, type: questionType, text: questionText, options: options, answer: null, keyList: keys, table: table }; return question; } catch (error) { this.log(`解析题目失败: ${error.message}`, 'error'); return null; } } // 自动填写答案 async autoFillAnswers() { if (this.questions.length === 0) { this.extractQuestions(); } this.log('开始自动答题...'); // 从题库中查找答案 this.questions.forEach(question => { const answer = this.findAnswerFromBank(question); if (answer) { this.fillAnswer(question, answer); this.answers[question.id] = answer; } }); this.examData.answeredQuestions = Object.keys(this.answers).length; this.main.updateStatus(); this.log(`自动答题完成: ${this.examData.answeredQuestions}/${this.examData.totalQuestions}`); // 显示进度通知 if (this.examData.answeredQuestions > 0) { this.main.showNotification('自动答题完成', `已填写 ${this.examData.answeredQuestions}/${this.examData.totalQuestions} 题`); } } // 从题库查找答案 findAnswerFromBank(question) { if (!this.main.questionBank.questions.length) return null; // 使用题目文本查找 const matchedQuestions = this.main.searchQuestion(question.text.substring(0, 50)); if (matchedQuestions.length > 0) { return matchedQuestions[0].answer; } // 如果没有找到,尝试智能推测(简单的规则) return this.smartGuessAnswer(question); } // 智能推测答案(简单规则) smartGuessAnswer(question) { // 这里可以添加一些简单的答题规则 // 例如:如果题目包含"错误"、"不正确"等词,选择看起来最不可能的选项 const text = question.text.toLowerCase(); if (question.type === 'single-choice') { // 单选题:默认选择C return 'C'; } else if (question.type === 'multi-choice') { // 多选题:默认选择AB return 'AB'; } return null; } // 填写答案 fillAnswer(question, answer) { if (!answer || !question.options.length) return; const answerValues = answer.split(''); question.options.forEach(option => { if (answerValues.includes(option.value)) { this.selectOption(option.element); } }); this.log(`第${question.index}题: 选择 ${answer}`); } // 选择选项 selectOption(element) { try { element.checked = true; // 触发事件 const changeEvent = new Event('change', { bubbles: true }); element.dispatchEvent(changeEvent); const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); element.dispatchEvent(clickEvent); return true; } catch (error) { this.log(`选择选项失败: ${error.message}`, 'error'); return false; } } // 提交考试 submitExam() { this.log('准备提交考试...'); try { // 检查是否有提交函数 if (typeof doSubmit === 'function') { doSubmit(false); this.main.showNotification('考试提交', '正在提交考试...'); } else if (typeof submitDo === 'function') { submitDo(false); this.main.showNotification('考试提交', '正在提交考试...'); } else { // 查找提交按钮 const submitButtons = document.querySelectorAll('input[type="button"], button'); submitButtons.forEach(button => { if (button.value.includes('提交') || button.textContent.includes('提交')) { button.click(); this.main.showNotification('考试提交', '已点击提交按钮'); } }); } } catch (error) { this.log(`提交考试失败: ${error.message}`, 'error'); } } // 获取统计信息 getStats() { return { total: this.examData.totalQuestions, answered: this.examData.answeredQuestions, progress: this.examData.totalQuestions ? Math.round(this.examData.answeredQuestions/this.examData.totalQuestions*100) : 0 }; } // 设置页面变化监听 setupObservers() { const observer = new MutationObserver(() => { // 检查是否有新题目加载 const currentCount = document.querySelectorAll('table[id^="tblItem_"]').length; if (currentCount > this.questions.length) { this.log('检测到新题目,重新提取...'); setTimeout(() => this.extractQuestions(), 1000); } }); observer.observe(document.body, { childList: true, subtree: true }); } log(message, level = 'info') { this.main.log(`[ExamHelper] ${message}`, level); } } // ==================== 答案提取器模块 ==================== class AnswerExtractor { constructor(main) { this.main = main; this.questionBank = { questions: [], extractedCount: 0 }; this.init(); } init() { this.log('答案提取器初始化'); } // 提取所有答案 extractAllAnswers() { this.questionBank.questions = []; this.questionBank.extractedCount = 0; // 从页面提取题目和答案 this.extractFromPage(); // 更新统计信息 this.main.updateStatus(); this.log(`答案提取完成: ${this.questionBank.questions.length} 道题目`); if (this.questionBank.questions.length > 0) { this.main.showNotification('答案提取', `成功提取 ${this.questionBank.questions.length} 道题目`); } return this.questionBank.questions; } // 从页面提取 extractFromPage() { // 方法1: 查找所有参考答案 const answerElements = document.querySelectorAll('div[style*="color:darkred"]'); answerElements.forEach((element, index) => { const question = this.extractQuestionFromElement(element, index); if (question) { this.questionBank.questions.push(question); this.questionBank.extractedCount++; } }); // 方法2: 从题目行提取 if (this.questionBank.questions.length === 0) { const questionRows = document.querySelectorAll('tr[id^="trScore_"]'); questionRows.forEach((row, index) => { const question = this.extractQuestionFromRow(row, index); if (question) { this.questionBank.questions.push(question); this.questionBank.extractedCount++; } }); } } // 从元素提取题目 extractQuestionFromElement(element, index) { try { const text = element.textContent || ''; // 提取答案 const answerMatch = text.match(/参考答案:([A-Z]+)/); if (!answerMatch) return null; const answer = answerMatch[1]; // 提取分值 const scoreMatch = text.match(/分值:(\d+)/); const score = scoreMatch ? parseInt(scoreMatch[1]) : 4; // 查找题目文本 let questionText = ''; let parent = element.parentElement; for (let i = 0; i < 5; i++) { if (!parent) break; // 查找前面的文本节点 const walker = document.createTreeWalker( parent, NodeFilter.SHOW_TEXT, null, false ); let node; let texts = []; while (node = walker.nextNode()) { if (node.textContent.trim().length > 20) { texts.push(node.textContent.trim()); } } if (texts.length > 0) { questionText = texts[texts.length - 1]; break; } parent = parent.previousElementSibling || parent.parentElement; } // 清理题目文本 questionText = this.cleanQuestionText(questionText); // 判断题型 const questionType = answer.length > 1 ? 'multi-choice' : 'single-choice'; return { index: index + 1, text: questionText, answer: answer, type: questionType, score: score, source: 'element-extraction' }; } catch (error) { this.log(`提取题目失败: ${error.message}`, 'error'); return null; } } // 从行提取题目 extractQuestionFromRow(row, index) { try { const cells = row.querySelectorAll('td'); if (cells.length < 2) return null; // 提取题目内容 let questionText = ''; const contentCell = cells[1]; // 查找题目文本 const textElements = contentCell.querySelectorAll('table td'); textElements.forEach(td => { const text = td.textContent?.trim(); if (text && text.length > 20 && !questionText) { questionText = text; } }); // 提取答案 let answer = ''; const answerDiv = contentCell.querySelector('div[style*="color:darkred"]'); if (answerDiv) { const answerMatch = answerDiv.textContent.match(/参考答案:([A-Z]+)/); if (answerMatch) { answer = answerMatch[1]; } } if (!answer) return null; // 提取分值 let score = 4; if (answerDiv) { const scoreMatch = answerDiv.textContent.match(/分值:(\d+)/); if (scoreMatch) { score = parseInt(scoreMatch[1]); } } // 清理题目文本 questionText = this.cleanQuestionText(questionText); // 判断题型 const questionType = answer.length > 1 ? 'multi-choice' : 'single-choice'; return { index: index + 1, text: questionText, answer: answer, type: questionType, score: score, source: 'row-extraction' }; } catch (error) { this.log(`提取题目行失败: ${error.message}`, 'error'); return null; } } // 清理题目文本 cleanQuestionText(text) { if (!text) return ''; // 移除多余空格和换行 text = text.replace(/\s+/g, ' ').trim(); // 移除题号 text = text.replace(/^\d+[\.、]/, '').trim(); // 移除括号中的内容 text = text.replace(/\(.*?\)/g, '').trim(); return text; } // 获取统计信息 getStats() { return { total: this.questionBank.questions.length, extracted: this.questionBank.extractedCount }; } log(message, level = 'info') { this.main.log(`[AnswerExtractor] ${message}`, level); } } // ==================== 主启动函数 ==================== function startLemonysoftHelper() { // 等待页面加载完成 const checkReady = () => { if (document.readyState === 'complete') { // 延迟启动,确保页面完全加载 setTimeout(() => { // 检查是否已经存在实例 if (!window.lemonysoftHelper) { window.lemonysoftHelper = new LemonysoftHelper(); // 定期更新状态 setInterval(() => { if (window.lemonysoftHelper && window.lemonysoftHelper.controlPanel) { window.lemonysoftHelper.updateStatus(); } }, 2000); } }, 1500); } else { setTimeout(checkReady, 500); } }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', checkReady); } else { checkReady(); } } // 启动助手 startLemonysoftHelper(); })();