// ==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]
' + '
' + '
' + '' + '' + '' + '' + '
' + '
' + '
🔑 硅基流动API Key
' + '' + '
免费获取: siliconflow.cn 注册即送14元免费额度
' + '
' + '
' + ' ' + '' + '
' + '
' + '
'; 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生成)