// ==UserScript== // @name 『不知名』学习通自动学习助手-免费题库-高分题库 // @version 3.0.3 // @namespace bzm // @description 学习通助手,支持视频,作业、考试自动答题,支持闯关模式。免费高分题库免费获取key。 // @match *://*.chaoxing.com/* // @run-at document-end // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_info // @grant GM_getResourceText // @grant GM_openInTab // @icon http://pan-yz.chaoxing.com/favicon.ico // @original-script https://scriptcat.org/zh-CN/script-show-page/5717 // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js // @require https://cdn.bootcdn.net/ajax/libs/limonte-sweetalert2/11.1.0/sweetalert2.all.min.js // @connect tk.swk.tw // @connect so.swk.tw // @connect tk.n1t.cn //@tag 无言题库 //@tag 搜题助手 //@tag 免费搜题 //@tag 可选付费 // @antifeature payment 脚本存在第三方答题接口付费功能 // ==/UserScript== /*********************************自定义配置区******************************************************** */ var setting = { showBox: 1, // 显示脚本浮窗 maskImg: 1, // 显示皮卡丘 task: 0, // 只处理任务点任务 video: 1, // 处理视频 audio: 1, // 处理音频 rate: 1, // 视频/音频倍速 review: 0, // 复习模式 work: 1, // 测验自动处理 time: 5000, // 答题时间间隔(ms) sub: 0, // 测验自动提交 force: 0, // 测验强制提交 decrypt: 1, // 字体解密 examTurn: 0, // 考试自动跳转 examTurnTime: 0, // 考试自动跳转随机间隔 goodStudent: 0, // 好学生模式 alterTitle: 1, // 答案插入题目 autoLogin: 0, // 自动登录 phone: '', // 登录手机号 password: '' // 登录密码 } /**************************************************************************************************/ var _w = unsafeWindow, _l = location, _d = _w.document, $ = _w.jQuery || top.jQuery, UE = _w.UE, md5 = window.md5, Typr = window.Typr; // API配置 - 多接口支持 var API_URLS = [ "https://tk.swk.tw/api/search.php", "https://so.swk.tw/api/search.php", "https://tk.n1t.cn/api/search.php" ]; var CURRENT_API_INDEX = 0; var IS_TESTING_KEY = false; function getApiKey() { var key = GM_getValue('api_key', ''); return key; } function hasApiKey() { var key = getApiKey(); return key && key.trim() !== ''; } function getQuotaInfo() { return { remaining: GM_getValue('quota_remaining', 0), free_remaining: GM_getValue('quota_free_remaining', 0), recharge_balance: GM_getValue('quota_recharge_balance', 0), today_free_usage: GM_getValue('quota_today_free_usage', 0) }; } var quotaInfo = getQuotaInfo(); var _mlist = null; var _defaults = null; var _domList = null; var $subBtn, $saveBtn, $frame_c, $okBtn; var isProcessing = false; var isBoxHidden = false; var pikaqiuAdded = false; var currentVideoInterval = null; var isJumping = false; var isInitialized = false; // 日志队列 var logQueue = []; var logTimer = null; // ==================== 题型处理工具函数 ==================== function getQuestionOptionsData(type, $question, $opts) { var result = { optionsData: [], optsText: [], $opts: $opts || [] }; if (type == 0 || type == 1) { if (!$opts || $opts.length === 0) { result.$opts = type == 0 ? $question.find('.answerList.singleChoice li, .Py-mian1 .answerList.singleChoice li, .stem_answer .answer_p, .clearfix.answerBg .fl.answer_p, .Zy_ulTop li a') : $question.find('.answerList.multiChoice li, .Py-mian1 .answerList.multiChoice li, .stem_answer .answer_p, .clearfix.answerBg .fl.answer_p, .Zy_ulTop li a'); } result.$opts.each(function() { var text = tidyStr($(this).html()); result.optsText.push(text); }); result.optionsData = result.optsText; } else if (type == 2) { var blankCount = getBlankInputCount($question); result.optionsData = [blankCount.toString()]; log(`📝 填空题传入空数量: ${blankCount}`, 'blue'); } else if (type == 3) { result.optionsData = ["对", "错"]; log(`📝 判断题传入固定选项: ["对","错"]`, 'blue'); } else if (type == 4) { result.optionsData = ["1"]; log(`📝 简答题传入固定参数: ["1"]`, 'blue'); } return result; } function fillSingleChoiceAnswer($question, $opts, optsText, answer, isPhoneMode) { var idx = optsText.findIndex(function(t) { return t == answer; }); if (idx != -1) { if (setting.goodStudent) { var $target = $($opts[idx]).parent ? $($opts[idx]).parent() : $($opts[idx]); $target.find('span').css('font-weight', 'bold'); log('📝 好学生模式:答案已加粗,未自动选择', 'blue'); } else { $($opts[idx]).click(); if ($($opts[idx]).parent) $($opts[idx]).parent().click(); } } } function fillMultiChoiceAnswer($question, $opts, optsText, answer) { var ansArr = splitAnswer(answer); $opts.each(function(i, t) { if (ansArr.includes(optsText[i])) { if (setting.goodStudent) { $($opts[i]).parent().find('span').css('font-weight', 'bold'); } else { setTimeout(function() { $($opts[i]).click(); if ($($opts[i]).parent) $($opts[i]).parent().click(); }, 300); } } }); } function fillJudgmentAnswer($question, $opts, answer) { var isTrue = ['正确','是','对','√','T','ri'].some(function(k) { return answer.includes(k); }); $opts.each(function(i, t) { var txt = tidyStr($(t).html()); var shouldSelect = (isTrue && (txt == '对' || txt == '√' || txt == '正确')) || (!isTrue && (txt == '错' || txt == '×' || txt == '错误')); if (shouldSelect) { if (setting.goodStudent) { $($opts[i]).parent().find('span').css('font-weight', 'bold'); } else { $($opts[i]).click(); if ($($opts[i]).parent) $($opts[i]).parent().click(); } } }); } function fillBlankAnswer($question, answer, isPhoneMode, contextWindow) { var answerList = splitAnswer(answer); log(`📝 填空题答案: ${answerList.join(' | ')}`, 'blue'); if (isPhoneMode) { fillBlankAnswerPhone($question, answerList, contextWindow); } else { fillBlankAnswerPC($question, answerList); } } function fillBlankAnswerPhone($question, answerList, contextWindow) { var $allInputs = $question.find('.blankList2 input, input[type="text"][name*="answer"]'); if ($allInputs.length) { var uniqueInputs = []; var seen = new Set(); $allInputs.each(function() { var name = $(this).attr('name'); var id = $(this).attr('id'); var key = name || id || $(this).index(); if (!seen.has(key)) { seen.add(key); uniqueInputs.push(this); } }); log(`📝 找到 ${uniqueInputs.length} 个填空输入框,准备填写`, 'blue'); $(uniqueInputs).each(function(i) { setTimeout(() => { var answerValue = answerList[i] !== undefined ? answerList[i] : (answerList[0] || ''); $(this).val(answerValue); $(this).trigger('input').trigger('change'); log(`✅ 填空题第${i+1}空已填写: ${answerValue}`, 'green'); }, i * 200); }); return true; } var $editorBlocks = $question.find('[data-editorindex]'); if ($editorBlocks.length) { var uniqueEditors = []; var seenIndices = new Set(); $editorBlocks.each(function() { var idx = $(this).attr('data-editorindex'); if (idx && !seenIndices.has(idx)) { seenIndices.add(idx); uniqueEditors.push(this); } }); log(`📝 找到 ${uniqueEditors.length} 个编辑器,准备填写`, 'blue'); uniqueEditors.forEach(function(editor, i) { var editorIndex = $(editor).attr('data-editorindex'); var itemId = $(editor).attr('data-itemid'); setTimeout(() => { try { var ueditor = null; if (contextWindow && contextWindow.editors && contextWindow.editors[editorIndex]) { ueditor = contextWindow.editors[editorIndex].ueditor; } if (!ueditor && contextWindow && contextWindow.UE && contextWindow.UE.instants) { var instantKey = 'ueditorInstant' + editorIndex; ueditor = contextWindow.UE.instants[instantKey]; } if (!ueditor && itemId && contextWindow && contextWindow.UE && contextWindow.UE.getEditor) { ueditor = contextWindow.UE.getEditor('ananas-editor-answer' + itemId); } if (ueditor) { var answerValue = answerList[i] !== undefined ? answerList[i] : (answerList[0] || ''); ueditor.setContent(answerValue); log(`✅ 填空题第${i+1}空已填写: ${answerValue}`, 'green'); } if (itemId) { var answerValue = answerList[i] !== undefined ? answerList[i] : (answerList[0] || ''); $('#answer' + itemId).val(answerValue).trigger('change'); } } catch(e) {} }, i * 300); }); return true; } return false; } function fillBlankAnswerPC($question, answerList) { var $pcInputs = $question.find('.Zy_ulTk .XztiHover1 textarea, .stem_answer .Answer .divText .textDIV textarea, .subEditor textarea'); if ($pcInputs.length) { var uniquePCInputs = []; var seenPC = new Set(); $pcInputs.each(function() { var id = $(this).attr('id'); var name = $(this).attr('name'); var key = id || name || $(this).index(); if (!seenPC.has(key)) { seenPC.add(key); uniquePCInputs.push(this); } }); log(`📝 找到 ${uniquePCInputs.length} 个填空输入框 (PC),准备填写`, 'blue'); $(uniquePCInputs).each(function(i) { setTimeout(() => { var $this = $(this); var answerValue = answerList[i] !== undefined ? answerList[i] : (answerList[0] || ''); if (UE && UE.getEditor && UE.getEditor($this.attr('id'))) { UE.getEditor($this.attr('id')).setContent(answerValue); } else { $this.val(answerValue); $this.trigger('input').trigger('change'); } log(`✅ 填空题第${i+1}空已填写: ${answerValue}`, 'green'); }, i * 200); }); return true; } return false; } function fillShortAnswer($question, answer, isPhoneMode, contextWindow) { log(`📝 简答题答案: ${answer.substring(0, 100)}...`, 'blue'); if (isPhoneMode) { return fillShortAnswerPhone($question, answer, contextWindow); } return fillShortAnswerPC($question, answer); } function fillShortAnswerPhone($question, answer, contextWindow) { var $editorBlocks = $question.find('[data-editorindex]'); if ($editorBlocks.length) { $editorBlocks.each(function(i) { var editorIndex = $(this).attr('data-editorindex'); var itemId = $(this).attr('data-itemid'); setTimeout(() => { try { var ueditor = null; if (contextWindow && contextWindow.editors && contextWindow.editors[editorIndex]) { ueditor = contextWindow.editors[editorIndex].ueditor; } if (!ueditor && contextWindow && contextWindow.UE && contextWindow.UE.instants) { var instantKey = 'ueditorInstant' + editorIndex; ueditor = contextWindow.UE.instants[instantKey]; } if (!ueditor && itemId && contextWindow && contextWindow.UE && contextWindow.UE.getEditor) { ueditor = contextWindow.UE.getEditor('ananas-editor-answer' + itemId); } if (ueditor) { ueditor.setContent(answer); log('✅ 简答题答案已填写', 'green'); } if (itemId) { $('#answer' + itemId).val(answer).trigger('change'); } } catch(e) {} }, 300); }); return true; } var $textarea = $question.find('textarea[name^="answer"], .answerTxt textarea'); if ($textarea.length) { $textarea.val(answer); $textarea.trigger('input').trigger('change'); return true; } return false; } function fillShortAnswerPC($question, answer) { var $ueTextarea = $question.find('textarea[name^="answerEditor"], .eidtDiv textarea, .divText textarea'); if ($ueTextarea.length) { var id = $ueTextarea.first().attr('id'); if (id && UE && UE.getEditor && UE.getEditor(id)) { try { UE.getEditor(id).setContent(answer); return true; } catch(e) {} } $ueTextarea.val(answer); $ueTextarea.trigger('input').trigger('change'); return true; } return false; } function fillAnswerByType(type, $question, answer, options, isPhoneMode, contextWindow) { var { $opts, optsText } = options; switch(type) { case 0: fillSingleChoiceAnswer($question, $opts, optsText, answer, isPhoneMode); break; case 1: fillMultiChoiceAnswer($question, $opts, optsText, answer); break; case 2: fillBlankAnswer($question, answer, isPhoneMode, contextWindow); break; case 3: fillJudgmentAnswer($question, $opts, answer); break; case 4: fillShortAnswer($question, answer, isPhoneMode, contextWindow); break; default: log(`⚠️ 未知题型类型: ${type}`, 'orange'); break; } } function getQuestionTitleDom($question, context) { var selectors = { phone: '.Py-m1-title', work: '.Zy_TItle.clearfix > div', exam: 'h3.mark_name', homework: '.mark_name' }; var selector = selectors[context] || selectors.work; return $question.find(selector); } function insertAnswerToTitle($titleDom, answer) { if (!setting.alterTitle) return; var answerHtml = `
📖 ${answer}
`; $titleDom.html($titleDom.html() + answerHtml); } // ==================== API相关函数 ==================== function splitAnswer(answer) { if (!answer) return []; var parts = answer.split(/[#]+/).map(a => a.trim()).filter(a => a !== ''); if (parts.length === 0 && answer.trim() !== '') { return [answer.trim()]; } return parts; } function saveQuotaInfo() { GM_setValue('quota_remaining', quotaInfo.remaining); GM_setValue('quota_free_remaining', quotaInfo.free_remaining); GM_setValue('quota_recharge_balance', quotaInfo.recharge_balance); GM_setValue('quota_today_free_usage', quotaInfo.today_free_usage); } function updateQuotaInfo(newQuotaInfo) { if (newQuotaInfo) { quotaInfo.remaining = newQuotaInfo.remaining !== undefined ? newQuotaInfo.remaining : quotaInfo.remaining; quotaInfo.free_remaining = newQuotaInfo.free_remaining !== undefined ? newQuotaInfo.free_remaining : quotaInfo.free_remaining; quotaInfo.recharge_balance = newQuotaInfo.recharge_balance !== undefined ? newQuotaInfo.recharge_balance : quotaInfo.recharge_balance; quotaInfo.today_free_usage = newQuotaInfo.today_free_usage !== undefined ? newQuotaInfo.today_free_usage : quotaInfo.today_free_usage; saveQuotaInfo(); updateQuotaDisplay(); } } function updateQuotaDisplay() { try { var targetDoc = top.document; if (!targetDoc.querySelector('#quotaInfo')) targetDoc = document; var $quotaInfo = $('#quotaInfo', targetDoc); if ($quotaInfo.length) { var remaining = quotaInfo.remaining; var hasKey = hasApiKey(); if (remaining > 0) { $quotaInfo.html(`📊 剩余次数: ${remaining} | 免费: ${quotaInfo.free_remaining}`); } else if (remaining === 0 && hasKey) { $quotaInfo.html('⚠️ 次数已用完 | 点击充值'); } else if (!hasKey) { $quotaInfo.html('⚠️ 请先设置API密钥'); } else { $quotaInfo.html('📊 剩余次数: 0'); } } } catch(e) {} } function getTopLogContainer() { try { var topDoc = top.document; var container = topDoc.getElementById('ne-21log'); if (container) return $(container); container = document.getElementById('ne-21log'); if (container) return $(container); return null; } catch(e) { return null; } } function flushLogs() { if (logQueue.length === 0) return; var container = getTopLogContainer(); if (container && container.length) { var logsToShow = logQueue.slice(); logQueue = []; for (var i = logsToShow.length - 1; i >= 0; i--) { container.prepend(logsToShow[i]); } container.scrollTop(0); } if (logTimer) { clearTimeout(logTimer); logTimer = null; } } function scheduleFlushLogs() { if (logTimer) return; logTimer = setTimeout(flushLogs, 100); } function log(str, color) { var time = new Date().toLocaleTimeString(); var logHtml = `
`;
$(targetDoc.body).append(imgHtml);
pikaqiuAdded = true;
$('#pikaqiu-img', targetDoc).click(function() {
var $box = $('#ne-21box', targetDoc);
if ($box.length) {
if ($box.css('display') === 'none') {
$box.css('display', 'block');
isBoxHidden = false;
} else {
$box.css('display', 'none');
isBoxHidden = true;
}
}
});
} catch(e) {}
}
$(document).keydown(function(e) {
if (e.keyCode == 120) {
var $box = $('#ne-21box');
if ($box.length === 0) return;
if (isBoxHidden) {
$box.css('display', 'block');
$box.css('opacity', '1');
isBoxHidden = false;
log('📌 面板已显示', 'green');
} else {
$box.css('display', 'none');
isBoxHidden = true;
log('📌 面板已隐藏,按F9键恢复显示', 'blue');
}
}
});
// 切换API接口
function switchToNextApi() {
CURRENT_API_INDEX = (CURRENT_API_INDEX + 1) % API_URLS.length;
log(`🔄 切换到备用接口: ${API_URLS[CURRENT_API_INDEX]}`, 'orange');
}
// 获取当前API地址
function getCurrentApiUrl() {
return API_URLS[CURRENT_API_INDEX];
}
/**
* 发送API请求(支持重试和切换接口)
* @param {string} apiKey API密钥
* @param {string} questionText 问题文本
* @param {string} typeText 题型文本
* @param {Array} optionsData 选项数据
* @param {number} retryCount 重试次数
* @returns {Promise}
*/
function sendApiRequest(apiKey, questionText, typeText, optionsData, retryCount = 0) {
return new Promise((resolve, reject) => {
var formData = `question=${encodeURIComponent(questionText)}&key=${encodeURIComponent(apiKey)}&type=${encodeURIComponent(typeText)}`;
if (optionsData && optionsData.length) {
formData += `&options=${encodeURIComponent(JSON.stringify(optionsData))}`;
}
var currentUrl = getCurrentApiUrl();
var timeoutId = setTimeout(() => {
GM_xmlhttpRequest.abort && GM_xmlhttpRequest.abort();
reject(new Error('请求超时'));
}, 30000);
GM_xmlhttpRequest({
method: 'POST',
url: currentUrl,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: formData,
timeout: 30000,
onload: function(xhr) {
clearTimeout(timeoutId);
try {
var res = JSON.parse(xhr.responseText);
if (res.code == 1 && res.data) {
resolve(res);
} else {
reject(new Error(res.msg || '获取答案失败'));
}
} catch(e) {
reject(new Error('解析响应失败: ' + e.message));
}
},
onerror: function() {
clearTimeout(timeoutId);
reject(new Error('网络请求失败'));
},
ontimeout: function() {
clearTimeout(timeoutId);
reject(new Error('请求超时'));
}
});
});
}
/**
* 获取答案(带重试和接口切换)
*/
function getAnswer(type, questionText, optionsData, retryCount = 0) {
return new Promise((resolve, reject) => {
var apiKey = getApiKey();
if (!apiKey || apiKey.trim() === '') {
log('❌ 请先设置API密钥才能使用自动答题功能', 'red');
reject('NO_API_KEY');
return;
}
quotaInfo = getQuotaInfo();
if (quotaInfo.remaining <= 0 && quotaInfo.free_remaining <= 0) {
log('❌ API次数已用完,无法获取答案', 'red');
reject('QUOTA_EXHAUSTED');
return;
}
var typeMap = {0:'单选题',1:'多选题',2:'填空题',3:'判断题',4:'简答题'};
var typeText = typeMap[type] || '单选题';
log(`🔍 请求答案 - 题型:${typeText} 题目:${questionText.substring(0, 40)}...`, 'blue');
sendApiRequest(apiKey, questionText, typeText, optionsData, retryCount)
.then(function(res) {
// 成功获取答案
if (res.quota_info) {
updateQuotaInfo(res.quota_info);
}
log(`✅ 答案: ${res.data.substring(0, 100)}...`, 'purple');
resolve(res.data);
})
.catch(function(error) {
var errorMsg = error.message || error;
log(`⚠️ 请求失败: ${errorMsg},尝试切换接口...`, 'orange');
// 切换接口重试
switchToNextApi();
// 最多重试3次(每个接口一次)
if (retryCount < API_URLS.length - 1) {
setTimeout(function() {
getAnswer(type, questionText, optionsData, retryCount + 1)
.then(resolve)
.catch(reject);
}, 1000);
} else {
// 所有接口都失败,不删除key,只返回错误
log(`❌ 所有接口请求失败: ${errorMsg}`, 'red');
reject(errorMsg);
}
});
});
}
// 测试API密钥(带重试机制)
function testApiKey(key, silent = false, retryCount = 0) {
return new Promise((resolve, reject) => {
if (IS_TESTING_KEY) {
reject('测试中,请稍后');
return;
}
IS_TESTING_KEY = true;
var testQuestion = "test";
var testType = "单选题";
var testOptions = ["选项A", "选项B"];
var formData = `question=${encodeURIComponent(testQuestion)}&key=${encodeURIComponent(key)}&type=${encodeURIComponent(testType)}&options=${encodeURIComponent(JSON.stringify(testOptions))}`;
var currentUrl = getCurrentApiUrl();
var timeoutId = setTimeout(() => {
IS_TESTING_KEY = false;
reject('请求超时');
}, 10000);
GM_xmlhttpRequest({
method: 'POST',
url: currentUrl,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: formData,
timeout: 10000,
onload: function(xhr) {
clearTimeout(timeoutId);
IS_TESTING_KEY = false;
try {
var res = JSON.parse(xhr.responseText);
if (res.code == 1 || res.code == 400) {
if (res.quota_info) {
updateQuotaInfo(res.quota_info);
if (!silent) {
log(`📊 剩余次数: ${res.quota_info.remaining} | 免费: ${res.quota_info.free_remaining}`, 'blue');
}
}
// 测试成功,重置接口索引到最优的
CURRENT_API_INDEX = 0;
resolve(res);
} else {
reject(res.msg || '密钥无效');
}
} catch(e) {
reject('解析响应失败');
}
},
onerror: function() {
clearTimeout(timeoutId);
IS_TESTING_KEY = false;
// 测试失败时切换接口重试
if (retryCount < API_URLS.length - 1) {
switchToNextApi();
setTimeout(function() {
testApiKey(key, silent, retryCount + 1)
.then(resolve)
.catch(reject);
}, 1000);
} else {
reject('网络请求失败');
}
},
ontimeout: function() {
clearTimeout(timeoutId);
IS_TESTING_KEY = false;
if (retryCount < API_URLS.length - 1) {
switchToNextApi();
setTimeout(function() {
testApiKey(key, silent, retryCount + 1)
.then(resolve)
.catch(reject);
}, 1000);
} else {
reject('请求超时');
}
}
});
});
}
function checkApiKeyBeforeAction(actionName) {
var apiKey = getApiKey();
if (!apiKey || apiKey.trim() === '') {
log(`❌ 无法执行${actionName}:请先在设置中配置API密钥`, 'red');
return false;
}
quotaInfo = getQuotaInfo();
if (quotaInfo.remaining <= 0 && quotaInfo.free_remaining <= 0) {
log(`❌ 无法执行${actionName}:API次数已用完,请充值`, 'red');
return false;
}
return true;
}
function getBlankInputCount($question) {
var count = 0;
var $inputs = $question.find('.blankList2 input, input[type="text"][name*="answer"]');
if ($inputs.length) {
var uniqueIdentifiers = new Set();
$inputs.each(function() {
var name = $(this).attr('name');
var id = $(this).attr('id');
if (name) {
uniqueIdentifiers.add(name);
} else if (id) {
uniqueIdentifiers.add(id);
} else {
var parentHtml = $(this).parent().html() || '';
uniqueIdentifiers.add($(this).index() + '_' + parentHtml.substring(0, 50));
}
});
count = uniqueIdentifiers.size;
if (count > 0) {
return count;
}
}
var $editorBlocks = $question.find('[data-editorindex]');
if ($editorBlocks.length) {
var uniqueIndices = new Set();
$editorBlocks.each(function() {
var idx = $(this).attr('data-editorindex');
if (idx !== undefined && idx !== null && idx !== '') {
uniqueIndices.add(idx);
}
});
count = uniqueIndices.size;
if (count > 0) {
return count;
}
}
var $pcInputs = $question.find('.Zy_ulTk .XztiHover1 textarea, .stem_answer .Answer .divText .textDIV textarea, .subEditor textarea');
if ($pcInputs.length) {
var uniquePCInputs = new Set();
$pcInputs.each(function() {
var id = $(this).attr('id');
var name = $(this).attr('name');
if (id) {
uniquePCInputs.add(id);
} else if (name) {
uniquePCInputs.add(name);
} else {
uniquePCInputs.add($(this).index());
}
});
count = uniquePCInputs.size;
if (count > 0) {
return count;
}
}
if (count === 0) {
return 1;
}
return count;
}
function tidyStr(s) {
if (!s) return null;
return s.replace(/<(?!img).*?>/g, "").replace(/^【.*?】\s*/, '').replace(/\s*(\d+\.\d+分)$/, '').trim().replace(/ /g, '');
}
function tidyQuestion(s) {
if (!s) return null;
return s.replace(/<(?!img).*?>/g, "").replace(/^【.*?】\s*/, '').replace(/\s*(\d+\.\d+分)$/, '').replace(/^\d+[.、]/, '').trim();
}
function waitForElement(selector, timeout = 30000) {
return new Promise((resolve, reject) => {
var start = Date.now();
var timer = setInterval(() => {
if ($(selector).length) {
clearInterval(timer);
resolve();
} else if (Date.now() - start > timeout) {
clearInterval(timer);
reject();
}
}, 500);
});
}
function getStr(str, start, end) {
let res = str.match(new RegExp(`${start}(.*?)${end}`));
return res ? res[1] : null;
}
function getElement(parent, selector, timeout = 10000) {
return new Promise(resolve => {
var result = parent.querySelector(selector);
if (result) return resolve(result);
var timer;
var observer = new MutationObserver(mutations => {
for (var mutation of mutations) {
for (var node of mutation.addedNodes) {
if (node instanceof Element) {
result = node.matches(selector) ? node : node.querySelector(selector);
if (result) {
observer.disconnect();
timer && clearTimeout(timer);
return resolve(result);
}
}
}
}
});
observer.observe(parent, { childList: true, subtree: true });
timer = setTimeout(() => {
observer.disconnect();
resolve(null);
}, timeout);
});
}
function getTaskParams() {
try {
var _iframeScripts = _d.scripts;
for (let i = 0; i < _iframeScripts.length; i++) {
if (_iframeScripts[i].innerHTML.indexOf('mArg = "";') != -1 && _iframeScripts[i].innerHTML.indexOf('==UserScript==') == -1) {
var _p = getStr(_iframeScripts[i].innerHTML.replace(/\s/g, ""), 'try{mArg=', ';}catch');
return _p;
}
}
return null;
} catch (e) {
return null;
}
}
function toNext() {
if (isJumping) {
log('⏳ 跳转中,请稍后...', 'orange');
return;
}
if (_mlist && _mlist.length > 0) {
log(`⚠️ 还有 ${_mlist.length} 个任务点未完成,不能跳转`, 'red');
return;
}
isJumping = true;
log('🔄 所有任务点已完成,准备跳转到下一个章节...', 'blue');
var nextBtn = null;
try {
nextBtn = top.document.querySelector('#mainid > .prev_next.next') ||
top.document.querySelector('#prevNextFocusNext') ||
$('.prev_next.next')[0];
if (nextBtn && !nextBtn.disabled) {
log('✅ 找到下一节按钮,3秒后跳转', 'green');
setTimeout(() => {
nextBtn.click();
log('📖 已点击跳转按钮', 'green');
setTimeout(() => {
isJumping = false;
}, 5000);
}, 3000);
} else {
log('✅ 课程已全部完成,无更多任务点', 'green');
isJumping = false;
}
} catch(e) {
log('❌ 跳转失败: ' + e.message, 'red');
isJumping = false;
}
}
function completeCurrentTask() {
if (_mlist && _mlist.length > 0) {
var completedTask = _mlist[0];
var taskName = completedTask.property ? (completedTask.property.name || completedTask.property.title || '未知') : '未知';
log(`✅ 完成任务: ${taskName}`, 'green');
_mlist.splice(0, 1);
log(`📋 剩余任务点数量: ${_mlist.length}`, 'blue');
}
if (_domList && _domList.length > 0) {
_domList.splice(0, 1);
}
isProcessing = false;
if (currentVideoInterval) {
clearInterval(currentVideoInterval);
currentVideoInterval = null;
}
if (_mlist && _mlist.length > 0) {
log(`📋 还有 ${_mlist.length} 个任务点待处理,继续...`, 'green');
setTimeout(function() {
missionStart();
}, 2000);
} else {
log('✅ 此页面所有任务处理完毕,准备跳转页面', 'green');
toNext();
}
}
function missionStart() {
if (isProcessing) {
log('⏳ 已有任务在处理中,等待完成...', 'orange');
return;
}
if (!_mlist || _mlist.length === 0) {
log('✅ 无任务点需要处理', 'green');
toNext();
return;
}
isProcessing = true;
var currentTask = _mlist[0];
var _type = currentTask['type'];
var _dom = _domList[0];
if (_type == undefined) {
_type = currentTask['property']["module"];
}
var taskName = currentTask.property ? (currentTask.property.name || currentTask.property.title || '未知') : '未知';
log(`📋 开始处理任务点 (剩余 ${_mlist.length} 个),类型: ${_type},名称: ${taskName}`, 'purple');
var handlers = {
'video': function() { missionVideo(_dom, currentTask); },
'audio': function() { missionAudio(_dom, currentTask); },
'workid': function() { missionWork(_dom, currentTask); },
'document': function() { missionDoucument(_dom, currentTask); },
'read': function() { missionRead(_dom, currentTask); },
'insertbook': function() { missionBook(_dom, currentTask); }
};
if (handlers[_type]) {
handlers[_type]();
} else if (['insertimage'].includes(_type)) {
log('ℹ️ 发现无需处理任务,跳过。', 'orange');
completeCurrentTask();
} else {
log(`⚠️ 暂不支持处理此类型:${_type},跳过。`, 'red');
completeCurrentTask();
}
}
function missionVideo(dom, obj) {
if (!setting.video) {
log('ℹ️ 用户设置不处理视频任务', 'orange');
completeCurrentTask();
return;
}
var { isPassed, property } = obj;
var { name } = property;
if (!setting.review && isPassed === true) {
log(`✅ 视频:${name} 检测已完成`, 'green');
completeCurrentTask();
return;
}
var target = dom.length > 0 ? dom[0] : null;
if (!target) {
log('⚠️ 未找到视频iframe,3秒后重试', 'orange');
isProcessing = false;
setTimeout(function() { missionVideo(dom, obj); }, 3000);
return;
}
log(`🎬 处理视频:${name}`, 'purple');
var executed = false;
var doc = target.contentDocument || target.contentWindow.document;
if (currentVideoInterval) {
clearInterval(currentVideoInterval);
currentVideoInterval = null;
}
currentVideoInterval = setInterval(function() {
var media = doc.querySelector('video') || doc.querySelector('audio');
if (media && !executed) {
executed = true;
log(`✅ ${name} 播放成功`, 'green');
media.pause();
media.muted = true;
media.playbackRate = setting.rate > 1 ? Math.min(setting.rate, 16) : 1;
media.play();
var resumePlay = function() {
if (media.paused && !media.ended) {
media.play();
log(`🔄 ${name} 恢复播放`, 'blue');
}
};
media.addEventListener('pause', resumePlay);
var onVideoEnd = function() {
log(`✅ ${name} 播放完成`, 'green');
media.removeEventListener('pause', resumePlay);
media.removeEventListener('ended', onVideoEnd);
if (currentVideoInterval) {
clearInterval(currentVideoInterval);
currentVideoInterval = null;
}
completeCurrentTask();
};
media.addEventListener('ended', onVideoEnd);
if (media.ended) {
onVideoEnd();
}
} else if (media && executed) {
if (media.ended) {
clearInterval(currentVideoInterval);
currentVideoInterval = null;
completeCurrentTask();
}
}
}, 1500);
}
function missionAudio(dom, obj) {
if (!setting.audio) {
log('ℹ️ 用户设置不处理音频任务', 'orange');
completeCurrentTask();
return;
}
var { isPassed, property } = obj;
var { name } = property;
if (!setting.review && isPassed === true) {
log(`✅ 音频:${name} 检测已完成`, 'green');
completeCurrentTask();
return;
}
log(`🎵 处理音频:${name},等待5秒后完成`, 'purple');
setTimeout(function() {
completeCurrentTask();
}, 5000);
}
function missionBook(dom, obj) {
var jobId = obj['property']['jobid'];
var name = obj['property']['bookname'];
var jtoken = obj['jtoken'];
var knowledgeId = _defaults['knowledgeid'];
var courseId = _defaults['courseid'];
var clazzId = _defaults['clazzId'];
$.ajax({
url: _l.protocol + "//" + _l.host + '/ananas/job?jobid=' + jobId + '&knowledgeid=' + knowledgeId + '&courseid=' + courseId + '&clazzid=' + clazzId + '&jtoken=' + jtoken + '&_dc=' + Date.now(),
method: 'GET',
success: function(res) {
log('📚 读书:' + name + (res.msg || '完成'), 'green');
completeCurrentTask();
},
error: function() {
log('❌ 读书任务失败,跳过', 'red');
completeCurrentTask();
}
});
}
function missionDoucument(dom, obj) {
var jobId = obj['property']['jobid'];
var name = obj['property']['name'];
var jtoken = obj['jtoken'];
var knowledgeId = _defaults['knowledgeid'];
var courseId = _defaults['courseid'];
var clazzId = _defaults['clazzId'];
$.ajax({
url: _l.protocol + "//" + _l.host + '/ananas/job/document?jobid=' + jobId + '&knowledgeid=' + knowledgeId + '&courseid=' + courseId + '&clazzid=' + clazzId + '&jtoken=' + jtoken + '&_dc=' + Date.now(),
method: 'GET',
success: function(res) {
log('📄 文档:' + name + (res.msg || '完成'), 'green');
completeCurrentTask();
},
error: function() {
log('❌ 文档任务失败,跳过', 'red');
completeCurrentTask();
}
});
}
function missionRead(dom, obj) {
var jobId = obj['property']['jobid'];
var name = obj['property']['title'];
var jtoken = obj['jtoken'];
var knowledgeId = _defaults['knowledgeid'];
var courseId = _defaults['courseid'];
var clazzId = _defaults['clazzId'];
$.ajax({
url: _l.protocol + '//' + _l.host + '/ananas/job/readv2?jobid=' + jobId + '&knowledgeid=' + knowledgeId + '&courseid=' + courseId + '&clazzid=' + clazzId + '&jtoken=' + jtoken + '&_dc=' + Date.now(),
method: 'GET',
success: function(res) {
log('📖 阅读:' + name + (res.msg || '完成'), 'green');
completeCurrentTask();
},
error: function() {
log('❌ 阅读任务失败,跳过', 'red');
completeCurrentTask();
}
});
}
function missionWork(dom, obj) {
if (!setting.work) {
log('ℹ️ 用户设置不自动处理测验', 'orange');
completeCurrentTask();
return;
}
if (!checkApiKeyBeforeAction('自动答题')) {
completeCurrentTask();
return;
}
var isDo = true;
if (setting.task && obj['jobid'] == undefined) {
isDo = false;
}
if (isDo) {
if (obj['jobid'] !== undefined) {
var phoneWeb = _l.protocol + '//' + _l.host + '/work/phone/work?workId=' + obj['jobid'].replace('work-', '') + '&courseId=' + _defaults['courseid'] + '&clazzId=' + _defaults['clazzId'] + '&knowledgeId=' + _defaults['knowledgeid'] + '&jobId=' + obj['jobid'] + '&enc=' + obj['enc'];
log('📝 准备处理测验', 'purple');
setTimeout(function() { startDoPhoneCyWork(0, dom, phoneWeb); }, 3000);
} else {
setTimeout(function() { startDoCyWork(0, dom); }, 3000);
}
} else {
log('ℹ️ 用户设置只处理属于任务点的任务', 'orange');
completeCurrentTask();
}
}
function startDoPhoneCyWork(index, doms, phoneWeb) {
if (index == doms.length) {
log('✅ 此页面全部测验已处理完毕', 'green');
completeCurrentTask();
return;
}
getElement($(doms[index]).contents()[0], 'iframe').then(function(iframe) {
if (!iframe) {
setTimeout(function() { startDoPhoneCyWork(index, doms, phoneWeb); }, 5000);
return;
}
var workIframe = $(iframe);
var workStatus = workIframe.contents().find('.newTestCon .newTestTitle .testTit_status').text().trim();
if (!workStatus) {
_domList.splice(0, 1);
completeCurrentTask();
return;
}
if (workStatus.indexOf("待做") != -1 || workStatus.indexOf("待完成") != -1 || workStatus.indexOf("未达到及格线") != -1) {
workIframe.attr('src', phoneWeb);
getElement($(doms[index]).contents()[0], 'iframe[src="' + phoneWeb + '"]').then(function() {
setTimeout(function() { doPhoneWork(workIframe.contents()); }, 3000);
});
} else if (workStatus.indexOf('待批阅') != -1) {
_mlist.splice(0, 1);
_domList.splice(0, 1);
log('⚠️ 测验待批阅,跳过', 'red');
completeCurrentTask();
} else {
_mlist.splice(0, 1);
_domList.splice(0, 1);
log('⚠️ 未知状态,跳过', 'red');
completeCurrentTask();
}
});
}
function doPhoneWork($dom) {
var $cy = $dom.find('.Wrappadding form');
$subBtn = $cy.find('.zquestions .zsubmit .btn-ok-bottom');
$okBtn = $dom.find('#okBtn');
$saveBtn = $cy.find('.zquestions .zsubmit .btn-save');
var TimuList = $cy.find('.zquestions .Py-mian1');
startDoPhoneTimu(0, TimuList);
}
function startDoPhoneTimu(index, TimuList) {
if (index == TimuList.length) {
if (setting.sub) {
log('✅ 测验处理完成,准备自动提交。', 'green');
setTimeout(function() {
$subBtn.click();
setTimeout(function() {
$okBtn.click();
log('✅ 提交成功', 'green');
completeCurrentTask();
}, 3000);
}, 5000);
} else if (setting.force) {
log('⚠️ 存在无答案题目,强制提交', 'red');
setTimeout(function() {
$subBtn.click();
setTimeout(function() {
$okBtn.click();
log('✅ 提交成功', 'green');
completeCurrentTask();
}, 3000);
}, 5000);
} else {
log('💾 测验处理完成,自动保存', 'green');
setTimeout(function() {
$saveBtn.click();
setTimeout(function() {
log('✅ 保存成功', 'green');
completeCurrentTask();
}, 3000);
}, 5000);
}
return;
}
var contextWindow = TimuList[index] ? (TimuList[index].ownerDocument.defaultView || unsafeWindow) : unsafeWindow;
var questionFull = $(TimuList[index]).find('.Py-m1-title').html();
var _question = tidyQuestion(questionFull).replace(/.*?\[.*?题\]\s*\n\s*/, '').trim();
var typeName = questionFull.match(/.*?\[(.*?)]|$/)[1];
var typeMap = { '单选题': 0, '多选题': 1, '填空题': 2, '判断题': 3, '简答题': 4 };
var _type = typeMap[typeName];
if (_type === undefined) {
if ($(TimuList[index]).find('.answerList.singleChoice li').length) _type = 0;
else if ($(TimuList[index]).find('.answerList.multiChoice li').length) _type = 1;
else if ($(TimuList[index]).find('.blankList2 input').length) _type = 2;
else if ($(TimuList[index]).find('.answerList.panduan li').length) _type = 3;
else if ($(TimuList[index]).find('textarea').length) _type = 4;
}
var checkAnswered = function() {
if (_type == 0 || _type == 1) {
var $opts = _type == 0 ? $(TimuList[index]).find('.answerList.singleChoice li') : $(TimuList[index]).find('.answerList.multiChoice li');
for (var i = 0; i < $opts.length; i++) {
if ($($opts[i]).attr('aria-label')) return true;
}
} else if (_type == 2) {
var $inputs = $(TimuList[index]).find('.blankList2 input');
if ($inputs.length && $inputs.first().val() && $inputs.first().val().trim() !== '') return true;
var $editorBlocks = $(TimuList[index]).find('[data-editorindex]');
if ($editorBlocks.length) {
var hasContent = false;
$editorBlocks.each(function() {
var itemId = $(this).attr('data-itemid');
if (itemId && $('#answer' + itemId).val() && $('#answer' + itemId).val().trim() !== '') {
hasContent = true;
}
});
if (hasContent) return true;
}
} else if (_type == 3) {
var $pd = $(TimuList[index]).find('.answerList.panduan li');
for (var i = 0; i < $pd.length; i++) {
if ($($pd[i]).attr('aria-label')) return true;
}
} else if (_type == 4) {
var $ta = $(TimuList[index]).find('textarea[name^="answer"]');
if ($ta.length && $ta.first().val() && $ta.first().val().trim() !== '') return true;
var $editorBlocks = $(TimuList[index]).find('[data-editorindex]');
if ($editorBlocks.length) {
var hasContent = false;
$editorBlocks.each(function() {
var itemId = $(this).attr('data-itemid');
if (itemId && $('#answer' + itemId).val() && $('#answer' + itemId).val().trim() !== '') {
hasContent = true;
}
});
if (hasContent) return true;
}
}
return false;
};
if (checkAnswered()) {
log(`📌 第${index + 1}题已作答,跳过`, 'green');
setTimeout(function() { startDoPhoneTimu(index + 1, TimuList); }, 30);
return;
}
var $opts = [];
var optsText = [];
var optionsData = [];
var pureQuestion = _question;
if (_type == 0 || _type == 1) {
$opts = _type == 0 ? $(TimuList[index]).find('.answerList.singleChoice li') : $(TimuList[index]).find('.answerList.multiChoice li');
$opts.each(function() {
optsText.push(tidyStr($(this).html()).replace(/^[A-Z]\s*\n\s*/, '').trim());
});
optionsData = optsText;
} else if (_type == 2) {
var blankCount = getBlankInputCount($(TimuList[index]));
optionsData = [blankCount.toString()];
log(`📝 填空题传入空数量: ${blankCount}`, 'blue');
} else if (_type == 3) {
optionsData = ["对", "错"];
log(`📝 判断题传入固定选项: ["对","错"]`, 'blue');
} else if (_type == 4) {
optionsData = ["1"];
log(`📝 简答题传入固定参数: ["1"]`, 'blue');
}
getAnswer(_type, pureQuestion, optionsData).then(function(agrs) {
if (agrs == '暂无答案') {
log('⚠️ AI无法匹配正确答案,跳过此题', 'red');
setTimeout(function() { startDoPhoneTimu(index + 1, TimuList); }, setting.time);
return;
}
var $titleDom = getQuestionTitleDom($(TimuList[index]), 'phone');
insertAnswerToTitle($titleDom, agrs);
var questionOptions = { $opts: $opts, optsText: optsText };
fillAnswerByType(_type, $(TimuList[index]), agrs, questionOptions, true, contextWindow);
log(`✅ 第${index + 1}题自动答题成功`, 'green');
setTimeout(function() { startDoPhoneTimu(index + 1, TimuList); }, setting.time);
}).catch(function() {
setTimeout(function() { startDoPhoneTimu(index + 1, TimuList); }, setting.time);
});
}
function startDoCyWork(index, doms) {
if (index == doms.length) {
log('✅ 此页面全部测验已处理完毕', 'green');
completeCurrentTask();
return;
}
getElement($(doms[index]).contents()[0], 'iframe').then(function(iframe) {
if (!iframe) {
setTimeout(function() { startDoCyWork(index, doms); }, 5000);
return;
}
var workIframe = $(iframe);
var workStatus = workIframe.contents().find(".newTestCon .newTestTitle .testTit_status").text().trim();
if (!workStatus) {
_domList.splice(0, 1);
completeCurrentTask();
return;
}
if (workStatus.indexOf("待做") != -1 || workStatus.indexOf("待完成") != -1) {
log('📝 准备处理测验', 'purple');
setTimeout(function() { doWork(index, doms, iframe); }, 5000);
} else if (workStatus.indexOf('待批阅') != -1) {
_mlist.splice(0, 1);
_domList.splice(0, 1);
log('⚠️ 测验待批阅,跳过', 'red');
completeCurrentTask();
} else {
_mlist.splice(0, 1);
_domList.splice(0, 1);
log('⚠️ 未知状态,跳过', 'red');
completeCurrentTask();
}
});
}
function doWork(index, doms, dom) {
$frame_c = $(dom).contents();
var $CyHtml = $frame_c.find('.CeYan');
var TiMuList = $CyHtml.find('.TiMu');
$subBtn = $frame_c.find(".ZY_sub").find(".btnSubmit");
$saveBtn = $frame_c.find(".ZY_sub").find(".btnSave");
startDoWork(index, doms, 0, TiMuList);
}
function startDoWork(index, doms, c, TiMuList) {
if (c == TiMuList.length) {
if (setting.sub) {
log('✅ 测验处理完成,准备自动提交。', 'green');
setTimeout(function() {
$subBtn.click();
setTimeout(function() {
$frame_c.find('#confirmSubWin > div > div > a.bluebtn').click();
log('✅ 提交成功', 'green');
completeCurrentTask();
}, 3000);
}, 5000);
} else if (setting.force) {
log('⚠️ 存在无答案题目,强制提交', 'red');
setTimeout(function() {
$subBtn.click();
setTimeout(function() {
$frame_c.find('#confirmSubWin > div > div > a.bluebtn').click();
log('✅ 提交成功', 'green');
completeCurrentTask();
}, 3000);
}, 5000);
} else {
log('💾 测验处理完成,自动保存', 'green');
setTimeout(function() {
$saveBtn.click();
setTimeout(function() {
log('✅ 保存成功', 'green');
completeCurrentTask();
}, 3000);
}, 5000);
}
return;
}
var questionFull = $(TiMuList[c]).find('.Zy_TItle.clearfix > div').html();
var _question = tidyQuestion(questionFull);
var typeName = questionFull.match(/^【(.*?)】|$/)[1];
var typeMap = { '单选题': 0, '多选题': 1, '填空题': 2, '判断题': 3, '简答题': 4 };
var _TimuType = typeMap[typeName];
if (_TimuType === undefined) {
if ($(TiMuList[c]).find('.Zy_ulTop li').length) {
_TimuType = $(TiMuList[c]).find('input[type="checkbox"]').length ? 1 : 0;
} else if ($(TiMuList[c]).find('.Zy_ulTk .XztiHover1').length) {
_TimuType = 2;
} else {
_TimuType = 4;
}
}
var $opts = [];
var optsText = [];
var optionsData = [];
var pureQuestion = _question;
if (_TimuType == 0 || _TimuType == 1) {
$opts = $(TiMuList[c]).find('.Zy_ulTop li a');
$opts.each(function() {
optsText.push(tidyStr($(this).html()));
});
optionsData = optsText;
} else if (_TimuType == 2) {
var blankCount = getBlankInputCount($(TiMuList[c]));
optionsData = [blankCount.toString()];
log(`📝 填空题传入空数量: ${blankCount}`, 'blue');
} else if (_TimuType == 3) {
optionsData = ["对", "错"];
log(`📝 判断题传入固定选项: ["对","错"]`, 'blue');
} else if (_TimuType == 4) {
optionsData = ["1"];
log(`📝 简答题传入固定参数: ["1"]`, 'blue');
}
getAnswer(_TimuType, pureQuestion, optionsData).then(function(agrs) {
var $titleDom = getQuestionTitleDom($(TiMuList[c]), 'work');
insertAnswerToTitle($titleDom, agrs);
var questionOptions = { $opts: $opts, optsText: optsText };
fillAnswerByType(_TimuType, $(TiMuList[c]), agrs, questionOptions, false, null);
setTimeout(function() { startDoWork(index, doms, c + 1, TiMuList); }, setting.time);
}).catch(function() {
setTimeout(function() { startDoWork(index, doms, c + 1, TiMuList); }, setting.time);
});
}
function missonHomeWork() {
log('📝 开始处理作业', 'green');
if (!checkApiKeyBeforeAction('作业自动答题')) return;
var $_homeworktable = $('.mark_table').find('form');
var TimuList = $_homeworktable.find('.questionLi');
doHomeWork(0, TimuList);
}
function doHomeWork(index, TiMuList) {
if (index == TiMuList.length) {
log('✅ 作业题目已全部完成', 'green');
return;
}
var typeName = $(TiMuList[index]).attr('typename');
var typeMap = { '单选题': 0, '多选题': 1, '填空题': 2, '判断题': 3, '简答题': 4 };
var _type = typeMap[typeName];
var _questionFull = $(TiMuList[index]).find('.mark_name').html();
var _question = tidyQuestion(_questionFull).replace(/^[(].*?[)]/, '').trim();
if (_type === undefined) {
var _answerTmpArr = $(TiMuList[index]).find('.stem_answer').find('.answer_p');
if (_answerTmpArr && _answerTmpArr.length > 0) {
_type = $(TiMuList[index]).find('input[type="checkbox"]').length ? 1 : 0;
} else if ($(TiMuList[index]).find('.stem_answer').find('.divText textarea').length) {
_type = 4;
}
}
var checkAnswered = function() {
if (_type == 0 || _type == 1) {
var $opts = $(TiMuList[index]).find('.stem_answer .answer_p');
for (var i = 0; i < $opts.length; i++) {
if ($($opts[i]).parent().find('span').attr('class') && $($opts[i]).parent().find('span').attr('class').indexOf('check_answer') != -1) {
return true;
}
}
} else if (_type == 2) {
var $inputs = $(TiMuList[index]).find('.stem_answer .Answer .divText .textDIV textarea');
if ($inputs.length && $inputs.val() && $inputs.val().trim() !== '') return true;
} else if (_type == 3) {
var $opts = $(TiMuList[index]).find('.stem_answer .answer_p');
for (var i = 0; i < $opts.length; i++) {
if ($($opts[i]).parent().find('span').attr('class') && $($opts[i]).parent().find('span').attr('class').indexOf('check_answer') != -1) {
return true;
}
}
} else if (_type == 4) {
var $ta = $(TiMuList[index]).find('.stem_answer .eidtDiv textarea');
if ($ta.length && $ta.val() && $ta.val().trim() !== '') return true;
}
return false;
};
if (checkAnswered()) {
log(`📌 第${index + 1}题已作答,跳过`, 'green');
setTimeout(function() { doHomeWork(index + 1, TiMuList); }, 30);
return;
}
var $opts = [];
var optsText = [];
var optionsData = [];
var pureQuestion = _question;
if (_type == 0 || _type == 1) {
$opts = $(TiMuList[index]).find('.stem_answer .answer_p');
$opts.each(function() {
optsText.push(tidyStr($(this).html()));
});
optionsData = optsText;
} else if (_type == 2) {
var blankCount = getBlankInputCount($(TiMuList[index]));
optionsData = [blankCount.toString()];
log(`📝 填空题传入空数量: ${blankCount}`, 'blue');
} else if (_type == 3) {
optionsData = ["对", "错"];
log(`📝 判断题传入固定选项: ["对","错"]`, 'blue');
} else if (_type == 4) {
optionsData = ["1"];
log(`📝 简答题传入固定参数: ["1"]`, 'blue');
}
getAnswer(_type, pureQuestion, optionsData).then(function(agrs) {
var $titleDom = getQuestionTitleDom($(TiMuList[index]), 'homework');
insertAnswerToTitle($titleDom, agrs);
var questionOptions = { $opts: $opts, optsText: optsText };
fillAnswerByType(_type, $(TiMuList[index]), agrs, questionOptions, false, null);
log(`✅ 第${index + 1}题自动答题成功`, 'green');
setTimeout(function() { doHomeWork(index + 1, TiMuList); }, setting.time);
}).catch(function() {
setTimeout(function() { doHomeWork(index + 1, TiMuList); }, setting.time);
});
}
function missonExam() {
if (!checkApiKeyBeforeAction('考试自动答题')) return;
var $_examtable = $('.mark_table').find('.whiteDiv');
var _questionFull = tidyStr($_examtable.find('h3.mark_name').html().trim());
var typeName = _questionFull.match(/[(](.*?),.*?分[)]|$/)[1];
var typeMap = { '单选题': 0, '多选题': 1, '填空题': 2, '判断题': 3, '简答题': 4 };
var _qType = typeMap[typeName];
var _question = tidyQuestion(_questionFull.replace(/[(].*?分[)]/, '').replace(/^\s*/, ''));
var $_ansdom = $_examtable.find('#submitTest').find('.stem_answer');
if (_qType === undefined) {
var $opts = $_ansdom.find('.clearfix.answerBg .fl.answer_p');
if ($opts.length) {
_qType = $_ansdom.find('input[type="checkbox"]').length ? 1 : 0;
} else if ($_ansdom.find('.Answer .divText .subEditor textarea').length) {
_qType = 4;
}
}
var checkAnswered = function() {
if (_qType == 0 || _qType == 1) {
var $opts = $_ansdom.find('.clearfix.answerBg .fl.answer_p');
for (var i = 0; i < $opts.length; i++) {
if ($($opts[i]).parent().find('span').attr('class') && $($opts[i]).parent().find('span').attr('class').indexOf('check_answer') != -1) {
return true;
}
}
} else if (_qType == 2) {
var $inputs = $_ansdom.find('.Answer .divText .subEditor textarea');
if ($inputs.length && $inputs.val() && $inputs.val().trim() !== '') return true;
} else if (_qType == 4) {
var $ta = $_ansdom.find('.subEditor textarea');
if ($ta.length && $ta.val() && $ta.val().trim() !== '') return true;
}
return false;
};
if (checkAnswered()) {
log('📌 此题已作答,跳过', 'green');
toNextExam();
return;
}
var $opts = [];
var optsText = [];
var optionsData = [];
var pureQuestion = _question;
if (_qType == 0 || _qType == 1) {
$opts = $_ansdom.find('.clearfix.answerBg .fl.answer_p');
$opts.each(function() {
optsText.push(tidyStr($(this).html()));
});
optionsData = optsText;
} else if (_qType == 2) {
var blankCount = getBlankInputCount($_ansdom);
optionsData = [blankCount.toString()];
log(`📝 填空题传入空数量: ${blankCount}`, 'blue');
} else if (_qType == 4) {
optionsData = ["1"];
log(`📝 简答题传入固定参数: ["1"]`, 'blue');
}
getAnswer(_qType, pureQuestion, optionsData).then(function(agrs) {
var $titleDom = getQuestionTitleDom($_examtable, 'exam');
insertAnswerToTitle($titleDom, agrs);
var questionOptions = { $opts: $opts, optsText: optsText };
fillAnswerByType(_qType, $_ansdom, agrs, questionOptions, false, null);
log('✅ 自动答题成功', 'green');
setTimeout(function() { toNextExam(); }, setting.time);
}).catch(function() {
setTimeout(function() { toNextExam(); }, setting.time);
});
}
function toNextExam() {
if (setting.examTurn) {
var $nextbtn = $('.mark_table .whiteDiv .nextDiv a.jb_btn');
var delay = setting.examTurnTime ? 2000 + (Math.floor(Math.random() * 5 + 1) * 1000) : 2000;
setTimeout(function() { $nextbtn.click(); }, delay);
log(`⏭️ ${delay/1000}秒后自动跳转下一题`, 'blue');
}
}
function decryptFont() {
if (typeof Typr === 'undefined') return;
var $tip = $('style:contains(font-cxsecret)');
if (!$tip.length) return;
var font = $tip.text().match(/base64,([\w\W]+?)'/)[1];
font = Typr.parse(base64ToUint8Array(font))[0];
var table = JSON.parse(GM_getResourceText('Table'));
var match = {};
for (var i = 19968; i < 40870; i++) {
var glyph = Typr.U.codeToGlyph(font, i);
if (!glyph) continue;
var path = Typr.U.glyphToPath(font, glyph);
var hash = md5(JSON.stringify(path)).slice(24);
match[i] = table[hash];
}
$('.font-cxsecret').html(function(idx, html) {
$.each(match, function(key, value) {
html = html.replace(new RegExp(String.fromCharCode(key), 'g'), String.fromCharCode(value));
});
return html;
}).removeClass('font-cxsecret');
}
function base64ToUint8Array(base64) {
var data = window.atob(base64);
var buf = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) buf[i] = data.charCodeAt(i);
return buf;
}
function showBox() {
if (!setting.showBox) return;
try {
var topDoc = top.document;
if (topDoc.querySelector('#ne-21box')) {
flushLogs();
quotaInfo = getQuotaInfo();
updateQuotaDisplay();
return;
}
} catch(e) {}
var boxHtml = `