// ==UserScript==
// @name 全自动答题助手
// @namespace http://tampermonkey.net/
// @version 2.8
// @description 根据页面中的答案自动选择正确选项(单选题、多选题、判断题、填空题、简答题),并自动点击下一题
// @author ScriptCat
// @match *://*.cx-online.net/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
let isAutoMode = false;
let autoInterval = null;
let isProcessing = false; // 防止重复处理标志
let currentQuestionId = ''; // 当前处理的题目ID
// 等待页面加载完成后执行
window.addEventListener('load', function() {
setTimeout(initAutoAnswer, 1500);
});
function initAutoAnswer() {
console.log('初始化自动答题脚本...');
// 添加样式美化
addStyles();
// 添加控制面板
addControlPanel();
// 初始执行一次答题
autoAnswer();
}
function autoAnswer() {
// 防止重复处理
if (isProcessing) {
console.log('正在处理中,跳过本次调用');
return;
}
isProcessing = true;
// 获取当前显示的题目容器
const currentQuestion = document.querySelector('.homeWork_cxt--left_item:not([style*="display: none"])');
if (!currentQuestion) {
console.log('未找到当前显示的题目容器');
isProcessing = false;
return;
}
// 生成当前题目的唯一标识(使用题目内容和类型)
const questionTypeElement = currentQuestion.querySelector('.multiple_head--queType');
const questionTitleElement = currentQuestion.querySelector('.multiple_ctx--title');
if (!questionTypeElement || !questionTitleElement) {
console.log('未找到题目元素');
isProcessing = false;
return;
}
const questionType = questionTypeElement.textContent.trim();
const questionTitle = questionTitleElement.textContent;
const newQuestionId = `${questionType}-${questionTitle}`;
// 如果是同一道题,跳过处理
if (newQuestionId === currentQuestionId) {
console.log('同一道题,跳过处理');
isProcessing = false;
return;
}
currentQuestionId = newQuestionId;
console.log('题目类型:', questionType);
console.log('题目内容:', questionTitle);
// 获取正确答案(从解析中提取)
const analysisElement = currentQuestion.querySelector('.multiple_ctx--analysis');
let correctAnswer = '';
if (analysisElement) {
if (questionType.includes('简答题') || questionType.includes('简答')) {
// 简答题的答案:获取第二个div的内容
const answerDiv = analysisElement.querySelector('div:last-child');
if (answerDiv) {
correctAnswer = answerDiv.textContent.trim();
console.log('简答题答案:', correctAnswer);
} else {
// 如果没有找到第二个div,尝试直接从文本中提取
const analysisText = analysisElement.textContent;
// 移除"详情解析:"部分
if (analysisText.includes('详情解析:')) {
const parts = analysisText.split('详情解析:');
if (parts.length > 1) {
correctAnswer = parts[1].trim();
}
}
}
} else if (questionType.includes('多项') || questionType.includes('多选')) {
// 多选题:提取所有/* */注释内容
const analysisText = analysisElement.textContent;
console.log('多选题解析文本:', analysisText);
// 使用正则表达式匹配所有/* */注释
const answerMatches = analysisText.match(/\/\*([^*]+)\*\//g);
if (answerMatches && answerMatches.length > 0) {
console.log('找到答案注释:', answerMatches);
// 提取每个注释的内容并清理
const answers = answerMatches.map(match => {
// 移除/*和*/,并去除首尾空格
return match.replace(/\/\*/g, '').replace(/\*\//g, '').trim();
});
// 连接所有答案
correctAnswer = answers.join('、');
console.log('多选题正确答案:', correctAnswer);
// 如果没有找到/* */注释,尝试从正确答案区域提取
} else {
// 尝试从正确答案区域提取
const rightAnsElement = currentQuestion.querySelector('.multiple_ctx--rightAns');
if (rightAnsElement) {
const rightAnsText = rightAnsElement.textContent;
const match = rightAnsText.match(/正确答案:\s*(.+)/);
if (match) {
correctAnswer = match[1].trim();
console.log('从正确答案区域提取的答案:', correctAnswer);
}
}
}
} else if (questionType.includes('判断')) {
// 特殊处理判断题:提取所有/* */注释,取最后一个作为正确答案
const analysisText = analysisElement.textContent;
// 查找所有的/* */注释
const allMatches = analysisText.match(/\/\*([^*]+)\*\//g);
if (allMatches) {
// 取最后一个匹配作为正确答案
const lastMatch = allMatches[allMatches.length - 1];
const answerMatch = lastMatch.match(/\/\*([^*]+)\*\//);
if (answerMatch) {
correctAnswer = answerMatch[1].trim();
console.log('判断题正确答案:', correctAnswer);
}
} else {
// 如果没有/* */注释,尝试在文本中查找"正确"或"错误"
if (analysisText.includes('正确')) {
correctAnswer = '正确';
} else if (analysisText.includes('错误')) {
correctAnswer = '错误';
}
}
} else {
// 其他题型(单选题、填空题),使用正则表达式提取答案
const analysisText = analysisElement.textContent;
const answerMatch = analysisText.match(/\/\*([^*]+)\*\//);
if (answerMatch) {
correctAnswer = answerMatch[1].trim();
console.log('正确答案:', correctAnswer);
}
}
}
// 根据题目类型处理答案
if (questionType.includes('单项') || questionType.includes('单选')) {
handleSingleChoice(currentQuestion, correctAnswer);
} else if (questionType.includes('多项') || questionType.includes('多选')) {
handleMultipleChoice(currentQuestion, correctAnswer);
} else if (questionType.includes('判断')) {
handleJudgment(currentQuestion, correctAnswer);
} else if (questionType.includes('填空')) {
handleFillInBlank(currentQuestion, correctAnswer);
} else if (questionType.includes('简答')) {
handleShortAnswer(currentQuestion, correctAnswer);
} else {
console.log('未知题目类型:', questionType);
}
// 如果是自动模式,延迟后点击下一题
if (isAutoMode) {
// 根据题目类型设置不同的延迟时间
let delayTime = 3000; // 默认3秒
if (questionType.includes('单项') || questionType.includes('单选') ||
questionType.includes('多项') || questionType.includes('多选') ||
questionType.includes('判断')) {
// 选择题需要更多时间让系统记录答案
delayTime = 2500;
} else if (questionType.includes('填空')) {
delayTime = 3500;
} else if (questionType.includes('简答')) {
delayTime = 4500;
}
console.log(`等待 ${delayTime} 毫秒后点击下一题`);
setTimeout(() => {
// 在处理完当前题目后,重置处理标志
isProcessing = false;
clickNextQuestion();
}, delayTime);
} else {
// 非自动模式下,处理完成后立即重置标志
setTimeout(() => {
isProcessing = false;
}, 1000);
}
}
function handleSingleChoice(currentQuestion, correctAnswer) {
console.log('处理单选题,答案:', correctAnswer);
// 在当前题目容器内获取所有选项
const options = currentQuestion.querySelectorAll('.multiple_ctx--option');
// 遍历选项,找到匹配的选项
for (let i = 0; i < options.length; i++) {
const option = options[i];
const optionText = option.querySelector('.multiple_ctx--option_title').textContent;
// 检查选项文本是否包含答案
if (optionText.includes(correctAnswer)) {
console.log('找到匹配选项:', optionText);
simulateClick(option);
showFeedback('单选题已选择: ' + optionText, 'success');
return;
}
}
// 如果没有直接匹配,尝试匹配字母
const letterMatch = correctAnswer.match(/^[A-D]/);
if (letterMatch) {
const letter = letterMatch[0];
for (let i = 0; i < options.length; i++) {
const option = options[i];
const optionText = option.querySelector('.multiple_ctx--option_title').textContent;
if (optionText.startsWith(letter)) {
console.log('按字母找到匹配选项:', optionText);
simulateClick(option);
showFeedback('单选题已选择: ' + optionText, 'success');
return;
}
}
}
showFeedback('未找到匹配的选项', 'error');
}
function handleMultipleChoice(currentQuestion, correctAnswer) {
console.log('处理多选题,答案:', correctAnswer);
// 获取所有选项
const options = currentQuestion.querySelectorAll('.multiple_ctx--option');
let selectedCount = 0;
if (!correctAnswer || correctAnswer.trim() === '') {
console.log('多选题答案为空');
showFeedback('多选题答案为空,无法选择', 'warning');
return;
}
// 清洗答案:去除/* */标记和多余空格
correctAnswer = correctAnswer.replace(/\/\*/g, '').replace(/\*\//g, '').trim();
console.log('清洗后的答案:', correctAnswer);
// 尝试按常见分隔符分割答案
let answerParts = [];
const separators = ['、', ',', ',', ';', ';', '/', ' ', ' '];
// 先尝试用顿号分割
if (correctAnswer.includes('、')) {
answerParts = correctAnswer.split('、').map(part => part.trim());
}
// 尝试用中文逗号分割
else if (correctAnswer.includes(',')) {
answerParts = correctAnswer.split(',').map(part => part.trim());
}
// 尝试用英文逗号分割
else if (correctAnswer.includes(',')) {
answerParts = correctAnswer.split(',').map(part => part.trim());
}
// 尝试用分号分割
else if (correctAnswer.includes(';') || correctAnswer.includes(';')) {
const separator = correctAnswer.includes(';') ? ';' : ';';
answerParts = correctAnswer.split(separator).map(part => part.trim());
}
// 如果没有分隔符,尝试按空格分割
else if (correctAnswer.includes(' ') || correctAnswer.includes(' ')) {
const separator = correctAnswer.includes(' ') ? ' ' : ' ';
answerParts = correctAnswer.split(separator).map(part => part.trim()).filter(part => part.length > 0);
}
// 如果还是没有分隔符,直接作为一个整体
else {
answerParts = [correctAnswer];
}
console.log('分割后的答案数组:', answerParts);
// 方法1: 先尝试按字母匹配
const letterAnswers = [];
const textAnswers = [];
// 将答案分成字母答案和文本答案
answerParts.forEach(part => {
// 匹配单独的字母,如A, B, C, D
if (part.match(/^[A-D]$/i)) {
letterAnswers.push(part.toUpperCase());
} else {
textAnswers.push(part);
}
});
// 处理字母答案
if (letterAnswers.length > 0) {
console.log('字母答案:', letterAnswers);
for (let i = 0; i < options.length; i++) {
const option = options[i];
const optionText = option.querySelector('.multiple_ctx--option_title').textContent;
const optionLetter = optionText.charAt(0); // 获取选项字母
if (letterAnswers.includes(optionLetter)) {
console.log('按字母选择选项:', optionText);
simulateClick(option);
selectedCount++;
// 确保点击后选项被选中
const radio = option.querySelector('.multiple_ctx--option_radio');
if (radio) {
radio.style.backgroundColor = '#409EFF';
}
}
}
}
// 处理文本答案(如果还有文本答案需要匹配)
if (textAnswers.length > 0 && selectedCount < answerParts.length) {
console.log('文本答案:', textAnswers);
// 创建一个选项文本到选项元素的映射
const optionMap = new Map();
for (let i = 0; i < options.length; i++) {
const option = options[i];
const optionText = option.querySelector('.multiple_ctx--option_title').textContent;
// 提取选项文本内容(去掉前面的字母和标点)
let optionContent = optionText;
if (optionText.includes('、')) {
optionContent = optionText.split('、')[1] || optionText;
} else if (optionText.includes('. ')) {
optionContent = optionText.split('. ')[1] || optionText;
} else if (optionText.match(/^[A-D]/)) {
optionContent = optionText.substring(1).trim();
}
optionMap.set(optionContent, option);
}
// 遍历文本答案,尝试匹配选项
for (const textAnswer of textAnswers) {
let matchedOption = null;
// 方法1: 完全匹配
for (const [optionContent, option] of optionMap) {
if (optionContent === textAnswer) {
matchedOption = option;
break;
}
}
// 方法2: 如果完全匹配失败,尝试部分匹配
if (!matchedOption) {
for (const [optionContent, option] of optionMap) {
if (optionContent.includes(textAnswer) || textAnswer.includes(optionContent)) {
matchedOption = option;
break;
}
}
}
// 方法3: 如果部分匹配也失败,尝试模糊匹配(忽略空格和标点)
if (!matchedOption) {
const cleanAnswer = textAnswer.replace(/[,。;、\s]/g, '');
for (const [optionContent, option] of optionMap) {
const cleanOption = optionContent.replace(/[,。;、\s]/g, '');
if (cleanOption.includes(cleanAnswer) || cleanAnswer.includes(cleanOption)) {
matchedOption = option;
break;
}
}
}
// 如果找到匹配的选项
if (matchedOption) {
// 检查是否已经选中(避免重复点击)
const radio = matchedOption.querySelector('.multiple_ctx--option_radio');
const isAlreadySelected = radio && window.getComputedStyle(radio).backgroundColor === 'rgb(64, 158, 255)';
if (!isAlreadySelected) {
console.log('按文本选择选项:', matchedOption.querySelector('.multiple_ctx--option_title').textContent);
simulateClick(matchedOption);
selectedCount++;
// 确保点击后选项被选中
if (radio) {
radio.style.backgroundColor = '#409EFF';
}
}
}
}
}
// 如果仍然没有匹配到,尝试整个答案字符串匹配所有选项
if (selectedCount === 0 && answerParts.length === 1 && answerParts[0].length > 5) {
console.log('尝试整个答案字符串匹配所有选项');
const fullAnswer = answerParts[0];
// 遍历所有选项,检查是否在完整答案中
for (let i = 0; i < options.length; i++) {
const option = options[i];
const optionText = option.querySelector('.multiple_ctx--option_title').textContent;
// 提取选项文本内容
let optionContent = optionText;
if (optionText.includes('、')) {
optionContent = optionText.split('、')[1] || optionText;
} else if (optionText.includes('. ')) {
optionContent = optionText.split('. ')[1] || optionText;
} else if (optionText.match(/^[A-D]/)) {
optionContent = optionText.substring(1).trim();
}
// 检查完整答案是否包含选项内容,或者选项内容是否包含在完整答案中
if (fullAnswer.includes(optionContent) || optionContent.includes(fullAnswer.substring(0, 5))) {
console.log('通过完整答案匹配选项:', optionText);
simulateClick(option);
selectedCount++;
const radio = option.querySelector('.multiple_ctx--option_radio');
if (radio) {
radio.style.backgroundColor = '#409EFF';
}
}
}
}
if (selectedCount > 0) {
showFeedback(`多选题已选择 ${selectedCount} 个选项`, 'success');
} else {
showFeedback('未找到匹配的选项', 'error');
}
}
function handleJudgment(currentQuestion, correctAnswer) {
console.log('处理判断题,答案:', correctAnswer);
// 在当前题目容器内获取所有选项
const options = currentQuestion.querySelectorAll('.multiple_ctx--option');
// 遍历选项,找到匹配的选项
for (let i = 0; i < options.length; i++) {
const option = options[i];
const optionText = option.querySelector('.multiple_ctx--option_title').textContent;
// 检查选项是否包含正确答案(如"正确"或"错误")
if (optionText.includes(correctAnswer)) {
console.log('找到匹配选项:', optionText);
simulateClick(option);
showFeedback('判断题已选择: ' + optionText, 'success');
return;
}
// 如果答案是"正确"/"错误",但选项是"A、正确"/"B、错误"的形式
if (correctAnswer === '正确' && optionText.includes('正确')) {
console.log('找到匹配选项:', optionText);
simulateClick(option);
showFeedback('判断题已选择: ' + optionText, 'success');
return;
}
if (correctAnswer === '错误' && optionText.includes('错误')) {
console.log('找到匹配选项:', optionText);
simulateClick(option);
showFeedback('判断题已选择: ' + optionText, 'success');
return;
}
}
showFeedback('未找到匹配的选项', 'error');
}
function handleFillInBlank(currentQuestion, correctAnswer) {
console.log('处理填空题,答案:', correctAnswer);
// 在当前题目容器内查找所有输入框
const inputElements = currentQuestion.querySelectorAll('input.el-input__inner');
if (inputElements.length === 0) {
console.log('未找到输入框');
showFeedback('未找到输入框', 'error');
return;
}
console.log(`找到 ${inputElements.length} 个输入框`);
// 分割答案
let answers = [correctAnswer];
// 如果答案中包含分隔符,按分隔符分割
if (correctAnswer.includes('/')) {
answers = correctAnswer.split('/').map(a => a.trim());
} else if (correctAnswer.includes(';')) {
answers = correctAnswer.split(';').map(a => a.trim());
} else if (correctAnswer.includes(';')) {
answers = correctAnswer.split(';').map(a => a.trim());
} else if (correctAnswer.includes('、')) {
answers = correctAnswer.split('、').map(a => a.trim());
} else if (correctAnswer.includes(',')) {
answers = correctAnswer.split(',').map(a => a.trim());
} else if (correctAnswer.includes(',')) {
answers = correctAnswer.split(',').map(a => a.trim());
}
console.log('填空答案数组:', answers);
// 填充每个输入框
let filledCount = 0;
for (let i = 0; i < inputElements.length; i++) {
const input = inputElements[i];
// 如果有对应的答案,就填充
if (i < answers.length) {
const answer = answers[i];
if (answer && answer !== '') {
// 设置输入框的值
input.value = answer;
// 触发输入事件,确保React/Vue等框架能捕获到变化
triggerInputEvent(input);
// 添加视觉反馈
input.style.backgroundColor = '#f0f9ff';
input.style.borderColor = '#409EFF';
input.style.transition = 'all 0.3s';
filledCount++;
console.log(`填充第${i+1}个空: ${answer}`);
// 为每个输入框添加短暂延迟
setTimeout(() => {
input.style.backgroundColor = '';
input.style.borderColor = '';
}, 300 * (i + 1));
}
} else if (answers.length === 1) {
// 如果只有一个答案但有多个空,填充第一个答案到所有空
const answer = answers[0];
if (answer && answer !== '') {
input.value = answer;
triggerInputEvent(input);
input.style.backgroundColor = '#f0f9ff';
input.style.borderColor = '#409EFF';
input.style.transition = 'all 0.3s';
filledCount++;
console.log(`填充第${i+1}个空(复用答案): ${answer}`);
setTimeout(() => {
input.style.backgroundColor = '';
input.style.borderColor = '';
}, 300 * (i + 1));
}
}
}
if (filledCount > 0) {
showFeedback(`填空题已填充 ${filledCount} 个空`, 'success');
} else {
showFeedback('填空题答案为空或无法解析', 'warning');
}
}
function handleShortAnswer(currentQuestion, correctAnswer) {
console.log('处理简答题,原始答案:', correctAnswer);
// 清理简答题答案中的特殊符号
if (correctAnswer) {
// 移除所有/* */注释符号及其内容
correctAnswer = correctAnswer.replace(/\/\*.*?\*\//g, '');
// 移除多余的空格和换行
correctAnswer = correctAnswer.replace(/\s+/g, ' ').trim();
console.log('清理后的简答题答案:', correctAnswer);
}
// 检查答案是否为空
if (!correctAnswer || correctAnswer.trim() === '' || correctAnswer === '/*') {
console.log('简答题答案为空或无效,无法填写');
showFeedback('简答题答案为空或无效,无法填写', 'warning');
return;
}
// 查找简答题的编辑器
const editorElement = currentQuestion.querySelector('.ql-editor');
if (!editorElement) {
console.log('未找到简答题编辑器');
showFeedback('未找到简答题编辑器', 'error');
return;
}
// 如果编辑器为空或者只有
标签,则填充答案
const editorContent = editorElement.innerHTML.trim();
if (editorContent === '