// ==UserScript==
// @name 小僵尸学习通学习助手
// @namespace xiaojiangshi-cx
// @version 1.5.0
// @author 小僵尸
// @description 小僵尸出品:学习通视频自动播放、AI后台自动答题(硅基流动免费大模型)、字体解密。F9隐藏面板。
// @match *://*.chaoxing.com/*
// @run-at document-idle
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_getResourceText
// @resource Table https://pkpkq.n1t.cn/font-decrypt/Table.json
// @connect pkpkq.n1t.cn
// @connect api.siliconflow.cn
// ==/UserScript==
(function() {
'use strict';
/* ========== 最开头确认执行 ========== */
console.log('[小僵尸] 脚本开始执行, path=' + location.pathname);
var isTop = (window.top === window.self);
/* ========== 配置 ========== */
var CFG = {};
var DEFAULTS = {
videoRate: 1, answerInterval: 3000,
autoSubmit: false, autoNextExam: true, insertAnswer: true,
decryptFont: true, handleVideo: true,
apiKey: '', apiUrl: 'https://api.siliconflow.cn/v1/chat/completions'
};
for (var k in DEFAULTS) {
var sv = localStorage.getItem('xj_' + k);
if (sv !== null) {
if (sv === 'true') CFG[k] = true;
else if (sv === 'false') CFG[k] = false;
else if (!isNaN(parseFloat(sv)) && isFinite(sv)) CFG[k] = parseFloat(sv);
else CFG[k] = sv;
} else CFG[k] = DEFAULTS[k];
}
function saveCfg(k, v) { localStorage.setItem('xj_' + k, v); CFG[k] = v; }
/* ========== 全局状态 ========== */
var logBox = null;
var taskList = null, defaults = null, domList = null;
var isProcessing = false, isJumping = false;
var pendingCount = 0, doneCount = 0;
var currentVideoTimer = null;
var jumpedNoTask = false;
var API_SERVERS = []; // 动态从CFG读取
/* ========== 日志 ========== */
function log(msg, color) {
var t = new Date().toLocaleTimeString();
var line = document.createElement('div');
line.style.cssText = 'border-top:1px solid #eee;padding:3px 0;font-size:12px;color:' + (color||'#333');
line.textContent = '[' + t + '] ' + msg;
if (logBox) {
logBox.insertBefore(line, logBox.firstChild);
while (logBox.children.length > 100) logBox.removeChild(logBox.lastChild);
}
console.log('[小僵尸]', msg);
}
/* ========== 工具 ========== */
function $(sel, root) { return (root||document).querySelector(sel); }
function $$(sel, root) { return Array.prototype.slice.call((root||document).querySelectorAll(sel)); }
function cleanTxt(html) {
if (!html) return '';
var div = document.createElement('div');
div.innerHTML = html;
var t = div.textContent || div.innerText || '';
// 去除HTML标签、题型括号【单选题】(单选题)(单选题)、选项前缀A.、分数(2.0分)、题号1.
t = t.replace(/<[^>]*>/g,'');
// 循环去除题型标签,可能有多层嵌套
for (var i = 0; i < 3; i++) {
t = t.replace(/^\s*【.*?题】\s*/, '').replace(/^\s*[((].*?题[))]\s*/, '');
}
t = t.replace(/^[A-Z][.、.))\s]+/, '').replace(/^\([A-Z]\)[\s]*/, '').replace(/^([A-Z])[\s]*/, '');
t = t.replace(/\s*[((]\d+\.?\d*分[))]\s*$/, '').replace(/^\d+[.、]?\s*/, '');
return t.trim();
}
function norm(t) { return (t||'').toUpperCase().replace(/[^\u4e00-\u9fa5A-Z0-9]/g,'').trim(); }
function splitAns(a) { return (a||'').split('#').map(function(s){return s.trim();}).filter(function(s){return s;}); }
function waitEl(sel, timeout) {
timeout = timeout || 20000;
return new Promise(function(res, rej) {
var start = Date.now();
var t = setInterval(function() {
if ($(sel)) { clearInterval(t); res(); }
else if (Date.now()-start > timeout) { clearInterval(t); rej(); }
}, 300);
});
}
/* ========== 浮窗 ========== */
function showPanel() {
if (!isTop) return; // 只在顶层窗口显示一次
if (document.getElementById('xj-box')) return;
var box = document.createElement('div');
box.id = 'xj-box';
box.style.cssText = 'position:fixed;top:5%;right:2%;z-index:999999;width:380px;background:#fff;border-radius:8px;box-shadow:0 2px 12px rgba(0,0,0,0.2);font-size:13px;font-family:Microsoft YaHei,sans-serif;';
box.innerHTML =
'
' +
'🧟 小僵尸学习通 v1.4.1' +
'[F9]
' +
'';
document.body.appendChild(box);
logBox = document.getElementById('xj-log');
document.getElementById('xj-close').onclick = function() { box.style.display = 'none'; };
document.getElementById('xj-vr').onchange = function() { var v=parseFloat(this.value); if(v>=1&&v<=8){saveCfg('videoRate',v);log('倍速:'+v);} };
document.getElementById('xj-ai').onchange = function() { var v=parseInt(this.value); if(v>=1000&&v<=10000){saveCfg('answerInterval',v);log('间隔:'+v);} };
document.getElementById('xj-rs').onclick = function() { log('手动重扫...','blue'); isProcessing=false; if(taskList&&taskList.length) startMission(); else log('无待处理任务','orange'); };
document.getElementById('xj-ts').onclick = function() {
log('测试搜题...','blue');
getAnswer(0, '1+1等于几', ['1','2','3']).then(function(a){log('✅测试成功: '+a,'green');}).catch(function(e){log('❌测试失败: '+e,'red');});
};
document.getElementById('xj-as').onchange = function() { saveCfg('autoSubmit', this.checked); };
document.getElementById('xj-ne').onchange = function() { saveCfg('autoNextExam', this.checked); };
document.getElementById('xj-key').onchange = function() { saveCfg('apiKey', this.value.trim()); log('API Key已保存','blue'); };
window.addEventListener('keydown', function(e) {
if (e.keyCode == 120) { box.style.display = box.style.display === 'none' ? 'block' : 'none'; }
});
}
/* ========== 后台AI答题(硅基流动) ========== */
function getAnswer(qType, qText, options) {
return new Promise(function(resolve, reject) {
var tmap = {0:'单选题',1:'多选题',2:'填空题',3:'判断题',4:'简答题'};
var ttype = tmap[qType] || '单选题';
var apiKey = CFG.apiKey || '';
if (!apiKey) {
log('⚠️ 未设置API Key,请在面板填写硅基流动Key','red');
reject('NO_KEY');
return;
}
// 针对不同题型构造精确prompt
var prompt = '你是一个严谨的答题助手。';
if (qType == 0) {
prompt += '这是单选题,从选项中选出唯一正确答案,只输出选项字母(A/B/C/D),不要解释。\n';
} else if (qType == 1) {
prompt += '这是多选题,从选项中选出所有正确答案,只输出选项字母连写(如ABD),不要解释。\n';
} else if (qType == 2) {
prompt += '这是填空题,直接填写空格内容,只输出答案文本,不要解释。\n';
} else if (qType == 3) {
prompt += '这是判断题,只输出"正确"或"错误"二字,不要解释。\n';
} else {
prompt += '这是简答题,简要回答问题,直接输出答案内容。\n';
}
prompt += '\n题目:' + qText + '\n';
if (options && options.length && (qType == 0 || qType == 1)) {
prompt += '选项:\n';
options.forEach(function(o, i) { prompt += String.fromCharCode(65+i) + '. ' + o + '\n'; });
}
if (qType == 3) prompt += '(正确/错误)\n';
prompt += '\n答案:';
log('AI[' + ttype + ']: ' + qText.substring(0,30) + '...', '#555');
var body = JSON.stringify({
model: 'Qwen/Qwen2.5-7B-Instruct',
messages: [{role:'user', content: prompt}],
max_tokens: 200,
temperature: 0.1
});
GM_xmlhttpRequest({
method: 'POST',
url: CFG.apiUrl,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + apiKey
},
data: body,
timeout: 30000,
onload: function(xhr) {
try {
var res = JSON.parse(xhr.responseText);
if (res.choices && res.choices[0] && res.choices[0].message) {
var ans = (res.choices[0].message.content || '').trim();
ans = ans.replace(/^(答案|答|选项|选择|正确答案)[::]?\s*/i, '').trim();
ans = ans.replace(/\s*[。.;;]\s*$/, '');
log('AI答案: ' + ans, 'purple');
resolve(ans);
} else if (res.error) {
reject('AI错误: ' + (res.error.message || JSON.stringify(res.error)));
} else {
reject('返回格式异常');
}
} catch(e) {
reject('解析失败: ' + e.message);
}
},
onerror: function() { reject('网络错误'); },
ontimeout: function() { reject('请求超时'); }
});
});
}
/* ========== 填答案辅助 ========== */
function clickOption($q, answer) {
var items = $$('li a, .answer_p', $q);
var opts = items.map(function(el) { return cleanTxt(el.innerHTML); });
var na = norm(answer);
// 先按字母匹配 (A/B/C/D)
var letterMatch = answer.trim().match(/^([A-Da-d])/);
if (letterMatch) {
var idx = letterMatch[1].toUpperCase().charCodeAt(0) - 65;
if (items[idx]) {
items[idx].click();
log('✅ 选中: ' + String.fromCharCode(65+idx) + '. ' + opts[idx], 'green');
return;
}
}
// 再按文本模糊匹配
for (var i = 0; i < opts.length; i++) {
var no = norm(opts[i]);
if (no === na || (na && (na.indexOf(no) !== -1 || no.indexOf(na) !== -1))) {
items[i].click();
log('✅ 选中: ' + opts[i], 'green');
return;
}
}
log('⚠️ 未匹配选项: ' + answer, 'orange');
}
function clickMulti($q, answer) {
var items = $$('li a, .answer_p', $q);
var opts = items.map(function(el) { return cleanTxt(el.innerHTML); });
// 解析多选题答案:支持 "ABD" "A,B,D" "A#B#D" 格式
var letters = answer.toUpperCase().match(/[A-D]/g);
if (letters && letters.length) {
letters.forEach(function(letter) {
var idx = letter.charCodeAt(0) - 65;
if (items[idx]) {
setTimeout(function(){ items[idx].click(); log('✅ 多选: ' + letter + '. ' + opts[idx], 'green'); }, 200);
}
});
return;
}
// 文本匹配
var arr = splitAns(answer);
items.forEach(function(el, i) {
var no = norm(opts[i]);
arr.forEach(function(a) {
var na = norm(a);
if (no === na || (na && (no.indexOf(na) !== -1 || na.indexOf(no) !== -1))) {
setTimeout(function(){ el.click(); }, 200);
}
});
});
}
function clickJudge($q, answer) {
var trueKw = '正确|是|对|√|T|TRUE|YES|ri';
var ans = (answer || '').trim();
var isTrue = false;
if (trueKw.indexOf(ans) !== -1 || trueKw.toLowerCase().indexOf(ans.toLowerCase()) !== -1) {
isTrue = true;
} else if (ans.indexOf('错误') !== -1 || ans.indexOf('错') !== -1 || ans.indexOf('×') !== -1 || ans === 'F' || ans === 'FALSE') {
isTrue = false;
} else {
// 无法判断时默认选"对"
isTrue = true;
}
var lis = $$('li', $q);
var clicked = false;
lis.forEach(function(li) {
var span = li.querySelector('span');
var v = li.getAttribute('val-param') || (span ? span.getAttribute('val-param') : null);
if (v == 'true' && isTrue) { li.click(); clicked = true; log('✅ 判断: 正确','green'); }
if (v == 'false' && !isTrue) { li.click(); clicked = true; log('✅ 判断: 错误','green'); }
});
if (!clicked && lis.length) {
if (isTrue) { lis[0].click(); log('✅ 判断: 正确(默认)','green'); }
else if (lis.length > 1) { lis[1].click(); log('✅ 判断: 错误','green'); }
else { lis[0].click(); log('✅ 判断: 正确(唯一)','green'); }
}
}
function fillText($q, answer) {
// 填空题:多个空用 # 分隔
var answers = splitAns(answer);
var tas = $$('textarea', $q);
var visibleTas = tas.filter(function(t) { return t.offsetParent !== null; });
var inputs = $$('input[type="text"]', $q);
var visibleInputs = inputs.filter(function(i) { return i.offsetParent !== null; });
if (visibleTas.length) {
visibleTas.forEach(function(ta, i) {
var v = answers[i] || answers[0] || answer;
ta.value = v;
ta.dispatchEvent(new Event('input', {bubbles:true}));
ta.dispatchEvent(new Event('change', {bubbles:true}));
});
} else if (visibleInputs.length) {
visibleInputs.forEach(function(inp, i) {
var v = answers[i] || answers[0] || answer;
inp.value = v;
inp.dispatchEvent(new Event('input', {bubbles:true}));
inp.dispatchEvent(new Event('change', {bubbles:true}));
});
}
log('✅ 已填写: ' + (answers[0] || answer).substring(0,50), 'green');
}
/* ========== 任务处理 ========== */
function isDone(t) { return !!(t && (t.isPassed || t.finished || t.status === 'completed')); }
function goNext() {
if (isJumping) return;
isJumping = true;
var btn = document.querySelector('.prev_next.next:not(.disabled)') ||
(top.document.querySelector('.prev_next.next:not(.disabled)'));
if (btn && !btn.disabled && !btn.classList.contains('disabled')) {
log('3秒后下一节...','green');
setTimeout(function(){ btn.click(); isJumping=false; }, 3000);
} else { log('已是最后一节','green'); isJumping=false; }
}
function completeTask() {
if (taskList && taskList.length) {
var t = taskList[0];
var name = t.property ? (t.property.name || t.property.title || '完成') : '完成';
log('✅ 完成: ' + name, 'green');
taskList.shift(); doneCount++;
}
if (domList && domList.length) domList.shift();
isProcessing = false;
if (currentVideoTimer) { clearInterval(currentVideoTimer); currentVideoTimer = null; }
if (taskList && taskList.length) { setTimeout(startMission, 2000); }
else { log('✅ 本页任务完成','green'); setTimeout(goNext, 2000); }
}
function startMission() {
if (isProcessing || !taskList || !taskList.length) return;
isProcessing = true;
var task = taskList[0];
var type = task.type || (task.property && task.property.module);
var dom = domList[0];
log('任务类型: ' + type, 'blue');
if (type === 'video' || type === 'audio') {
processMedia(dom, task);
} else if (type === 'document' || type === 'read' || type === 'insertbook') {
processAjaxTask(task, type);
} else if (type === 'workid') {
processQuiz(dom, task);
} else if (type === 'insertimage') {
completeTask();
} else {
log('不支持类型: ' + type, 'red');
completeTask();
}
}
function processMedia(dom, task) {
var name = task.property ? (task.property.name || '媒体') : '媒体';
if (!CFG.handleVideo) { completeTask(); return; }
if (task.isPassed) { log('已完成跳过','green'); completeTask(); return; }
var target = dom && dom[0] ? dom[0] : null;
if (!target) { isProcessing=false; setTimeout(function(){processMedia(dom,task);},3000); return; }
var doc = target.contentDocument || target.contentWindow.document;
log('🎬 播放: ' + name, 'purple');
if (currentVideoTimer) clearInterval(currentVideoTimer);
var done = false;
currentVideoTimer = setInterval(function() {
var media = doc.querySelector('video') || doc.querySelector('audio');
if (media && !done) {
done = true;
media.pause();
media.muted = true;
media.playbackRate = Math.min(CFG.videoRate, 8);
media.play();
media.addEventListener('pause', function() { if (!media.ended) media.play(); });
media.addEventListener('ended', function() {
log('✅ 播放完成','green');
clearInterval(currentVideoTimer); currentVideoTimer = null;
completeTask();
});
if (media.ended) { clearInterval(currentVideoTimer); currentVideoTimer = null; completeTask(); }
} else if (media && done && media.ended) {
clearInterval(currentVideoTimer); currentVideoTimer = null; completeTask();
}
}, 1500);
}
function processAjaxTask(task, kind) {
if (isDone(task)) { completeTask(); return; }
var jobId = task.property.jobid;
var jtoken = task.jtoken;
var kid = defaults.knowledgeid, cid = defaults.courseid, clid = defaults.clazzId;
var path = kind === 'read' ? '/ananas/job/readv2' : (kind === 'document' ? '/ananas/job/document' : '/ananas/job');
var url = location.protocol + '//' + location.host + path + '?jobid=' + jobId + '&knowledgeid=' + kid + '&courseid=' + cid + '&clazzid=' + clid + '&jtoken=' + jtoken + '&_dc=' + Date.now();
GM_xmlhttpRequest({
method:'GET', url:url, timeout:10000,
onload: function() { log('📄 ' + kind + ' 完成','green'); completeTask(); },
onerror: function() { log('❌ ' + kind + ' 失败重试','red'); isProcessing=false; setTimeout(function(){processAjaxTask(task,kind);},3000); },
ontimeout: function() { log('⏰ ' + kind + ' 超时','orange'); isProcessing=false; setTimeout(function(){processAjaxTask(task,kind);},3000); }
});
}
/* ========== 测验答题 ========== */
function processQuiz(dom, task) {
log('📝 开始处理测验','purple');
// 在任务点iframe里找测验iframe
var outerDoc = dom[0] ? (dom[0].contentDocument || dom[0].contentWindow.document) : document;
var innerFrame = outerDoc.querySelector('iframe');
if (!innerFrame) { setTimeout(function(){processQuiz(dom,task);},3000); return; }
var innerDoc = innerFrame.contentDocument || innerFrame.contentWindow.document;
var questions = innerDoc.querySelectorAll('.TiMu');
if (!questions.length) {
// 可能是手机版
questions = innerDoc.querySelectorAll('.Py-mian1');
}
if (!questions.length) { log('未找到题目元素','orange'); setTimeout(function(){processQuiz(dom,task);},3000); return; }
log('找到 ' + questions.length + ' 道题','green');
var idx = 0;
function nextQ() {
if (idx >= questions.length) {
log('✅ 全部答完,保存','green');
var saveBtn = innerDoc.querySelector('.btnSave');
if (saveBtn) saveBtn.click();
setTimeout(completeTask, 3000);
return;
}
var qEl = questions[idx];
var qHtml = (qEl.querySelector('.Zy_TItle, .Py-m1-title')||qEl).innerHTML;
var clean = cleanTxt(qHtml);
// 判断题型
var qType = 4;
var hasCheckbox = qEl.querySelector('input[type="checkbox"]');
var hasRadio = qEl.querySelector('input[type="radio"]');
var hasTextarea = qEl.querySelector('textarea');
var hasInput = qEl.querySelector('input[type="text"]');
if (hasCheckbox) qType = 1;
else if (hasRadio || qEl.querySelector('.Zy_ulTop, .answerList')) qType = 0;
else if (qEl.querySelector('.Zy_ulTk, .blankList2') || hasInput) qType = 2;
else if (qEl.querySelector('.panduan, .answer_p')) qType = 3;
else if (hasTextarea) qType = 4;
var opts = [];
if (qType == 0 || qType == 1) {
$$('li a, .answer_p', qEl).forEach(function(el) { opts.push(cleanTxt(el.innerHTML)); });
} else if (qType == 3) {
opts = ['对','错'];
} else if (qType == 2) {
opts = [String(qEl.querySelectorAll('input[type="text"], textarea').length)];
} else {
opts = ['1'];
}
log('第' + (idx+1) + '题 类型=' + qType + ': ' + clean.substring(0,30), 'blue');
getAnswer(qType, clean, opts).then(function(ans) {
if (ans) {
if (CFG.insertAnswer) {
var p = innerDoc.createElement('p');
p.style.color = 'green'; p.textContent = '📖 ' + ans;
qEl.appendChild(p);
}
if (qType == 0) clickOption(qEl, ans);
else if (qType == 1) clickMulti(qEl, ans);
else if (qType == 3) clickJudge(qEl, ans);
else fillText(qEl, ans);
} else {
log('无答案','orange');
}
idx++;
setTimeout(nextQ, CFG.answerInterval);
}).catch(function(e) {
log('搜题失败: ' + e, 'red');
idx++;
setTimeout(nextQ, CFG.answerInterval);
});
}
nextQ();
}
/* ========== 作业 ========== */
function processHomework() {
log('📝 处理作业','green');
var qList = document.querySelectorAll('.mark_table .questionLi');
if (!qList.length) { log('作业页面未找到题目','orange'); return; }
log('找到 ' + qList.length + ' 道作业题','green');
var idx = 0;
function nextQ() {
if (idx >= qList.length) { log('✅ 作业全部完成','green'); return; }
var qEl = qList[idx];
var qHtml = (qEl.querySelector('.mark_name')||qEl).innerHTML;
var clean = cleanTxt(qHtml);
var qType = 4;
if (qEl.querySelector('input[type="checkbox"]')) qType = 1;
else if (qEl.querySelector('.answer_p') || qEl.querySelector('input[type="radio"]')) qType = 0;
else if (qEl.querySelector('.divText textarea') && qEl.querySelectorAll('.divText textarea').length === 1 && qEl.querySelector('.stem_answer .divText textarea')) qType = 2;
var opts = [];
if (qType == 0 || qType == 1) {
$$('.answer_p', qEl).forEach(function(el){ opts.push(cleanTxt(el.innerHTML)); });
} else if (qType == 3) {
opts = ['对','错'];
} else {
opts = ['1'];
}
getAnswer(qType, clean, opts).then(function(ans) {
if (ans) {
if (CFG.insertAnswer) {
var p = document.createElement('p'); p.style.color='green'; p.textContent='📖 '+ans;
qEl.querySelector('.mark_name').appendChild(p);
}
if (qType == 0) clickOption(qEl, ans);
else if (qType == 1) clickMulti(qEl, ans);
else if (qType == 3) clickJudge(qEl, ans);
else fillText(qEl, ans);
}
idx++;
setTimeout(nextQ, CFG.answerInterval);
}).catch(function() { idx++; setTimeout(nextQ, CFG.answerInterval); });
}
nextQ();
}
/* ========== 考试 ========== */
function processExam() {
log('📝 处理考试','green');
var $tb = document.querySelector('.mark_table .whiteDiv');
if (!$tb) { log('未找到考试区域','orange'); return; }
var qHtml = ($tb.querySelector('h3.mark_name')||{}).innerHTML || '';
var clean = cleanTxt(qHtml);
var qType = 4;
var opts = $$('.clearfix.answerBg .fl.answer_p', $tb);
if (opts.length) qType = $tb.querySelector('input[type="checkbox"]') ? 1 : 0;
var optTexts = opts.map(function(el){ return cleanTxt(el.innerHTML); });
getAnswer(qType, clean, optTexts).then(function(ans) {
if (ans) {
if (qType == 0) clickOption($tb, ans);
else if (qType == 1) clickMulti($tb, ans);
else if (qType == 3) clickJudge($tb, ans);
else fillText($tb, ans);
}
if (CFG.autoNextExam) {
setTimeout(function() {
var nb = document.querySelector('.nextDiv a.jb_btn');
if (nb) nb.click();
}, 2000 + Math.random()*3000);
}
});
}
/* ========== 字体解密(可选) ========== */
function decryptFont() {
if (!CFG.decryptFont) return;
var secs = document.querySelectorAll('.font-cxsecret');
if (!secs.length) return;
// 动态加载Typr
var s = document.createElement('script');
s.src = 'https://pkpkq.n1t.cn/font-decrypt/TyprMd5.js';
s.onload = function() { log('字体解密库加载完成','blue'); };
document.head.appendChild(s);
}
/* ========== 初始化 ========== */
function init() {
showPanel();
log('✅ 脚本已运行 path=' + location.pathname, 'green');
if (CFG.decryptFont) setTimeout(decryptFont, 2000);
if (location.pathname.includes('/knowledge/cards')) {
// 从页面script里找mArg
var params = null;
for (var i = 0; i < document.scripts.length; i++) {
var c = document.scripts[i].innerHTML || '';
if (c.indexOf('mArg') !== -1 && c.indexOf('attachments') !== -1) {
var m = c.match(/mArg\s*=\s*"([^"]+)"/);
if (m) { params = m[1]; break; }
}
}
if (!params) {
log('⚠️ 未找到任务参数(可能本页无任务点)','orange');
if (!jumpedNoTask) {
jumpedNoTask = true;
setTimeout(function() {
var b = document.querySelector('.prev_next.next:not(.disabled)');
if (b) b.click();
}, 2000);
}
return;
}
try {
var decoded = decodeURIComponent(params.replace(/"/g,''));
var data = JSON.parse(decoded);
defaults = data.defaults;
var tasks = data.attachments || [];
var pending = tasks.filter(function(t){return !isDone(t);});
log('📋 共'+tasks.length+'任务点, 待处理'+pending.length,'green');
if (!pending.length) { setTimeout(goNext, 2000); return; }
waitEl('.ans-attach-ct', 20000).then(function() {
taskList = []; domList = [];
var containers = document.querySelectorAll('.ans-attach-ct');
containers.forEach(function(ct, i) {
if (i < tasks.length && !isDone(tasks[i])) {
taskList.push(tasks[i]);
domList.push($$('iframe', ct));
}
});
if (taskList.length) { log('🚀 开始处理'+taskList.length+'个任务','green'); startMission(); }
}).catch(function(){ log('等待任务元素超时','red'); });
} catch(e) {
log('解析任务参数失败: ' + e.message, 'red');
}
} else if (location.pathname.includes('/exam/test/')) {
waitEl('.mark_table .whiteDiv', 15000).then(processExam);
} else if (location.pathname.includes('/mooc2/work/dowork') || location.pathname.includes('/work/doHomeWork')) {
waitEl('.mark_table', 15000).then(processHomework);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
//(注:内容由AI生成)