// ==UserScript== // @name 贤程教育——广东创新自动答题 // @namespace http://tampermonkey.net/ // @version 2.3 // @description 自动选择正确答案、提交并处理章节练习及综合测评 // @author ChatGPT & Developer // @match https://chengkao.gdcxxy.net/gdcx/wiki_exam_zy.php* // @match https://chengkao.gdcxxy.net/gdcx/wiki_exam_cy.php* // @match https://chengkao.gdcxxy.net/gdcx/studycenter_zy.php // @match https://chengkao.gdcxxy.net/gdcx/studycenter_cy.php // @match *://*.gdcxxy.net/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; // 配置参数 const config = { autoStart: false, answerDelay: 1000, nextPageDelay: 2000, maxRetryCount: 3, autoConfirm: true, // 自动点击确认按钮 pressEnterAfterCompletion: true // 答完题后按回车键 }; // 状态管理 let state = { running: false, paused: false, completedChapters: 0, totalQuestions: 0, correctAnswers: 0, currentChapter: '', startTime: null, timerInterval: null }; // 新增:控制面板位置/尺寸状态(用于记忆拖动和缩放后的状态) let panelState = { x: 20, // 初始X坐标 y: 20, // 初始Y坐标 width: 320, // 初始宽度 height: 500, // 初始高度(原代码未设高度,新增默认值) isDragging: false, dragStart: { x: 0, y: 0 }, isResizing: false, resizeStart: { x: 0, y: 0, width: 0, height: 0 } }; // 初始化 function init() { // 恢复保存的状态 const savedState = GM_getValue('autoAnswerState'); if (savedState) { state = { ...state, ...savedState }; } // 新增:恢复控制面板位置/尺寸状态 const savedPanelState = GM_getValue('autoAnswerPanelState'); if (savedPanelState) { panelState = { ...panelState, ...savedPanelState }; } // 创建控制面板(新增拖动/缩放相关样式和结构) createControlPanel(); // 注册菜单命令 GM_registerMenuCommand('⚙️ 脚本设置', showSettings); GM_registerMenuCommand('📊 重置统计', resetStats); // 根据当前URL执行相应逻辑 const currentUrl = window.location.href; if (currentUrl.includes('wiki_exam_zy.php') || currentUrl.includes('wiki_exam_cy.php')) { // 答题页面逻辑(章节练习和综合测评) if (state.running && !state.paused) { setTimeout(handleExamPage, 2000); } // 检查是否有确认提示 setTimeout(checkForConfirmation, 1000); } else if (currentUrl.includes('studycenter_zy.php') || currentUrl.includes('studycenter_cy.php')) { // 练习列表页面逻辑(章节练习和综合测评) if (state.running && !state.paused) { setTimeout(handleStudyCenterPage, 2000); } } // 如果设置了自动开始,并且不在运行状态,则开始执行 if (config.autoStart && !state.running) { startScript(); } } // 检查确认提示并自动点击 function checkForConfirmation() { if (!config.autoConfirm) return; // 检查是否有确认提示 const confirmText = document.body.textContent; const isCompletionText = confirmText.includes('已是本次测试最后一题') || confirmText.includes('将返回章节练习页面') || confirmText.includes('将返回综合测评页面'); if (isCompletionText) { addLog("检测到完成提示,正在查找确认按钮...", "info"); // 查找确认按钮(适配两种页面) const buttons = document.querySelectorAll('button, input[type="button"]'); for (let btn of buttons) { if (btn.textContent.includes('确定') || btn.value.includes('确定')) { addLog("找到确认按钮,正在点击...", "success"); btn.click(); return; } } // 尝试通过链接返回 setTimeout(() => { const backLinks = document.querySelectorAll('a'); for (let link of backLinks) { if (link.textContent.includes('返回') && (link.href.includes('studycenter_zy.php') || link.href.includes('studycenter_cy.php'))) { link.click(); return; } } // 直接跳转回列表页 window.location.href = window.location.href.includes('zy.php') ? 'https://chengkao.gdcxxy.net/gdcx/studycenter_zy.php' : 'https://chengkao.gdcxxy.net/gdcx/studycenter_cy.php'; }, 2000); // 模拟回车键 if (config.pressEnterAfterCompletion) { setTimeout(simulateEnterKey, 500); } } } // 模拟按下回车键 function simulateEnterKey() { addLog("尝试模拟按下回车键...", "info"); const enterEvent = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true }); document.dispatchEvent(enterEvent); document.body.dispatchEvent(enterEvent); const activeElement = document.activeElement; if (activeElement && activeElement !== document.body) { activeElement.dispatchEvent(enterEvent); } addLog("已模拟回车键按下", "success"); } // 创建控制面板(新增拖动/缩放功能) function createControlPanel() { const panelHTML = `
自动答题脚本
广东创新科技职业学院
已停止
${state.completedChapters}
已完成项目
${state.totalQuestions}
答题总数
${state.totalQuestions > 0 ? Math.round((state.correctAnswers / state.totalQuestions) * 100) : 100}%
正确率
00:00:00
运行时间
[系统] 控制面板已加载(支持拖动标题栏、右下角缩放)
`; // 添加控制面板到页面 document.body.insertAdjacentHTML('beforeend', panelHTML); // 添加事件监听 document.getElementById('btn-start').addEventListener('click', startScript); document.getElementById('btn-pause').addEventListener('click', pauseScript); document.getElementById('btn-stop').addEventListener('click', stopScript); // 新增:初始化拖动和缩放事件 initDragAndResize(); // 初始化面板状态 updatePanelState(); } // 新增:初始化控制面板拖动和缩放功能 function initDragAndResize() { const panel = document.getElementById('auto-answer-panel'); const dragHandle = document.getElementById('panel-drag-handle'); const resizeHandle = document.getElementById('panel-resize-handle'); // 1. 拖动功能 dragHandle.addEventListener('mousedown', (e) => { // 排除缩放手柄区域的点击(避免拖动和缩放冲突) if (e.target === resizeHandle || e.target.closest('#panel-resize-handle')) return; panelState.isDragging = true; // 记录鼠标按下时的初始位置和面板位置 panelState.dragStart.x = e.clientX; panelState.dragStart.y = e.clientY; panelState.x = panel.offsetLeft; panelState.y = panel.offsetTop; // 添加鼠标捕获(防止鼠标移出面板后拖动失效) dragHandle.setCapture ? dragHandle.setCapture() : panel.setCapture(); // 隐藏鼠标指针(优化拖动体验) document.body.style.cursor = 'move'; }); // 2. 缩放功能 resizeHandle.addEventListener('mousedown', (e) => { panelState.isResizing = true; // 记录鼠标按下时的初始位置和面板尺寸 panelState.resizeStart.x = e.clientX; panelState.resizeStart.y = e.clientY; panelState.resizeStart.width = panel.offsetWidth; panelState.resizeStart.height = panel.offsetHeight; // 添加鼠标捕获 resizeHandle.setCapture ? resizeHandle.setCapture() : panel.setCapture(); // 隐藏鼠标指针(优化缩放体验) document.body.style.cursor = 'se-resize'; }); // 3. 全局鼠标移动事件(处理拖动和缩放) document.addEventListener('mousemove', (e) => { // 处理拖动 if (panelState.isDragging) { const deltaX = e.clientX - panelState.dragStart.x; const deltaY = e.clientY - panelState.dragStart.y; // 更新面板位置(限制在可视区域内) panelState.x = Math.max(0, Math.min(panelState.x + deltaX, window.innerWidth - panel.offsetWidth)); panelState.y = Math.max(0, Math.min(panelState.y + deltaY, window.innerHeight - panel.offsetHeight)); panel.style.left = `${panelState.x}px`; panel.style.top = `${panelState.y}px`; } // 处理缩放 if (panelState.isResizing) { const deltaX = e.clientX - panelState.resizeStart.x; const deltaY = e.clientY - panelState.resizeStart.y; // 更新面板尺寸(设置最小尺寸限制,避免过小) panelState.width = Math.max(280, panelState.resizeStart.width + deltaX); panelState.height = Math.max(400, panelState.resizeStart.height + deltaY); panel.style.width = `${panelState.width}px`; panel.style.height = `${panelState.height}px`; } }); // 4. 全局鼠标松开事件(结束拖动/缩放) document.addEventListener('mouseup', () => { // 结束拖动 if (panelState.isDragging) { panelState.isDragging = false; // 释放鼠标捕获 dragHandle.releaseCapture ? dragHandle.releaseCapture() : panel.releaseCapture(); // 恢复鼠标指针 document.body.style.cursor = ''; // 保存拖动后的位置 GM_setValue('autoAnswerPanelState', panelState); } // 结束缩放 if (panelState.isResizing) { panelState.isResizing = false; // 释放鼠标捕获 resizeHandle.releaseCapture ? resizeHandle.releaseCapture() : panel.releaseCapture(); // 恢复鼠标指针 document.body.style.cursor = ''; // 保存缩放后的尺寸 GM_setValue('autoAnswerPanelState', panelState); } }); // 5. 防止拖动/缩放时文本选中 dragHandle.addEventListener('selectstart', (e) => e.preventDefault()); resizeHandle.addEventListener('selectstart', (e) => e.preventDefault()); } // 显示设置对话框 function showSettings() { const settingsHTML = `

