Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greasyfork.ip-ddns.com/scripts/537074/1598335/%E5%B2%90%E9%BB%84%E5%A4%A9%E4%BD%BF%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%20-%20%E8%87%AA%E5%8A%A8%E7%AD%94%E9%A2%98%E6%A8%A1%E5%9D%97.js
// ==UserScript==
// @name 岐黄天使刷课助手 - 自动答题模块
// @namespace http://tampermonkey.net/qhtx-modules
// @version 1.3.0
// @description 岐黄天使刷课助手的自动答题功能模块,提供自动识别题目、匹配答案及自动提交等功能。
// @author AI助手
// ==/UserScript==
// 自动答题模块
(function() {
'use strict';
// 切换自动答题状态
window.toggleAutoAnswer = function() {
if (window.qh.isAutoAnswering) {
stopAutoAnswer();
} else {
startAutoAnswer();
}
};
// 开始自动答题
window.startAutoAnswer = function() {
// 如果已经在自动答题,则不重复开始
if (window.qh.isAutoAnswering) {
return;
}
// 设置自动答题状态
window.qh.isAutoAnswering = true;
// 更新状态
if (window.qh && window.qh.updateStatus) {
window.qh.updateStatus('自动答题已开始');
} else {
console.log('自动答题已开始');
}
// 更新按钮状态
const autoAnswerBtn = document.getElementById('qh-auto-answer-btn');
if (autoAnswerBtn) {
autoAnswerBtn.textContent = '停止自动答题';
autoAnswerBtn.style.background = 'linear-gradient(90deg, #f44336, #e53935)';
}
// 开始自动答题
autoAnswerCurrentQuestion();
};
// 停止自动答题
window.stopAutoAnswer = function() {
// 如果没有在自动答题,则不执行停止操作
if (!window.qh.isAutoAnswering) {
return;
}
// 清除自动答题定时器
if (window.qh.autoAnswerInterval) {
clearTimeout(window.qh.autoAnswerInterval);
window.qh.autoAnswerInterval = null;
}
// 设置自动答题状态
window.qh.isAutoAnswering = false;
// 更新状态
if (window.qh && window.qh.updateStatus) {
window.qh.updateStatus('自动答题已停止');
} else {
console.log('自动答题已停止');
}
// 更新按钮状态
const autoAnswerBtn = document.getElementById('qh-auto-answer-btn');
if (autoAnswerBtn) {
autoAnswerBtn.textContent = '自动答题';
autoAnswerBtn.style.background = 'linear-gradient(90deg, #E91E63, #C2185B)';
}
};
// 自动答题当前题目
function autoAnswerCurrentQuestion() {
try {
// 如果不再自动答题,则退出
if (!window.qh.isAutoAnswering) {
return;
}
// 获取当前题目
const currentQuestion = getCurrentQuestion();
if (!currentQuestion) {
console.log('未找到当前题目,延迟重试');
window.qh.autoAnswerInterval = setTimeout(autoAnswerCurrentQuestion, getRandomDelay(window.qh.humanLikeDelay));
return;
}
// 查找题目在题库中的匹配
const matchedQuestion = findQuestionInBank(currentQuestion.title);
if (!matchedQuestion) {
console.log('题库中未找到匹配的题目:', currentQuestion.title);
// 保存当前题目到题库
saveCurrentQuestion(currentQuestion);
// 尝试查找下一题
goToNextQuestion(currentQuestion);
return;
}
console.log('找到匹配的题目:', matchedQuestion.question);
console.log('答案:', matchedQuestion.answer);
// 选择正确答案
selectAnswer(currentQuestion, matchedQuestion);
// 延迟后前往下一题
window.qh.autoAnswerInterval = setTimeout(() => {
goToNextQuestion(currentQuestion);
}, getRandomDelay(window.qh.humanLikeDelay));
} catch (e) {
console.error('自动答题出错:', e);
// 出错后延迟重试
window.qh.autoAnswerInterval = setTimeout(autoAnswerCurrentQuestion, getRandomDelay(window.qh.humanLikeDelay));
}
}
// 获取当前题目
function getCurrentQuestion() {
try {
// 尝试在主文档中查找题目
let questionElement = document.querySelector('.timu');
if (questionElement) {
const title = questionElement.querySelector('.subject')?.textContent.trim();
if (title) {
return {
element: questionElement,
title: title,
isInIframe: false
};
}
}
// 尝试在iframe中查找题目
const frames = document.querySelectorAll('iframe');
for (const frame of frames) {
try {
const frameDoc = frame.contentDocument || frame.contentWindow.document;
questionElement = frameDoc.querySelector('.timu');
if (questionElement) {
const title = questionElement.querySelector('.subject')?.textContent.trim();
if (title) {
return {
element: questionElement,
title: title,
isInIframe: true,
iframe: frame
};
}
}
} catch (e) {
console.error('无法访问iframe内容:', e);
}
}
return null;
} catch (e) {
console.error('获取当前题目出错:', e);
return null;
}
}
// 在题库中查找匹配的题目
function findQuestionInBank(questionTitle) {
if (!questionTitle || !window.qh.savedQuestionBank || window.qh.savedQuestionBank.length === 0) {
return null;
}
// 清理题目文本,移除题号和多余空格
const cleanTitle = questionTitle.replace(/^\d+[\.\、\s]+/, '').trim();
// 在题库中查找完全匹配的题目
const exactMatch = window.qh.savedQuestionBank.find(q => {
const bankTitle = q.question.replace(/^\d+[\.\、\s]+/, '').trim();
return bankTitle === cleanTitle;
});
if (exactMatch) {
return exactMatch;
}
// 如果没有找到完全匹配,尝试查找相似度高的题目
const threshold = 0.8; // 相似度阈值
let bestMatch = null;
let highestSimilarity = 0;
for (const q of window.qh.savedQuestionBank) {
const bankTitle = q.question.replace(/^\d+[\.\、\s]+/, '').trim();
const similarity = calculateSimilarity(cleanTitle, bankTitle);
if (similarity > threshold && similarity > highestSimilarity) {
highestSimilarity = similarity;
bestMatch = q;
}
}
return bestMatch;
}
// 计算两个字符串的相似度(使用Levenshtein距离)
function calculateSimilarity(str1, str2) {
if (!str1 || !str2) return 0;
// 如果字符串完全相同,直接返回1
if (str1 === str2) return 1;
// 计算Levenshtein距离
const len1 = str1.length;
const len2 = str2.length;
// 创建距离矩阵
const matrix = [];
for (let i = 0; i <= len1; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= len2; j++) {
matrix[0][j] = j;
}
// 填充矩阵
for (let i = 1; i <= len1; i++) {
for (let j = 1; j <= len2; j++) {
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
matrix[i][j] = Math.min(
matrix[i - 1][j] + 1, // 删除
matrix[i][j - 1] + 1, // 插入
matrix[i - 1][j - 1] + cost // 替换
);
}
}
// 计算相似度
const distance = matrix[len1][len2];
const maxLen = Math.max(len1, len2);
return 1 - distance / maxLen;
}
// 保存当前题目到题库
function saveCurrentQuestion(currentQuestion) {
try {
if (!currentQuestion || !currentQuestion.element) return;
// 获取题目文本
const title = currentQuestion.title;
if (!title) return;
// 生成题目ID
const questionId = generateQuestionId(title);
// 获取选项
let options = [];
let optionElements;
if (currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
optionElements = frameDoc.querySelectorAll('.option');
} else {
optionElements = document.querySelectorAll('.option');
}
if (optionElements && optionElements.length > 0) {
options = Array.from(optionElements).map(option => option.textContent.trim());
}
// 创建新题目对象
const newQuestion = {
id: questionId,
question: title,
options: options,
answer: '', // 暂时没有答案
analysis: '',
updateTime: Date.now()
};
// 检查题目是否已存在
const existingIndex = window.qh.savedQuestionBank.findIndex(q => q.id === questionId);
if (existingIndex === -1) {
// 添加新题目
window.qh.savedQuestionBank.push(newQuestion);
console.log('添加新题目到题库:', title);
} else {
// 更新已有题目的选项
window.qh.savedQuestionBank[existingIndex].options = options;
window.qh.savedQuestionBank[existingIndex].updateTime = Date.now();
console.log('更新题库中的题目选项:', title);
}
// 保存题库
GM_setValue('qh-question-bank', window.qh.savedQuestionBank);
// 更新题库状态显示
const statusElement = document.getElementById('qh-question-status');
if (statusElement) {
statusElement.textContent = `题库状态: 已保存 ${window.qh.savedQuestionBank.length} 道题目`;
}
} catch (e) {
console.error('保存当前题目出错:', e);
}
}
// 生成题目ID
function generateQuestionId(questionText) {
// 使用题目文本的哈希值作为ID
let hash = 0;
for (let i = 0; i < questionText.length; i++) {
const char = questionText.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // 转换为32位整数
}
return 'q_' + Math.abs(hash).toString(16);
}
// 选择答案
function selectAnswer(currentQuestion, matchedQuestion) {
try {
if (!currentQuestion || !matchedQuestion || !matchedQuestion.answer) {
console.log('没有足够的信息来选择答案');
return;
}
// 获取答案
const answer = matchedQuestion.answer.trim();
if (!answer) {
console.log('答案为空');
return;
}
console.log('准备选择答案:', answer);
// 获取选项元素
let optionElements;
if (currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
optionElements = frameDoc.querySelectorAll('.option');
} else {
optionElements = document.querySelectorAll('.option');
}
if (!optionElements || optionElements.length === 0) {
console.log('未找到选项元素');
return;
}
// 根据答案类型选择不同的处理方式
if (answer.length === 1 && /[A-Z]/.test(answer)) {
// 单选题,答案是A、B、C、D等字母
const index = answer.charCodeAt(0) - 'A'.charCodeAt(0);
if (index >= 0 && index < optionElements.length) {
console.log('选择单选答案:', answer, '索引:', index);
simulateClick(optionElements[index], currentQuestion);
}
} else if (/^[A-Z]+$/.test(answer)) {
// 多选题,答案是多个字母组合,如ABC
for (let i = 0; i < answer.length; i++) {
const index = answer.charCodeAt(i) - 'A'.charCodeAt(0);
if (index >= 0 && index < optionElements.length) {
console.log('选择多选答案:', answer[i], '索引:', index);
simulateClick(optionElements[index], currentQuestion);
}
}
} else {
// 答案是文本,需要匹配选项内容
for (let i = 0; i < optionElements.length; i++) {
const optionText = optionElements[i].textContent.trim();
if (optionText.includes(answer) || answer.includes(optionText)) {
console.log('通过文本匹配选择答案:', optionText);
simulateClick(optionElements[i], currentQuestion);
break;
}
}
}
} catch (e) {
console.error('选择答案出错:', e);
}
}
// 前往下一题
function goToNextQuestion(currentQuestion) {
try {
// 如果不再自动答题,则退出
if (!window.qh.isAutoAnswering) {
return;
}
// 检查是否已完成所有题目
if (isExamFinished(currentQuestion)) {
console.log('已完成所有题目,准备提交');
autoSubmitExam(currentQuestion);
return;
}
// 获取当前题目编号
const currentNumber = getCurrentQuestionNumber(currentQuestion);
const currentTitle = currentQuestion ? currentQuestion.title : '';
console.log('当前题目编号:', currentNumber, '标题:', currentTitle);
// 查找下一题按钮
let nextBtn;
if (currentQuestion && currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
nextBtn = frameDoc.getElementById('next') || frameDoc.querySelector('.next');
} else {
nextBtn = document.getElementById('next') || document.querySelector('.next');
}
if (nextBtn) {
console.log('找到下一题按钮,准备点击');
// 禁用下一题按钮,防止重复点击
nextBtn.disabled = true;
// 模拟点击下一题按钮
simulateClick(nextBtn, currentQuestion);
// 使用一个函数来等待页面加载新题目
waitForNextQuestion(currentTitle, currentNumber, currentQuestion);
} else {
console.log('未找到下一题按钮');
// 尝试查找交卷按钮
let submitBtn;
if (currentQuestion && currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
submitBtn = frameDoc.getElementById('jiaojuan') || frameDoc.getElementById('jiaojuanBtn');
} else {
submitBtn = document.getElementById('jiaojuan') || document.getElementById('jiaojuanBtn');
}
if (submitBtn && submitBtn.style.display !== 'none') {
console.log('找到交卷按钮,准备提交');
autoSubmitExam(currentQuestion);
} else {
// 延迟后再次尝试
window.qh.autoAnswerInterval = setTimeout(autoAnswerCurrentQuestion, getRandomDelay(window.qh.humanLikeDelay));
}
}
} catch (e) {
console.error('前往下一题出错:', e);
// 出错后延迟重试
window.qh.autoAnswerInterval = setTimeout(autoAnswerCurrentQuestion, getRandomDelay(window.qh.humanLikeDelay));
}
}
// 等待下一题加载
function waitForNextQuestion(previousTitle, previousNumber, currentQuestion) {
// 如果不再自动答题,则退出
if (!window.qh.isAutoAnswering) {
return;
}
// 获取当前题目
const newQuestion = getCurrentQuestion();
if (!newQuestion) {
// 如果没有找到新题目,延迟后再次检查
window.qh.autoAnswerInterval = setTimeout(() => {
waitForNextQuestion(previousTitle, previousNumber, currentQuestion);
}, 500);
return;
}
// 检查是否已经切换到新题目
if (newQuestion.title === previousTitle) {
// 如果题目标题没有变化,检查题号是否变化
const newNumber = getCurrentQuestionNumber(newQuestion);
if (newNumber === previousNumber) {
// 如果题号也没有变化,延迟后再次检查
window.qh.autoAnswerInterval = setTimeout(() => {
waitForNextQuestion(previousTitle, previousNumber, currentQuestion);
}, 500);
return;
}
}
// 已切换到新题目,继续自动答题
console.log('已切换到新题目:', newQuestion.title);
window.qh.autoAnswerInterval = setTimeout(autoAnswerCurrentQuestion, getRandomDelay(window.qh.humanLikeDelay));
}
// 获取当前题目编号
function getCurrentQuestionNumber(currentQuestion) {
try {
if (!currentQuestion || !currentQuestion.element) return -1;
// 尝试从题目文本中提取编号
const titleMatch = currentQuestion.title.match(/^(\d+)[\.、\s]/);
if (titleMatch && titleMatch[1]) {
return parseInt(titleMatch[1]);
}
// 尝试从题目导航中获取当前题号
let navElement;
if (currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
navElement = frameDoc.querySelector('.timu_index .on');
} else {
navElement = document.querySelector('.timu_index .on');
}
if (navElement) {
const navText = navElement.textContent.trim();
const navMatch = navText.match(/(\d+)/);
if (navMatch && navMatch[1]) {
return parseInt(navMatch[1]);
}
}
return -1;
} catch (e) {
console.error('获取当前题目编号出错:', e);
return -1;
}
}
// 检查是否已完成所有题目
function isExamFinished(currentQuestion) {
try {
if (!currentQuestion) return false;
// 检查是否有交卷按钮
let submitBtn;
if (currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
submitBtn = frameDoc.getElementById('jiaojuan') || frameDoc.getElementById('jiaojuanBtn');
} else {
submitBtn = document.getElementById('jiaojuan') || document.getElementById('jiaojuanBtn');
}
if (submitBtn && submitBtn.style.display !== 'none') {
// 检查是否所有题目都已作答
let allAnswered = true;
let navElements;
if (currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
navElements = frameDoc.querySelectorAll('.timu_index li');
} else {
navElements = document.querySelectorAll('.timu_index li');
}
if (navElements && navElements.length > 0) {
for (const navElement of navElements) {
// 检查是否有未作答的题目(通常未作答的题目没有特定的类)
if (!navElement.classList.contains('on') && !navElement.classList.contains('hasdo')) {
allAnswered = false;
break;
}
}
}
return allAnswered;
}
return false;
} catch (e) {
console.error('检查是否已完成所有题目出错:', e);
return false;
}
}
// 自动提交考试
function autoSubmitExam(currentQuestion) {
try {
// 如果不再自动答题,则退出
if (!window.qh.isAutoAnswering) {
return;
}
console.log('准备自动提交考试');
// 查找交卷按钮
let submitBtn;
if (currentQuestion && currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
submitBtn = frameDoc.getElementById('jiaojuan') || frameDoc.getElementById('jiaojuanBtn');
} else {
submitBtn = document.getElementById('jiaojuan') || document.getElementById('jiaojuanBtn');
}
if (submitBtn) {
console.log('找到交卷按钮,延迟后提交');
// 延迟一段时间后提交,模拟人类行为
window.qh.autoAnswerInterval = setTimeout(() => {
// 模拟点击交卷按钮
simulateClick(submitBtn, currentQuestion);
// 延迟后处理确认对话框
setTimeout(() => {
handleSubmitConfirmation(currentQuestion);
}, 1000);
}, getRandomDelay(window.qh.autoSubmitDelay));
} else {
console.log('未找到交卷按钮');
stopAutoAnswer();
}
} catch (e) {
console.error('自动提交考试出错:', e);
stopAutoAnswer();
}
}
// 处理提交确认对话框
function handleSubmitConfirmation(currentQuestion) {
try {
// 查找确认按钮
let confirmBtn;
if (currentQuestion && currentQuestion.isInIframe) {
const frameDoc = currentQuestion.iframe.contentDocument || currentQuestion.iframe.contentWindow.document;
confirmBtn = frameDoc.querySelector('.layui-layer-btn0') ||
frameDoc.querySelector('.messager-button .l-btn');
} else {
confirmBtn = document.querySelector('.layui-layer-btn0') ||
document.querySelector('.messager-button .l-btn');
}
if (confirmBtn) {
console.log('找到确认按钮,点击确认');
simulateClick(confirmBtn, currentQuestion);
// 停止自动答题
stopAutoAnswer();
// 更新状态
updateStatus('考试已提交');
} else {
console.log('未找到确认按钮,可能已经提交');
stopAutoAnswer();
}
} catch (e) {
console.error('处理提交确认对话框出错:', e);
stopAutoAnswer();
}
}
})();
// 章节考试模块
const ChapterExamModule = (function() {
'use strict';
// 私有变量
const config = {
retryDelay: 1000,
autoAnswerDelay: 3000,
nextExamDelay: 3000,
logWindowWidth: 400,
logWindowHeight: 300
};
// 日志窗口状态
let logWindow = null;
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
// 私有方法
function updateStatus(message) {
if (window.qh && window.qh.updateStatus) {
window.qh.updateStatus(message);
}
addLog(message);
}
function closePanel() {
const panel = document.getElementById('qh-chapter-exam-panel');
const overlay = document.getElementById('qh-chapter-exam-overlay');
if (panel) panel.style.display = 'none';
if (overlay) overlay.style.display = 'none';
}
function showError(message) {
console.error(message);
addLog(`错误: ${message}`, 'error');
}
// 创建日志窗口
function createLogWindow() {
if (logWindow) return;
logWindow = document.createElement('div');
logWindow.id = 'qh-log-window';
logWindow.className = 'qh-log-window';
logWindow.innerHTML = `
<div class="qh-log-header">
<span>考试日志</span>
<div class="qh-log-controls">
<button class="qh-log-minimize">_</button>
<button class="qh-log-close">×</button>
</div>
</div>
<div class="qh-log-content"></div>
`;
// 添加样式
const style = document.createElement('style');
style.textContent = `
.qh-log-window {
position: fixed;
top: 20px;
right: 20px;
width: ${config.logWindowWidth}px;
height: ${config.logWindowHeight}px;
background: rgba(255, 255, 255, 0.95);
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
z-index: 10000;
display: flex;
flex-direction: column;
font-family: Arial, sans-serif;
overflow: hidden;
resize: both;
}
.qh-log-header {
background: linear-gradient(135deg, #00a8cc, #0062bd);
color: white;
padding: 8px 12px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: move;
user-select: none;
}
.qh-log-controls {
display: flex;
gap: 8px;
}
.qh-log-controls button {
background: none;
border: none;
color: white;
cursor: pointer;
font-size: 16px;
padding: 0 4px;
opacity: 0.8;
transition: opacity 0.2s;
}
.qh-log-controls button:hover {
opacity: 1;
}
.qh-log-content {
flex: 1;
padding: 12px;
overflow-y: auto;
font-size: 14px;
line-height: 1.5;
}
.qh-log-item {
margin-bottom: 8px;
padding: 4px 8px;
border-radius: 4px;
background: #f5f5f5;
}
.qh-log-item.error {
background: #ffebee;
color: #c62828;
}
.qh-log-item.success {
background: #e8f5e9;
color: #2e7d32;
}
.qh-log-item.info {
background: #e3f2fd;
color: #1565c0;
}
`;
document.head.appendChild(style);
// 添加拖拽功能
const header = logWindow.querySelector('.qh-log-header');
header.addEventListener('mousedown', startDragging);
// 添加控制按钮事件
logWindow.querySelector('.qh-log-minimize').addEventListener('click', () => {
const content = logWindow.querySelector('.qh-log-content');
content.style.display = content.style.display === 'none' ? 'block' : 'none';
});
logWindow.querySelector('.qh-log-close').addEventListener('click', () => {
logWindow.style.display = 'none';
});
document.body.appendChild(logWindow);
}
// 拖拽相关函数
function startDragging(e) {
if (e.target.tagName === 'BUTTON') return;
isDragging = true;
const rect = logWindow.getBoundingClientRect();
dragOffset = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', stopDragging);
}
function drag(e) {
if (!isDragging) return;
const x = e.clientX - dragOffset.x;
const y = e.clientY - dragOffset.y;
logWindow.style.left = `${x}px`;
logWindow.style.top = `${y}px`;
logWindow.style.right = 'auto';
}
function stopDragging() {
isDragging = false;
document.removeEventListener('mousemove', drag);
document.removeEventListener('mouseup', stopDragging);
}
// 添加日志
function addLog(message, type = 'info') {
if (!logWindow) {
createLogWindow();
}
const content = logWindow.querySelector('.qh-log-content');
const item = document.createElement('div');
item.className = `qh-log-item ${type}`;
item.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
content.appendChild(item);
content.scrollTop = content.scrollHeight;
}
// 查找章节考试链接
function findChapterExamLinks() {
return new Promise((resolve) => {
const examLinks = [];
const frames = document.querySelectorAll('iframe');
addLog(`找到 ${frames.length} 个框架`);
if (frames.length === 0) {
addLog('未找到任何框架');
resolve(examLinks);
return;
}
const frame = frames[0];
try {
const frameDoc = frame.contentDocument || frame.contentWindow.document;
addLog('正在检查框架: ' + frame.src);
// 点击"进行考试"标签
const frameExamTab = frameDoc.querySelector('.list[onclick="tabExam(this)"]');
if (frameExamTab) {
addLog('在框架中找到进行考试标签');
simulateClick(frameExamTab, { isInIframe: true, iframe: frame });
}
// 等待考试列表加载
setTimeout(() => {
const examList = frameDoc.getElementById('examList');
if (examList) {
addLog('在框架中找到考试列表');
const examButtons = examList.querySelectorAll('.btn-outline-success');
addLog(`找到 ${examButtons.length} 个考试按钮`);
examButtons.forEach(button => {
const onclickAttr = button.getAttribute('onclick');
if (onclickAttr && onclickAttr.startsWith('goexam(')) {
const match = onclickAttr.match(/goexam\((\d+),(\d+)\)/);
if (match) {
const examId = match[1];
const examType = match[2];
const examInfo = button.closest('.list').querySelector('.info')?.textContent.trim();
examLinks.push({
element: button,
text: examInfo || `章节考试 ${examId}`,
examId: examId,
examType: examType,
isInIframe: true,
iframe: frame
});
}
}
});
}
addLog(`框架处理完成,找到考试数量: ${examLinks.length}`);
resolve(examLinks);
}, config.retryDelay);
} catch (e) {
addLog('访问框架内容时出错: ' + e.message, 'error');
resolve(examLinks);
}
});
}
// 显示章节考试面板
function showChapterExamPanel() {
try {
// 创建日志窗口
createLogWindow();
// 检查是否已存在章节考试面板
if (document.getElementById('qh-chapter-exam-panel')) {
document.getElementById('qh-chapter-exam-panel').style.display = 'block';
document.getElementById('qh-chapter-exam-overlay').style.display = 'block';
return;
}
// 创建遮罩层
const overlay = document.createElement('div');
overlay.className = 'qh-question-overlay';
overlay.id = 'qh-chapter-exam-overlay';
document.body.appendChild(overlay);
// 创建章节考试面板
const panel = document.createElement('div');
panel.className = 'qh-question-panel';
panel.id = 'qh-chapter-exam-panel';
panel.innerHTML = `
<div class="qh-question-title">
章节考试
<span class="qh-question-close" id="qh-chapter-exam-close">×</span>
</div>
<div class="qh-question-content" id="qh-chapter-exam-content">
<div style="text-align: center; padding: 20px;">正在查找章节考试...</div>
</div>
<div class="qh-question-btns">
<button class="qh-question-btn" id="qh-start-chapter-exam-btn">开始章节考试</button>
<button class="qh-question-btn" id="qh-auto-chapter-exam-btn">自动完成章节考试</button>
</div>
`;
document.body.appendChild(panel);
// 绑定事件
bindPanelEvents();
// 显示面板
document.getElementById('qh-chapter-exam-panel').style.display = 'block';
document.getElementById('qh-chapter-exam-overlay').style.display = 'block';
// 查找章节考试
findChapterExamLinks().then(examLinks => {
addLog(`查找考试完成,找到数量: ${examLinks.length}`);
if (examLinks.length === 0) {
showNoExamsFound();
} else {
displayChapterExams(examLinks);
}
});
} catch (e) {
addLog('显示章节考试面板出错: ' + e.message, 'error');
}
}
// 绑定面板事件
function bindPanelEvents() {
// 关闭按钮
document.getElementById('qh-chapter-exam-close').addEventListener('click', closePanel);
// 开始章节考试按钮
document.getElementById('qh-start-chapter-exam-btn').addEventListener('click', startChapterExam);
// 自动完成章节考试按钮
document.getElementById('qh-auto-chapter-exam-btn').addEventListener('click', autoCompleteChapterExam);
}
// 显示未找到考试
function showNoExamsFound() {
const contentElement = document.getElementById('qh-chapter-exam-content');
if (contentElement) {
contentElement.innerHTML = `
<div style="text-align: center; padding: 20px;">
未找到章节考试,请确保您已点击"进行考试"标签。
<br><br>
<button class="qh-question-btn" onclick="ChapterExamModule.retryFindExams()">重试</button>
</div>
`;
}
}
// 显示章节考试列表
function displayChapterExams(examLinks) {
const contentElement = document.getElementById('qh-chapter-exam-content');
if (!contentElement) return;
if (examLinks.length === 0) {
contentElement.innerHTML = `
<div style="text-align: center; padding: 20px;">
未找到章节考试,请确保您在课程学习页面。
</div>
`;
return;
}
// 构建HTML
let html = '<div style="margin-bottom: 15px;">找到以下章节考试:</div>';
examLinks.forEach((link, index) => {
html += `
<div class="qh-question-item" data-index="${index}">
<div class="qh-question-text">${index + 1}. ${link.text}</div>
<button class="qh-question-btn" style="width: 100%; margin-top: 10px;" onclick="ChapterExamModule.startExam(${index})">开始考试</button>
</div>
`;
});
contentElement.innerHTML = html;
}
// 开始章节考试
function startChapterExam() {
try {
findChapterExamLinks().then(examLinks => {
if (examLinks.length === 0) {
showError('未找到章节考试链接');
return;
}
const examLink = examLinks[0];
if (examLink) {
// 直接点击考试按钮
if (examLink.isInIframe) {
simulateClick(examLink.element, { isInIframe: true, iframe: examLink.iframe });
} else {
simulateClick(examLink.element);
}
addLog(`开始考试: ${examLink.text}`);
closePanel();
}
});
} catch (e) {
showError('开始章节考试出错: ' + e.message);
}
}
// 自动完成章节考试
function autoCompleteChapterExam() {
try {
findChapterExamLinks().then(examLinks => {
if (examLinks.length === 0) {
showError('未找到章节考试链接');
return;
}
closePanel();
autoCompleteExams(examLinks, 0);
});
} catch (e) {
showError('自动完成章节考试出错: ' + e.message);
}
}
// 自动完成所有考试
function autoCompleteExams(examLinks, index) {
if (index >= examLinks.length) {
addLog('所有章节考试已完成', 'success');
return;
}
const link = examLinks[index];
addLog(`正在完成第 ${index + 1}/${examLinks.length} 个章节考试: ${link.text}`);
if (link) {
// 直接点击考试按钮
if (link.isInIframe) {
simulateClick(link.element, { isInIframe: true, iframe: link.iframe });
} else {
simulateClick(link.element);
}
// 延迟后开始自动答题
setTimeout(() => {
// 设置自动答题完成后的回调
const originalStopAutoAnswer = window.stopAutoAnswer;
window.stopAutoAnswer = function() {
// 恢复原始函数
window.stopAutoAnswer = originalStopAutoAnswer;
originalStopAutoAnswer();
// 延迟后继续下一个考试
setTimeout(() => {
autoCompleteExams(examLinks, index + 1);
}, config.nextExamDelay);
};
// 开始自动答题
startAutoAnswer();
}, config.autoAnswerDelay);
}
}
// 重试查找考试
function retryFindExams() {
const contentElement = document.getElementById('qh-chapter-exam-content');
if (contentElement) {
contentElement.innerHTML = '<div style="text-align: center; padding: 20px;">正在重新查找章节考试...</div>';
}
findChapterExamLinks().then(examLinks => {
if (examLinks.length === 0) {
showNoExamsFound();
} else {
displayChapterExams(examLinks);
}
});
}
// 公开API
return {
showChapterExamPanel,
retryFindExams,
startExam: function(index) {
findChapterExamLinks().then(examLinks => {
const link = examLinks[index];
if (link) {
// 直接点击考试按钮
if (link.isInIframe) {
simulateClick(link.element, { isInIframe: true, iframe: link.iframe });
} else {
simulateClick(link.element);
}
addLog(`开始考试: ${link.text}`);
closePanel();
}
});
}
};
})();
// 将章节测试模块添加到全局作用域
window.ChapterExamModule = ChapterExamModule;