// ==UserScript==
// @name 湛江考试专用
// @namespace http://tampermonkey.net/
// @version 2.2
// @description 自动答题、题库记录和管理功能,完全修复选择题自动答题问题,新增问答题和多选题支持
// @author You
// @match *://*qsxueli.com/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_download
// @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
// ==/UserScript==
(function() {
'use strict';
class QuestionBank {
constructor() {
this.bank = GM_getValue('question_bank', {});
this.stats = GM_getValue('question_stats', {
totalQuestions: 0,
answeredQuestions: 0,
unknownQuestions: 0,
lastUpdate: ''
});
}
// 添加题目到题库
addQuestion(question, answer, type = 'choice') {
const key = this.normalizeQuestion(question);
if (!this.bank[key]) {
this.bank[key] = {
answer: answer,
type: type,
createdAt: new Date().toISOString()
};
this.saveBank();
return true;
}
return false;
}
// 查找答案
findAnswer(question) {
const key = this.normalizeQuestion(question);
return this.bank[key] || null;
}
// 标准化题目文本
normalizeQuestion(question) {
return question.replace(/\s+/g, ' ').trim().replace(/ /g, ' ');
}
// 保存题库
saveBank() {
GM_setValue('question_bank', this.bank);
}
// 导出题库
exportBank() {
const data = JSON.stringify(this.bank, null, 2);
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `question_bank_${new Date().toISOString().split('T')[0]}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// 导入题库
importBank(file) {
const reader = new FileReader();
reader.onload = (e) => {
try {
const importedBank = JSON.parse(e.target.result);
this.bank = { ...this.bank, ...importedBank };
this.saveBank();
this.updateStats();
alert('题库导入成功!');
} catch (error) {
alert('导入失败:文件格式错误');
}
};
reader.readAsText(file);
}
// 更新统计信息
updateStats() {
const questionElements = document.querySelectorAll('.title, .sp');
let total = questionElements.length;
let answered = 0;
let unknown = 0;
questionElements.forEach((element, index) => {
const questionText = this.normalizeQuestion(element.textContent.replace(/^\d+\./, '').trim());
if (this.findAnswer(questionText)) {
answered++;
} else {
unknown++;
}
});
this.stats = {
totalQuestions: total,
answeredQuestions: answered,
unknownQuestions: unknown,
lastUpdate: new Date().toLocaleString()
};
GM_setValue('question_stats', this.stats);
return this.stats;
}
// 获取统计信息
getStats() {
return this.updateStats();
}
// 检测题目类型(增强版)- 修复选择题检测,新增问答题和多选题检测
detectQuestionType(questionElement) {
const questionText = questionElement.textContent || '';
const parentLi = questionElement.closest('li');
if (!parentLi) return 'choice';
// 通过类名检测题目类型
const liClass = parentLi.getAttribute('class') || '';
// 多选题检测 - 新增:类名包含multiple(如multiple10, multiple11等)
if (liClass.includes('multiple')) {
return 'multiple';
}
// 问答题检测 - 类名包含open(如open20, open21等)
if (liClass.includes('open') && liClass.match(/open\d+/)) {
return 'open';
}
// 填空题检测 - 类名包含fill
if (liClass.includes('fill')) {
return 'fill';
}
// 判断题检测 - 类名包含judgement
if (liClass.includes('judgement')) {
return 'judgement';
}
// 单选题检测 - 类名包含single
if (liClass.includes('single')) {
return 'choice';
}
// 检查是否存在输入框或文本域
const hasTextInput = parentLi.querySelector('input[type="text"]');
const hasTextArea = parentLi.querySelector('textarea');
const hasRadioButtons = parentLi.querySelectorAll('input[type="radio"]').length > 0;
const hasCheckboxes = parentLi.querySelectorAll('input[type="checkbox"]').length > 0;
const hasOpenTextarea = parentLi.querySelector('.open_textarea textarea'); // 问答题的textarea
// 如果有问答题特有的textarea,判断为问答题
if (hasOpenTextarea) {
return 'open';
}
// 如果有文本输入框,优先判断为填空题
if (hasTextInput) {
return 'fill';
}
// 如果有文本域,判断为简答题
if (hasTextArea && !hasRadioButtons && !hasCheckboxes) {
return 'essay';
}
// 多选题检测:通过是否存在多个checkbox
if (hasCheckboxes && !hasRadioButtons) {
// 检查checkbox数量,通常多选题有多个选项
const checkboxCount = parentLi.querySelectorAll('input[type="checkbox"]').length;
if (checkboxCount >= 2) {
return 'multiple';
}
}
// 填空题检测
const hasFillBlankSymbols = questionText.includes('_') ||
questionText.includes('()') ||
questionText.includes('()') ||
questionText.includes('请填写') ||
questionText.includes('请填空');
if (hasFillBlankSymbols && !hasRadioButtons && !hasCheckboxes) {
return 'fill';
}
// 判断题特征检测
const judgementOptions = parentLi.querySelectorAll('input[type="radio"][value="对"], input[type="radio"][value="错"]');
if (judgementOptions.length === 2) {
return 'judgement';
}
// 如果有单选按钮,就是单选题
if (hasRadioButtons) {
return 'choice';
}
// 默认情况
return 'choice';
}
// 在结果页面检测题目类型(增强版)- 新增问答题和多选题检测
detectQuestionTypeInResult(questionElement) {
const questionText = questionElement.textContent || '';
const parentLi = questionElement.closest('li');
if (!parentLi) return 'choice';
// 通过类名检测
const liClass = parentLi.getAttribute('class') || '';
// 新增:多选题检测
if (liClass.includes('multiple')) {
return 'multiple';
}
// 新增:问答题检测
if (liClass.includes('open') && liClass.match(/open\d+/)) {
return 'open';
}
if (liClass.includes('fill')) {
return 'fill';
}
if (liClass.includes('judgement')) {
return 'judgement';
}
if (liClass.includes('single')) {
return 'choice';
}
// 检查答案元素的特征
const hasChoiceAnswer = parentLi.querySelector('.daan');
const hasFillAnswer = parentLi.querySelector('.daan .zhengque');
const hasEssayAnswer = parentLi.querySelector('.jianda-da, .essay-answer');
const hasOpenAnswer = parentLi.querySelector('.daan .zhengque'); // 问答题答案
// 新增:问答题答案提取
if (hasOpenAnswer && questionElement.closest('.big_question')) {
return 'open';
}
if (hasFillAnswer) return 'fill';
if (hasEssayAnswer) return 'essay';
if (hasChoiceAnswer) {
// 检查答案是否包含多个选项(多选题)
const answerElement = parentLi.querySelector('.daan');
if (answerElement) {
const answerText = answerElement.textContent || '';
// 检查答案是否包含多个大写字母(如ABD, ABC等)
const multipleAnswerMatch = answerText.match(/[A-D]{2,}/);
if (multipleAnswerMatch) {
return 'multiple';
}
}
return 'choice';
}
// 根据题目文本特征判断
const hasFillBlankSymbols = questionText.includes('_') ||
questionText.includes('()') ||
questionText.includes('()') ||
questionText.includes('请填写') ||
questionText.includes('请填空');
if (hasFillBlankSymbols) return 'fill';
// 默认
return 'choice';
}
// 提取填空题答案
extractFillAnswer(parentLi) {
const answerElements = parentLi.querySelectorAll('.daan');
for (let answerElement of answerElements) {
if (answerElement.textContent.includes('正确答案')) {
let answerText = answerElement.textContent
.replace(/正确答案/g, '')
.replace(/\s+/g, '')
.trim();
answerText = answerText.replace(/^[::]\s*/, '').trim();
console.log('提取到的填空题答案:', answerText);
return answerText;
}
}
return null;
}
// 提取多选题答案(新增方法)- 专门处理多选题答案提取
extractMultipleAnswer(parentLi) {
console.log('开始提取多选题答案...');
// 查找包含正确答案的daan元素
const answerElements = parentLi.querySelectorAll('.daan');
for (let answerElement of answerElements) {
// 检查是否包含"正确答案"文本
if (answerElement.textContent.includes('正确答案')) {
// 获取整个答案文本
let fullText = answerElement.textContent.trim();
// 提取答案部分(可能是多个字母,如ABC、ABD等)
// 首先移除"正确答案"字样
let answerText = fullText.replace(/正确答案/g, '').trim();
// 清理答案文本,移除多余空格和标点
answerText = answerText.replace(/[::]\s*/, '').trim();
// 提取连续的A-D字母(多选题答案通常由多个字母组成)
const answerMatch = answerText.match(/[A-D]{2,}/);
if (answerMatch) {
const multipleAnswer = answerMatch[0];
console.log('提取到的多选题答案:', multipleAnswer);
return multipleAnswer;
}
// 如果没有找到连续字母,尝试提取单个字母组合
const letters = answerText.match(/[A-D]/g);
if (letters && letters.length > 1) {
const multipleAnswer = letters.join('');
console.log('提取到的多选题答案(组合):', multipleAnswer);
return multipleAnswer;
}
console.log('提取到的完整答案文本:', answerText.substring(0, 100) + '...');
return answerText;
}
}
// 备用方法:直接获取整个daan的文本
const daanElement = parentLi.querySelector('.daan');
if (daanElement) {
let answerText = daanElement.textContent.trim();
// 尝试提取多选题答案格式
const answerMatch = answerText.match(/[A-D]{2,}/);
if (answerMatch) {
const multipleAnswer = answerMatch[0];
console.log('备用方法提取多选题答案:', multipleAnswer);
return multipleAnswer;
}
console.log('备用方法提取完整答案:', answerText.substring(0, 100) + '...');
return answerText;
}
console.log('未找到多选题答案');
return null;
}
// 提取问答题答案
extractOpenAnswer(parentLi) {
console.log('开始提取问答题答案...');
const answerElements = parentLi.querySelectorAll('.daan');
for (let answerElement of answerElements) {
if (answerElement.textContent.includes('答案解析')) {
let fullText = answerElement.textContent.trim();
let answerText = fullText.replace(/答案解析/g, '').trim();
answerText = answerText.replace(/\s+/g, ' ').trim();
console.log('提取到的问答题答案:', answerText.substring(0, 100) + '...');
return answerText;
}
}
const daanElement = parentLi.querySelector('.daan');
if (daanElement) {
let answerText = daanElement.textContent.trim();
console.log('备用方法提取问答题答案:', answerText.substring(0, 100) + '...');
return answerText;
}
console.log('未找到问答题答案');
return null;
}
// 智能分割填空题答案
splitFillAnswers(questionText, answerText, inputCount) {
console.log(`智能分割答案: 题目="${questionText}", 答案="${answerText}", 输入框数量=${inputCount}`);
if (answerText.includes(';')) {
const parts = answerText.split(';').map(part => part.trim()).filter(part => part);
if (parts.length === inputCount) {
console.log('使用分号分割的答案:', parts);
return parts;
}
}
const commonSeparators = ['、', ',', ',', ' '];
for (let separator of commonSeparators) {
if (answerText.includes(separator)) {
const parts = answerText.split(separator).map(part => part.trim()).filter(part => part);
if (parts.length === inputCount) {
console.log(`使用分隔符"${separator}"分割的答案:`, parts);
return parts;
}
}
}
const blankCount = this.countBlanksInQuestion(questionText);
if (blankCount > 0 && blankCount === inputCount) {
return this.splitByBlankCount(answerText, blankCount);
}
console.log('无法智能分割,返回单个答案数组');
return [answerText];
}
// 计算题目中的空位数量
countBlanksInQuestion(questionText) {
const blankPatterns = [
/(\s*)/g,
/\(\s*\)/g,
/_\s*_/g,
/\[?\s*\]?/g,
/\{?\s*\}/g
];
let totalBlanks = 0;
for (let pattern of blankPatterns) {
const matches = questionText.match(pattern);
if (matches) {
totalBlanks += matches.length;
}
}
console.log(`题目中的空位数量: ${totalBlanks}`);
return totalBlanks;
}
// 按空位数量分割答案
splitByBlankCount(answerText, blankCount) {
if (blankCount <= 1) {
return [answerText];
}
const avgLength = Math.ceil(answerText.length / blankCount);
const parts = [];
for (let i = 0; i < blankCount; i++) {
const start = i * avgLength;
const end = (i + 1) * avgLength;
parts.push(answerText.substring(start, end).trim());
}
console.log(`按空位数量分割的答案:`, parts);
return parts;
}
}
class ControlPanel {
constructor(questionBank) {
this.questionBank = questionBank;
this.panel = null;
this.isDragging = false;
this.offset = { x: 0, y: 0 };
this.createPanel();
}
createPanel() {
this.panel = document.createElement('div');
this.panel.id = 'auto-answer-panel';
this.panel.innerHTML = `
统计信息
总题目数:
0
已收录:
0
未收录:
0
最后更新:
-
`;
this.addStyles();
document.body.appendChild(this.panel);
this.bindEvents();
this.updateDisplay();
}
addStyles() {
const styles = `
#auto-answer-panel {
position: fixed;
top: 100px;
right: 20px;
width: 320px;
background: white;
border: 2px solid #409EFF;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 10000;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.panel-header {
background: #409EFF;
color: white;
padding: 10px 15px;
cursor: move;
display: flex;
justify-content: between;
align-items: center;
border-radius: 6px 6px 0 0;
user-select: none;
}
.close-btn {
background: none;
border: none;
color: white;
font-size: 18px;
cursor: pointer;
padding: 0;
width: 20px;
height: 20px;
}
.panel-content {
padding: 15px;
}
.stats {
margin-bottom: 15px;
}
.stats h4 {
margin: 0 0 10px 0;
color: #333;
font-size: 14px;
}
.stat-item {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 12px;
}
.stat-item span:first-child {
color: #666;
}
.stat-item span:last-child {
color: #409EFF;
font-weight: bold;
}
.actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.actions button {
padding: 8px 12px;
border: 1px solid #409EFF;
background: white;
color: #409EFF;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
transition: all 0.3s;
}
.actions button:hover {
background: #409EFF;
color: white;
}
#auto-answer-btn, #fill-blank-btn, #judgement-btn, #essay-btn, #open-question-btn, #multiple-choice-btn {
grid-column: 1 / -1;
}
.fill-blank-input {
border: 1px solid #409EFF;
border-radius: 4px;
padding: 4px 8px;
margin: 2px;
width: 120px;
}
.essay-answer-input, .open-question-input {
width: 100%;
min-height: 80px;
border: 1px solid #409EFF;
border-radius: 4px;
padding: 8px;
margin-top: 8px;
font-family: inherit;
resize: vertical;
}
.essay-submit-btn, .open-submit-btn {
background: #409EFF;
color: white;
border: none;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
margin-top: 8px;
}
`;
const styleSheet = document.createElement('style');
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
}
bindEvents() {
const header = this.panel.querySelector('.panel-header');
header.addEventListener('mousedown', this.startDrag.bind(this));
this.panel.querySelector('.close-btn').addEventListener('click', () => {
this.panel.style.display = 'none';
});
this.panel.querySelector('#auto-answer-btn').addEventListener('click', () => {
this.autoAnswer();
});
this.panel.querySelector('#record-answers-btn').addEventListener('click', () => {
this.recordAnswers();
});
this.panel.querySelector('#fill-blank-btn').addEventListener('click', () => {
this.enableFillBlankMode();
});
this.panel.querySelector('#judgement-btn').addEventListener('click', () => {
this.enableJudgementMode();
});
this.panel.querySelector('#essay-btn').addEventListener('click', () => {
this.enableEssayMode();
});
this.panel.querySelector('#open-question-btn').addEventListener('click', () => {
this.enableOpenQuestionMode();
});
// 新增:多选题模式按钮
this.panel.querySelector('#multiple-choice-btn').addEventListener('click', () => {
this.enableMultipleChoiceMode();
});
this.panel.querySelector('#export-btn').addEventListener('click', () => {
this.questionBank.exportBank();
});
this.panel.querySelector('#import-btn').addEventListener('click', () => {
document.getElementById('import-input').click();
});
document.getElementById('import-input').addEventListener('change', (e) => {
if (e.target.files.length > 0) {
this.questionBank.importBank(e.target.files[0]);
this.updateDisplay();
}
});
}
startDrag(e) {
if (e.target.classList.contains('close-btn')) return;
this.isDragging = true;
const rect = this.panel.getBoundingClientRect();
this.offset.x = e.clientX - rect.left;
this.offset.y = e.clientY - rect.top;
document.addEventListener('mousemove', this.drag.bind(this));
document.addEventListener('mouseup', this.stopDrag.bind(this));
}
drag(e) {
if (!this.isDragging) return;
const x = e.clientX - this.offset.x;
const y = e.clientY - this.offset.y;
this.panel.style.left = x + 'px';
this.panel.style.top = y + 'px';
this.panel.style.right = 'auto';
}
stopDrag() {
this.isDragging = false;
document.removeEventListener('mousemove', this.drag.bind(this));
document.removeEventListener('mouseup', this.stopDrag.bind(this));
}
updateDisplay() {
const stats = this.questionBank.getStats();
document.getElementById('total-questions').textContent = stats.totalQuestions;
document.getElementById('answered-questions').textContent = stats.answeredQuestions;
document.getElementById('unknown-questions').textContent = stats.unknownQuestions;
document.getElementById('last-update').textContent = stats.lastUpdate;
}
// 自动答题功能 - 新增多选题支持
autoAnswer() {
console.log('开始自动答题...');
const questions = document.querySelectorAll('.title');
let answeredCount = 0;
questions.forEach((questionElement, index) => {
const questionText = this.questionBank.normalizeQuestion(
questionElement.textContent.replace(/^\d+\./, '').trim()
);
console.log(`处理题目 ${index + 1}: "${questionText.substring(0, 50)}..."`);
const questionData = this.questionBank.findAnswer(questionText);
if (questionData) {
const questionType = questionData.type || 'choice';
console.log(`找到答案: ${questionData.answer.substring(0, 50)}..., 类型: ${questionType}`);
if (questionType === 'choice') {
if (this.answerChoiceQuestion(questionElement, questionData.answer)) {
answeredCount++;
}
} else if (questionType === 'multiple') {
// 新增:多选题自动答题
if (this.answerMultipleQuestion(questionElement, questionData.answer)) {
answeredCount++;
}
} else if (questionType === 'fill') {
this.answerFillBlank(questionElement, questionData.answer);
answeredCount++;
} else if (questionType === 'judgement') {
this.answerJudgement(questionElement, questionData.answer);
answeredCount++;
} else if (questionType === 'essay') {
this.answerEssay(questionElement, questionData.answer);
answeredCount++;
} else if (questionType === 'open') {
this.answerOpenQuestion(questionElement, questionData.answer);
answeredCount++;
}
} else {
console.log(`未找到题目答案: "${questionText.substring(0, 30)}..."`);
}
});
this.updateDisplay();
alert(`自动答题完成!已回答 ${answeredCount} 道题目`);
}
// 新增:多选题答题方法
answerMultipleQuestion(questionElement, answer) {
const parentLi = questionElement.closest('li');
if (!parentLi) {
console.log('未找到父级li元素');
return false;
}
const answerValue = answer.toString().trim().toUpperCase();
console.log(`多选题答案: ${answerValue}`);
// 获取所有复选框
const checkboxInputs = parentLi.querySelectorAll('input[type="checkbox"]');
console.log(`找到 ${checkboxInputs.length} 个复选框`);
// 先将所有复选框取消选中(多选题可能需要取消之前的选项)
checkboxInputs.forEach(input => {
if (input.checked) {
input.click(); // 取消选中
}
});
let answeredOptions = 0;
// 方法1: 直接点击匹配的input
for (let input of checkboxInputs) {
const inputValue = input.value.trim().toUpperCase();
console.log(`复选框值: ${inputValue}`);
// 检查这个选项是否在答案中
if (answerValue.includes(inputValue)) {
console.log(`选项 ${inputValue} 在答案中,尝试点击`);
if (this.simulateRealClick(input)) {
answeredOptions++;
console.log(`方法1成功: 选择 ${inputValue}`);
}
}
}
// 方法2: 通过选项标签文本匹配
if (answeredOptions < answerValue.length) {
const optionLabels = parentLi.querySelectorAll('.el-checkbox__label');
console.log(`找到 ${optionLabels.length} 个选项标签`);
for (let i = 0; i < optionLabels.length; i++) {
const label = optionLabels[i];
const labelText = label.textContent.trim();
console.log(`选项标签 ${i + 1}: "${labelText}"`);
const optionLetter = labelText.charAt(0).toUpperCase();
console.log(`提取的选项字母: ${optionLetter}`);
// 检查这个选项是否在答案中且尚未选中
if (answerValue.includes(optionLetter) && checkboxInputs[i] && !checkboxInputs[i].checked) {
console.log('尝试方法2: 通过选项标签匹配');
if (this.simulateRealClick(checkboxInputs[i])) {
answeredOptions++;
console.log(`方法2成功: 选择 ${optionLetter}`);
}
}
}
}
// 方法3: 通过选项索引匹配
if (answeredOptions < answerValue.length) {
// 将答案字符串分解为单个字母
const answerLetters = answerValue.split('');
console.log(`答案字母分解: ${answerLetters}`);
for (let letter of answerLetters) {
const optionIndex = 'ABCDE'.indexOf(letter);
console.log(`选项索引: ${letter} -> ${optionIndex}`);
if (optionIndex >= 0 && optionIndex < checkboxInputs.length) {
console.log('尝试方法3: 通过选项索引匹配');
if (checkboxInputs[optionIndex] && !checkboxInputs[optionIndex].checked) {
if (this.simulateRealClick(checkboxInputs[optionIndex])) {
answeredOptions++;
console.log(`方法3成功: 选择 ${letter}`);
}
}
}
}
}
console.log(`多选题答题完成,选择了 ${answeredOptions} 个选项`);
return answeredOptions > 0;
}
// 问答题答题方法
answerOpenQuestion(questionElement, answer) {
const parentLi = questionElement.closest('li');
if (!parentLi) {
console.log('未找到父级li元素');
return false;
}
console.log(`问答题答案: ${answer.substring(0, 50)}...`);
const textarea = parentLi.querySelector('.open_textarea textarea, .el-textarea textarea');
if (textarea) {
console.log('找到问答题的textarea');
textarea.value = answer;
const inputEvent = new Event('input', { bubbles: true });
textarea.dispatchEvent(inputEvent);
const changeEvent = new Event('change', { bubbles: true });
textarea.dispatchEvent(changeEvent);
console.log(`问答题自动答题: 填写答案 "${answer.substring(0, 50)}..."`);
return true;
} else {
console.log('未找到问答题的textarea');
return false;
}
}
// 单选题答题方法
answerChoiceQuestion(questionElement, answer) {
const parentLi = questionElement.closest('li');
if (!parentLi) {
console.log('未找到父级li元素');
return false;
}
const answerValue = answer.toString().trim().toUpperCase();
console.log(`单选题答案: ${answerValue}`);
const radioInputs = parentLi.querySelectorAll('input[type="radio"]');
console.log(`找到 ${radioInputs.length} 个单选按钮`);
for (let input of radioInputs) {
const inputValue = input.value.trim().toUpperCase();
console.log(`单选按钮值: ${inputValue}`);
if (inputValue === answerValue) {
console.log('尝试方法1: 直接点击input元素');
if (this.simulateRealClick(input)) {
console.log(`方法1成功: 选择 ${answerValue}`);
return true;
}
}
}
const optionLabels = parentLi.querySelectorAll('.el-radio__label');
console.log(`找到 ${optionLabels.length} 个选项标签`);
for (let i = 0; i < optionLabels.length; i++) {
const label = optionLabels[i];
const labelText = label.textContent.trim();
console.log(`选项标签 ${i + 1}: "${labelText}"`);
const optionLetter = labelText.charAt(0).toUpperCase();
console.log(`提取的选项字母: ${optionLetter}`);
if (optionLetter === answerValue && radioInputs[i]) {
console.log('尝试方法2: 通过选项标签匹配');
if (this.simulateRealClick(radioInputs[i])) {
console.log(`方法2成功: 选择 ${answerValue}`);
return true;
}
}
}
const optionIndex = 'ABCDE'.indexOf(answerValue);
console.log(`选项索引: ${answerValue} -> ${optionIndex}`);
if (optionIndex >= 0 && optionIndex < radioInputs.length) {
console.log('尝试方法3: 通过选项索引匹配');
if (this.simulateRealClick(radioInputs[optionIndex])) {
console.log(`方法3成功: 选择 ${answerValue}`);
return true;
}
}
const allLabels = parentLi.querySelectorAll('label.el-radio');
for (let label of allLabels) {
const radioInput = label.querySelector('input[type="radio"]');
if (radioInput && radioInput.value.trim().toUpperCase() === answerValue) {
console.log('尝试方法4: 点击label元素');
if (this.simulateRealClick(label)) {
console.log(`方法4成功: 选择 ${answerValue}`);
return true;
}
}
}
console.log('所有匹配方法都失败');
return false;
}
// 模拟真实点击
simulateRealClick(element) {
try {
element.click();
const mouseEvents = ['mousedown', 'mouseup', 'click'];
mouseEvents.forEach(eventType => {
const event = new MouseEvent(eventType, {
view: window,
bubbles: true,
cancelable: true,
buttons: 1
});
element.dispatchEvent(event);
});
element.dispatchEvent(new Event('change', { bubbles: true }));
element.dispatchEvent(new Event('input', { bubbles: true }));
// 对于checkbox,检查checked状态
if (element.type === 'checkbox') {
if (element.checked) {
console.log('点击成功,复选框已选中');
return true;
} else {
console.log('点击失败,复选框未选中');
return false;
}
}
// 对于radio,检查checked状态
if (element.type === 'radio' && element.checked) {
console.log('点击成功,单选按钮已选中');
return true;
} else {
console.log('点击可能未成功,单选按钮未选中');
return false;
}
} catch (error) {
console.log('点击过程中出错:', error);
return false;
}
}
// 填空题答题
answerFillBlank(questionElement, answer) {
const parentLi = questionElement.closest('li');
const textInputs = parentLi.querySelectorAll('input[type="text"]');
if (textInputs.length > 0) {
console.log(`检测到 ${textInputs.length} 个输入框`);
const questionText = this.questionBank.normalizeQuestion(
questionElement.textContent.replace(/^\d+\./, '').trim()
);
let answers = [];
if (Array.isArray(answer)) {
answers = answer;
console.log('使用已有的答案数组:', answers);
} else {
answers = this.questionBank.splitFillAnswers(questionText, answer, textInputs.length);
console.log('智能分割后的答案:', answers);
}
textInputs.forEach((input, index) => {
if (answers[index]) {
input.value = answers[index].trim();
input.dispatchEvent(new Event('input', { bubbles: true }));
console.log(`填空题自动答题: 第${index+1}个输入框填入答案 "${answers[index].trim()}"`);
} else if (index === 0 && answers[0]) {
input.value = answers[0].trim();
input.dispatchEvent(new Event('input', { bubbles: true }));
console.log(`填空题自动答题: 第1个输入框填入完整答案 "${answers[0].trim()}"`);
} else {
console.log(`填空题自动答题: 第${index+1}个输入框无对应答案`);
}
});
}
}
// 判断题答题
answerJudgement(questionElement, answer) {
const parentLi = questionElement.closest('li');
const options = parentLi.querySelectorAll('input[type="radio"]');
options.forEach(option => {
if (option.value === answer) {
option.click();
console.log(`判断题自动答题: 选择答案 "${answer}"`);
}
});
}
// 简答题答题
answerEssay(questionElement, answer) {
const parentLi = questionElement.closest('li');
const textarea = parentLi.querySelector('textarea');
if (textarea) {
textarea.value = answer;
textarea.dispatchEvent(new Event('input', { bubbles: true }));
console.log(`简答题自动答题: 填写答案 "${answer.substring(0, 30)}..."`);
}
}
// 启用填空题模式
enableFillBlankMode() {
const questions = document.querySelectorAll('.title');
let processedCount = 0;
questions.forEach((questionElement, index) => {
const questionText = questionElement.textContent || '';
if (this.questionBank.detectQuestionType(questionElement) === 'fill') {
const parentLi = questionElement.closest('li');
const textInputs = parentLi.querySelectorAll('input[type="text"]');
if (textInputs.length > 0) {
const questionData = this.questionBank.findAnswer(
this.questionBank.normalizeQuestion(questionText.replace(/^\d+\./, '').trim())
);
if (questionData && questionData.answer) {
this.answerFillBlank(questionElement, questionData.answer);
}
processedCount++;
}
}
});
alert(`填空题模式已启用!处理了 ${processedCount} 道填空题`);
}
// 启用判断题模式
enableJudgementMode() {
const questions = document.querySelectorAll('.title');
let processedCount = 0;
questions.forEach((questionElement, index) => {
const questionText = questionElement.textContent || '';
if (this.questionBank.detectQuestionType(questionElement) === 'judgement') {
const parentLi = questionElement.closest('li');
const options = parentLi.querySelectorAll('input[type="radio"]');
if (options.length > 0) {
const questionData = this.questionBank.findAnswer(
this.questionBank.normalizeQuestion(questionText.replace(/^\d+\./, '').trim())
);
if (questionData && questionData.answer) {
this.answerJudgement(questionElement, questionData.answer);
}
processedCount++;
}
}
});
alert(`判断题模式已启用!处理了 ${processedCount} 道判断题`);
}
// 启用简答题模式
enableEssayMode() {
const questions = document.querySelectorAll('.title');
let processedCount = 0;
questions.forEach((questionElement, index) => {
const questionText = questionElement.textContent || '';
if (this.questionBank.detectQuestionType(questionElement) === 'essay') {
const parentLi = questionElement.closest('li');
const textarea = parentLi.querySelector('textarea');
if (textarea) {
const questionData = this.questionBank.findAnswer(
this.questionBank.normalizeQuestion(questionText.replace(/^\d+\./, '').trim())
);
if (questionData && questionData.answer) {
this.answerEssay(questionElement, questionData.answer);
}
processedCount++;
}
}
});
alert(`简答题模式已启用!处理了 ${processedCount} 道简答题`);
}
// 启用问答题模式
enableOpenQuestionMode() {
const questions = document.querySelectorAll('.title');
let processedCount = 0;
questions.forEach((questionElement, index) => {
const questionText = questionElement.textContent || '';
if (this.questionBank.detectQuestionType(questionElement) === 'open') {
const parentLi = questionElement.closest('li');
const textarea = parentLi.querySelector('.open_textarea textarea, .el-textarea textarea');
if (textarea) {
const questionData = this.questionBank.findAnswer(
this.questionBank.normalizeQuestion(questionText.replace(/^\d+\./, '').trim())
);
if (questionData && questionData.answer) {
this.answerOpenQuestion(questionElement, questionData.answer);
}
processedCount++;
}
}
});
alert(`问答题模式已启用!处理了 ${processedCount} 道问答题`);
}
// 新增:启用多选题模式
enableMultipleChoiceMode() {
const questions = document.querySelectorAll('.title');
let processedCount = 0;
questions.forEach((questionElement, index) => {
const questionText = questionElement.textContent || '';
if (this.questionBank.detectQuestionType(questionElement) === 'multiple') {
const parentLi = questionElement.closest('li');
const checkboxes = parentLi.querySelectorAll('input[type="checkbox"]');
if (checkboxes.length > 0) {
const questionData = this.questionBank.findAnswer(
this.questionBank.normalizeQuestion(questionText.replace(/^\d+\./, '').trim())
);
if (questionData && questionData.answer) {
this.answerMultipleQuestion(questionElement, questionData.answer);
}
processedCount++;
}
}
});
alert(`多选题模式已启用!处理了 ${processedCount} 道多选题`);
}
// 记录答案功能 - 新增多选题记录
recordAnswers() {
const resultPageQuestions = document.querySelectorAll('.sp');
let recordedCount = 0;
if (resultPageQuestions.length > 0) {
resultPageQuestions.forEach((questionElement, index) => {
const questionText = this.questionBank.normalizeQuestion(
questionElement.textContent.replace(/^\d+\./, '').trim()
);
console.log(`处理题目 ${index + 1}: ${questionText.substring(0, 50)}...`);
const questionType = this.questionBank.detectQuestionTypeInResult(questionElement);
console.log(`题目类型: ${questionType}`);
if (questionType === 'choice') {
const answerElement = questionElement.closest('li').querySelector('.daan');
if (answerElement) {
const answerText = answerElement.textContent.replace(/正确答案[::]?\s*/g, '').trim();
console.log(`找到选择题答案文本: ${answerText}`);
const answerMatch = answerText.match(/[A-E]/);
if (answerMatch) {
const answer = answerMatch[0].toUpperCase();
console.log(`提取到单选题答案: ${answer}`);
if (this.questionBank.addQuestion(questionText, answer, 'choice')) {
recordedCount++;
console.log(`成功记录单选题: ${answer}`);
}
}
}
} else if (questionType === 'multiple') {
// 新增:多选题答案记录
const parentLi = questionElement.closest('li');
const answerText = this.questionBank.extractMultipleAnswer(parentLi);
if (answerText) {
console.log(`找到多选题答案: ${answerText}`);
if (this.questionBank.addQuestion(questionText, answerText, 'multiple')) {
recordedCount++;
console.log(`成功记录多选题: ${answerText}`);
}
}
} else if (questionType === 'fill') {
const parentLi = questionElement.closest('li');
const answerText = this.questionBank.extractFillAnswer(parentLi);
if (answerText) {
console.log(`找到填空题答案: ${answerText}`);
if (this.questionBank.addQuestion(questionText, answerText, 'fill')) {
recordedCount++;
console.log(`成功记录填空题: ${answerText}`);
}
}
} else if (questionType === 'judgement') {
const answerElement = questionElement.closest('li').querySelector('.daan, .judgement-da, .panduan-da');
if (answerElement) {
const answerText = answerElement.textContent.replace(/正确答案[::]?\s*/g, '').trim();
console.log(`找到判断题答案文本: ${answerText}`);
if (answerText === '对' || answerText === '错') {
if (this.questionBank.addQuestion(questionText, answerText, 'judgement')) {
recordedCount++;
console.log(`成功记录判断题: ${answerText}`);
}
}
}
} else if (questionType === 'essay') {
const answerElement = questionElement.closest('li').querySelector('.jianda-da, .essay-answer');
if (answerElement) {
const answerText = answerElement.textContent.trim();
if (answerText) {
if (this.questionBank.addQuestion(questionText, answerText, 'essay')) {
recordedCount++;
console.log(`记录简答题答案: ${answerText.substring(0, 30)}...`);
}
}
}
} else if (questionType === 'open') {
const parentLi = questionElement.closest('li');
const answerText = this.questionBank.extractOpenAnswer(parentLi);
if (answerText) {
console.log(`找到问答题答案: ${answerText.substring(0, 50)}...`);
if (this.questionBank.addQuestion(questionText, answerText, 'open')) {
recordedCount++;
console.log(`成功记录问答题: ${answerText.substring(0, 30)}...`);
}
}
}
});
}
this.updateDisplay();
alert(`记录完成!新增 ${recordedCount} 道题目到题库`);
}
}
// 初始化
let questionBank, controlPanel;
function init() {
questionBank = new QuestionBank();
controlPanel = new ControlPanel(questionBank);
setTimeout(() => {
controlPanel.updateDisplay();
}, 1000);
// 如果是结果页面,自动记录答案
if (document.querySelector('.sp')) {
setTimeout(() => {
console.log('检测到结果页面,开始自动记录答案...');
controlPanel.recordAnswers();
}, 2000);
}
// 自动检测并处理各种题型
setTimeout(() => {
const hasFillQuestions = document.querySelector('li[class*="fill"]');
const hasJudgementQuestions = document.querySelector('li[class*="judgement"]');
const hasEssayQuestions = document.querySelector('textarea');
const hasOpenQuestions = document.querySelector('li[class*="open"] .open_textarea');
const hasMultipleQuestions = document.querySelector('li[class*="multiple"]'); // 新增:多选题检测
if (hasFillQuestions || hasJudgementQuestions || hasEssayQuestions || hasOpenQuestions || hasMultipleQuestions) {
console.log('检测到各种题型,自动启用相应模式');
if (hasFillQuestions) {
controlPanel.enableFillBlankMode();
}
if (hasJudgementQuestions) {
controlPanel.enableJudgementMode();
}
if (hasEssayQuestions) {
controlPanel.enableEssayMode();
}
if (hasOpenQuestions) {
controlPanel.enableOpenQuestionMode();
}
if (hasMultipleQuestions) {
controlPanel.enableMultipleChoiceMode(); // 新增:多选题模式
}
}
}, 3000);
}
// 等待页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();