脚本设置

`; document.body.insertAdjacentHTML('beforeend', settingsHTML); // 添加事件监听 document.getElementById('saveSettings').addEventListener('click', function() { config.autoConfirm = document.getElementById('autoConfirmSetting').checked; config.pressEnterAfterCompletion = document.getElementById('pressEnterSetting').checked; GM_setValue('autoAnswerConfig', config); document.querySelector('#auto-answer-panel + div').remove(); document.querySelector('#auto-answer-panel + div').remove(); addLog("设置已保存", "success"); }); document.getElementById('cancelSettings').addEventListener('click', function() { document.querySelector('#auto-answer-panel + div').remove(); document.querySelector('#auto-answer-panel + div').remove(); }); } // 重置统计信息 function resetStats() { state.completedChapters = 0; state.totalQuestions = 0; state.correctAnswers = 0; updatePanelState(); addLog("统计信息已重置", "info"); } // 更新面板状态 function updatePanelState() { const statusDot = document.getElementById('status-dot'); const statusText = document.getElementById('status-text'); if (state.running && !state.paused) { statusDot.style.background = '#2ecc71'; statusText.textContent = '运行中'; } else if (state.paused) { statusDot.style.background = '#f39c12'; statusText.textContent = '已暂停'; } else { statusDot.style.background = '#e74c3c'; statusText.textContent = '已停止'; } // 更新统计信息 document.getElementById('completed-chapters').textContent = state.completedChapters; document.getElementById('total-questions').textContent = state.totalQuestions; const rate = state.totalQuestions > 0 ? Math.round((state.correctAnswers / state.totalQuestions) * 100) : 100; document.getElementById('success-rate').textContent = `${rate}%`; // 保存状态 GM_setValue('autoAnswerState', state); } // 添加日志 function addLog(message, type = 'info') { const logContent = document.getElementById('log-content'); if (!logContent) return; const color = type === 'error' ? '#e74c3c' : type === 'success' ? '#2ecc71' : type === 'warning' ? '#f39c12' : '#3498db'; const time = new Date().toLocaleTimeString(); logContent.innerHTML += `
[${time}] ${message}
`; logContent.scrollTop = logContent.scrollHeight; } // 开始脚本 function startScript() { if (state.running && !state.paused) return; if (state.paused) { state.paused = false; addLog("脚本已恢复执行", "success"); } else { state.running = true; state.startTime = new Date(); state.timerInterval = setInterval(updateRunTime, 1000); addLog("脚本开始执行", "success"); } updatePanelState(); // 根据当前页面执行相应操作 const currentUrl = window.location.href; if (currentUrl.includes('wiki_exam_zy.php') || currentUrl.includes('wiki_exam_cy.php')) { handleExamPage(); } else if (currentUrl.includes('studycenter_zy.php') || currentUrl.includes('studycenter_cy.php')) { handleStudyCenterPage(); } } // 暂停脚本 function pauseScript() { if (!state.running || state.paused) return; state.paused = true; addLog("脚本已暂停", "warning"); updatePanelState(); } // 停止脚本 function stopScript() { if (!state.running) return; state.running = false; state.paused = false; clearInterval(state.timerInterval); addLog("脚本已停止", "info"); updatePanelState(); } // 更新运行时间 function updateRunTime() { if (state.startTime && state.running && !state.paused) { const now = new Date(); const diff = now - state.startTime; const hours = Math.floor(diff / 3600000); const minutes = Math.floor((diff % 3600000) / 60000); const seconds = Math.floor((diff % 60000) / 1000); const runTimeEl = document.getElementById('run-time'); if (runTimeEl) { runTimeEl.textContent = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } } } // 处理答题页面(同时支持章节练习和综合测评) function handleExamPage() { if (!state.running || state.paused) return; // 检查是否已完成所有题目 const totNumEl = document.getElementById('tot_num'); const didNumEl = document.getElementById('did_num'); if (!totNumEl || !didNumEl) { addLog("未找到题目进度元素", "error"); return; } const totalQuestions = parseInt(totNumEl.textContent); const completedQuestions = parseInt(didNumEl.textContent); if (completedQuestions >= totalQuestions) { addLog('所有题目已完成', "success"); checkForConfirmation(); if (config.pressEnterAfterCompletion) { setTimeout(simulateEnterKey, 500); } return; } // 获取正确答案(兼容原逻辑+简答题新逻辑) let correctAnswer = ''; const correctAnswerEl = document.getElementById('tright'); // 获取题目类型 const questionTypeElement = document.querySelector('.test_boxdt .text-default') || document.querySelector('.questionTest .text-333'); let questionType = ''; if (questionTypeElement) { questionType = questionTypeElement.textContent.trim(); } // ------------- 核心修改:简答题自动提取答案 ------------- if (questionType.includes('简答')) { // 查找简答题专用答案容器(匹配 "试题答案S" 注释后的结构) const answerContainer = document.querySelector('.answer.mt40 #resolve'); if (answerContainer) { // 提取答案文本(去除多余标签和空格,保留原始格式) let answerText = answerContainer.innerText.trim(); // 过滤 "正确答案:" 前缀(若存在) if (answerText.startsWith('正确答案:')) { answerText = answerText.replace('正确答案:', '').trim(); } correctAnswer = answerText; addLog(`提取到简答题答案: ${correctAnswer.substring(0, 30)}...`, "success"); // 显示前30字符避免日志过长 } else { // 若未找到专用容器,降级使用原tright元素(兼容旧结构) if (correctAnswerEl) { correctAnswer = correctAnswerEl.value; addLog("使用备用方式提取简答题答案", "warning"); } else { addLog("未找到简答题答案元素", "error"); return; } } } else { // 其他题型(单选/多选/判断/填空)保持原逻辑 if (!correctAnswerEl) { addLog("未找到正确答案元素", "error"); return; } correctAnswer = correctAnswerEl.value; } // 根据题目类型选择/填写答案 if (questionType.includes('单项') || questionType.includes('判断')) { // 单选题或判断题 const radioInput = document.querySelector(`input[type="radio"][value="${correctAnswer}"]`); if (radioInput) { radioInput.checked = true; addLog(`已选择答案: ${correctAnswer}`, "success"); } } else if (questionType.includes('多项') || questionType.includes('双选')) { // 多选题 for (let i = 0; i < correctAnswer.length; i++) { const option = correctAnswer[i]; const checkboxInput = document.querySelector(`input[type="checkbox"][value="${option}"]`); if (checkboxInput) { checkboxInput.checked = true; addLog(`已选择答案: ${option}`, "success"); } } } else if (questionType.includes('填空') || questionType.includes('简答')) { // 填空题/简答题(填充答案) const inputField = document.getElementById('tiankong') || document.getElementById('allqita'); if (inputField) { inputField.value = correctAnswer; addLog(`已填写答案: ${correctAnswer.substring(0, 30)}...`, "success"); // 显示前30字符避免日志过长 } } // 更新统计数据 state.totalQuestions++; state.correctAnswers++; updatePanelState(); // 提交答案(适配两种页面的提交按钮) const submitButton = document.querySelector('button[onclick^="sub_answere"]') || document.querySelector('.btn-hero.btn-primary') || document.querySelector('.courseblue[onclick*="sub"]'); if (submitButton) { addLog('提交答案', "info"); submitButton.click(); // 等待提交完成后再跳转到下一题 setTimeout(() => { // 检查是否有下一题按钮 const nextButton = document.querySelector('.next_choice a') || document.querySelector('a[href*="n_or_p=2"]'); if (nextButton && nextButton.style.display !== 'none') { addLog('跳转到下一题', "info"); nextButton.click(); } else { addLog('没有下一题按钮或已完成所有题目', "info"); checkForConfirmation(); if (config.pressEnterAfterCompletion) { setTimeout(simulateEnterKey, 500); } } }, config.nextPageDelay); } } // 处理练习列表页面(同时支持章节练习和综合测评) function handleStudyCenterPage() { if (!state.running || state.paused) return; // 点击所有展开按钮(适配两种页面) const expandButtons = document.querySelectorAll( 'button[onclick*="expand"], .flex-align-center[id*="btnshowTwo_"]' ); if (expandButtons.length > 0) { addLog(`找到 ${expandButtons.length} 个展开按钮,正在展开...`, "info"); expandButtons.forEach(btn => { if (btn.style.display !== 'none') btn.click(); }); } // 等待一段时间让章节展开 setTimeout(() => { // 查找所有未完成的项目 const incompleteChapters = []; // 1. 章节练习页面未完成项目 const zyIncomplete = document.querySelectorAll('span[id^="zycs_"], span[id^="zycs2_"]'); zyIncomplete.forEach(el => { if (el.textContent.includes('未完成')) { const practiceBtn = el.closest('tr')?.querySelector('button[onclick*="gotozy"]') || el.closest('.conframe')?.querySelector('button[onclick*="gotozy"]'); if (practiceBtn) incompleteChapters.push(practiceBtn); } }); // 2. 综合测评页面未完成项目 const cyIncomplete = document.querySelectorAll('span[id^="zt_"], span[id^="zt2_"]'); cyIncomplete.forEach(el => { if (el.textContent.includes('未完成')) { const practiceBtn = el.closest('tr')?.querySelector('button[onclick*="gotocy"]') || el.closest('.conframe')?.querySelector('button[onclick*="gotocy"]'); if (practiceBtn) incompleteChapters.push(practiceBtn); } }); // 如果有未完成的项目,点击第一个 if (incompleteChapters.length > 0) { addLog(`找到 ${incompleteChapters.length} 个未完成的项目`, "info"); // 获取项目名称 const chapterName = incompleteChapters[0].closest('tr')?.querySelector('td:first-child')?.textContent.trim() || incompleteChapters[0].closest('.conframe')?.querySelector('.text-333 + span')?.textContent.trim() || '未知项目'; state.currentChapter = chapterName; addLog(`开始处理项目: ${chapterName}`, "info"); incompleteChapters[0].click(); } else { addLog('所有项目已完成', "success"); stopScript(); // 显示完成通知 GM_notification({ text: '所有项目已完成!', title: '自动答题脚本', timeout: 5000 }); } }, 2000); } // 添加CSS样式 GM_addStyle(` #auto-answer-panel { resize: both; overflow: auto; min-width: 280px; /* 与缩放最小宽度一致 */ min-height: 400px; /* 与缩放最小高度一致 */ } #auto-answer-panel button:hover { opacity: 0.9; transform: translateY(-2px); transition: all 0.2s; } #log-content::-webkit-scrollbar { width: 6px; } #log-content::-webkit-scrollbar-track { background: #1a2530; border-radius: 3px; } #log-content::-webkit-scrollbar-thumb { background: #3498db; border-radius: 3px; } /* 新增:缩放手柄hover样式 */ #panel-resize-handle:hover { background: #2980b9; } `); // 初始化脚本 window.addEventListener('load', function() { // 加载保存的配置 const savedConfig = GM_getValue('autoAnswerConfig'); if (savedConfig) { Object.assign(config, savedConfig); } setTimeout(init, 1000); }); })();