// ==UserScript== // @name 🥇超星/学习通学习小助手|修复视频播放|自动跳转任务点作业、考试覆盖98%|后台自动挂机|闯关课程|自动答题|阅读时长|1:1时长|章测作业字体解密|自动答题|最新题库每天自动更新 // @version 2.0 // @description ✨超星学习通⚪视频自动观看,跳转下一个任务点⚪章节测试自动完成,搜索无答案自动后台检索,可视化配置界面,参数DIY⭐️【复习模式】可补次数补时长,⭐️【闯关课程】支持闯关模式课程全自动学习,无答案保存⚪最新题库每半个小时自动更新 // @author aliang // @run-at document-end // @match *://*.chaoxing.com/* // @match *://*.edu.cn/* // @match *://*.nbdlib.cn/* // @match *://*.hnsyu.net/* // @match *://*.gdhkmooc.com/* // @connect cx.icodef.com // @connect api.tikuhai.com // @connect token.aliangsq.cn // @connect sso.chaoxing.com // @connect mooc1-api.chaoxing.com // @connect mooc1-1.chaoxing.com // @connect mooc1-2.chaoxing.com // @connect mooc2-ans.chaoxing.com // @connect cdn.bootcdn.net // @connect cdnjs.cloudflare.com // @connect mooc1.chaoxing.com // @connect fystat-ans.chaoxing.com // @connect stat2-ans.chaoxing.com // @connect mooc1.gdhkmooc.com // @connect mooc2-ans.hnsyu.net // @connect mooc1.hnsyu.net // @connect mooc1.hlju.edu.cn // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAADlQTFRFR3BMGvopGvopGvspGfwpGfooG/0pGvooGvopGfspGfopGfopGvooGvspGPgpGvspGf8oGvspGvopI5sFGQAAABJ0Uk5TAG/YyTCqGH9QuZthI+hC8g6LKC6qBQAAAT1JREFUeNrFk0tuxDAMQ+mvLH9ih/c/bGE5U7TFoNt5GwWgSDEBgg8TL7yhf8uVTPhLCdSMjZCkLmyy9sekNNfRvSZWAHCknHRPclCOrhEXFWjb1c3vybuAAyhksLUKsAoVm0AWIO4FpQf2cHsMtueSsxHQyAjgMgcchzX1lOOqCKdpOjn+VBXODrsuGOZspDvDPlg9e8qRM7nswMhW7VXRWQ4F0V6Bp0HhqbhjTfcZnTM30y05wJi8UMkRrV0ifXmSK4xE9Xz6dCXdehkdDoPkHXHoGQ/KgociCy9yLE5E9mpK+Ekvrqqf01dX4sJvrSXPEaq0o+R4Xdd3ZLk9R2rdniUFP+m1SjmqU1JdBFa5dXCGKiXml7elGe6ysC4JZJAr4ycyLbc7nbS9v8RlIfR1770nzeQi/qHFz/6fXz/9ELvsFfnDAAAAAElFTkSuQmCC // @grant unsafeWindow // @grant GM_info // @grant GM_getResourceText // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @require https://greasyfork.org/scripts/456170-hacktimerjs/code/hacktimerjs.js?version=1143079 // @require https://lib.baomitu.com/jquery/3.6.0/jquery.min.js // @require https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js // @resource layxcss https://cdn.bootcdn.net/ajax/libs/layx/2.5.4/layx.min.css // @resource layxcss https://cdnjs.cloudflare.com/ajax/libs/layx/2.5.4/layx.min.css // @resource layuicss https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/layui/2.6.8/css/layui.min.css // @resource ttf https://www.forestpolice.org/ttf/2.0/table.json // @antifeature payment 存在第三方付费接口 // @namespace noshuang // ==/UserScript== /******/ (() => { // webpackBootstrap var __webpack_exports__ = {}; var defaultConfig = { ua: 'Dalvik/2.1.0 (Linux; U; Android 11; M3121K1AB Build/SKQ1.211006.001) (device:M3121K1AB) Language/zh_CN com.chaoxing.mobile/ChaoXingStudy_3_5.1.4_android_phone_614_74 (@Kalimdor)_', interval: 3000, autoVideo: true, autoRead: true, autoAnswer: true, videoSpeed: 1, reviewMode: false, matchRate: 0.8, autoSubmitRate: 0.8, autoSubmit: true, autoSwitch: false, tutorial: true, randomAnswer: false, threadWatch: true, freeFirst: true, readSpeed: 10, notice: '本脚本仅供学习研究,请勿使用于非法用途!', debugger: false, types: { '单选题': '0', '多选题': '1', '填空题': '2', '判断题': '3', '简答题': '4', '名词解释': '5', '论述题': '6', '计算题': '7', }, /** 付费题库可将token填入下方''中 */ token: '', aiAsk:false }, otherApi = [ { desc: "接口来源:https://cx.icodef.com/query.html", url: 'http://cx.icodef.com/wyn-nb?v=4', headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', 'Authorization': ''/** 一之题库token填写 */ }, method: 'post', getdata: (data) => { return `question=${encodeURIComponent(data.question)}`; }, getanswer: (response) => { const res = JSON.parse(response.responseText); if (res.code === 1) { let data = res.data.replace(/javascript:void\(0\);/g, '').trim().replace(/\n/g, ''); if (data.includes('叛逆') || data.includes('公众号') || data.includes('李恒雅') || data.includes('一之')) { return false; } else { return data.split("#"); } } return false; } } ], _self = unsafeWindow, top = (/* unused pure expression or super */ null && (_self)), script_info = GM_info.script, cache_key = "20230524", reqUrl = [ { "api": "http://token.aliangsq.cn/", "headers": {} }, ], icon = ``; let cacheData = GM_getValue(cache_key); if (cacheData && !cacheData.token) cacheData.token = defaultConfig.token; defaultConfig = cacheData || defaultConfig; const log = msg => defaultConfig.debugger && console.log(msg); (function () { 'use strict'; const _postMessage = unsafeWindow.postMessage; unsafeWindow.postMessage = function (msg, targetOrigin, transfer) { if (msg && msg.includes('"toggle":true')) { msg = msg.replace('"toggle":true', '"toggle":false'); } _postMessage.call(unsafeWindow, msg, targetOrigin, transfer); }; String.prototype.cl = function () { return this.replace(/^【.*?】\s*/, '').replace(/\s*(\d+\.\d+分)$/, '') }; var utils = { randomStr: (len = 32) => { const $chars = 'qwertyuioplkjhgfdsazxcvbnm1234567890'; let ss = ''; for (let i = 0; i < len; i++) { ss += $chars.charAt(Math.floor(Math.random() * $chars.length)); } return ss; }, notify: (level, msg) => { let data = { level: level, msg: msg } return JSON.stringify(data); }, sortData: (data) => { const arr = []; data.forEach(item => { const parent = data.find(item2 => item2.id === item.parentnodeid); parent ? (parent.children || (parent.children = [])).push(item) : arr.push(item); }); return arr; }, toOneArray: (arr) => { return arr.reduce((newArr, item) => newArr.concat(item, item.children ? utils.toOneArray(item.children) : []), []); }, sleep: (time) => { return new Promise(resolve => setTimeout(resolve, time)); }, getUrlParam: (name) => { const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); const r = window.location.search.substr(1).match(reg); return r ? unescape(r[2]) : null; }, toQueryString: (obj) => { return obj ? Object.keys(obj).sort().map(key => { const val = obj[key]; return Array.isArray(val) ? val.sort().map(val2 => encodeURIComponent(key) + '=' + encodeURIComponent(val2)).join('&') : encodeURIComponent(key) + '=' + encodeURIComponent(val); }).join('&') : ''; }, getInputParam: (name) => { const input = document.getElementsByName(name)[0]; return input ? input.value : null; }, getVideoEnc: (clazzid, uid, jobid, objectId, playingTime, duration) => { return md5("[" + clazzid + "][" + uid + "][" + jobid + "][" + objectId + "][" + (playingTime * 1000) + "][d_yHJ!$pdA~5][" + (duration * 1000) + "][0_" + duration + "]"); }, getTimestamp: () => { return new Date().getTime(); } , removeHtml: (html) => { if (html == null) { return ''; } // 判断是否为字符串 if (typeof html !== 'string') { return html; } return html.replace(/<((?!img|sub|sup|br)[^>]+)>/g, '').replace(/ /g, ' ').replace(/\s+/g, ' ').replace(//g, '\n').replace(//g, '').trim(); } , cache: (key, value) => { GM_setValue(key, { value: value, time: utils.getTimestamp() }); return value; }, cacheExpired: (key, time) => { var cache = GM_getValue(key); if (cache) { if (cache.time + time > utils.getTimestamp()) { return cache.value; } } return false; }, matchIndex: (options, answer) => { var matchArr = []; for (var i = 0; i < answer.length; i++) { for (var j = 0; j < options.length; j++) { if (answer[i] == options[j]) { matchArr.push(j); } } } return matchArr; } , similarity: (s, t) => { let l = Math.max(s.length, t.length); let n = s.length; let m = t.length; let d = Array.from({ length: n + 1 }, (_, i) => [i]); for (let j = 0; j <= m; j++) d[0][j] = j; for (let i = 1; i <= n; i++) for (let j = 1; j <= m; j++) { let cost = s[i - 1] === t[j - 1] ? 0 : 1; d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); } return (1 - d[n][m] / l); } , fuzzyMatchIndex: (options, answer) => { const matchArr = []; for (const ans of answer) { let maxSim = 0, index = 0; for (let i = 0; i < options.length; i++) { const sim = utils.similarity(ans, options[i]); if (sim > maxSim) { maxSim = sim; index = i; } } if (maxSim > defaultConfig.matchRate) matchArr.push(index); } return matchArr; } }; var api = { monitorVerify: (responseText, url, method, data, ua) => { return new Promise((resolve, reject) => { try { let obj = JSON.parse(responseText); let divHtml = ' '; layx.prompt(divHtml, "请输入验证码", function (id, value, textarea, button, event) { let url = obj.verify_path + "&ucode=" + value; window.open(url); }); } catch (error) { let domain = url.match(/:\/\/(.[^/]+)/)[1]; let urlShowVerify = "https://" + domain + "/antispiderShowVerify.ac"; page.layx_log(`若未自动弹出页面,请点我打开`, 'error'); layx.iframe('verifyCode', '验证码验证', urlShowVerify); let timer = setInterval(() => { api.defaultRequest(url, method, data, ua, true).then((response) => { if (response.responseText && !response.responseText.includes('输入验证码')) { layx.destroy('verifyCode'); clearInterval(timer); page.layx_log('验证码验证成功!', 'success'); resolve(response); } else { page.layx_log('验证码验证失败!将在5s后重新验证', 'error'); } }) }, 5000); } }); }, defaultRequest: async (url, method, data = {}, ua = defaultConfig.ua, verify = false) => { try { const response = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ url, method, headers: { 'User-Agent': ua, 'X-Requested-With': 'XMLHttpRequest', 'Sec-Fetch-Site': 'same-origin', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, data: utils.toQueryString(data), onload: resolve, onerror: reject }); }); if (!verify && response.responseText && response.responseText.includes('输入验证码')) { page.layx_log('检测到验证码!将弹出新页面自行验证验证码(出现验证码多为间隔频率过短,或者请求过多,请根据自己情况调高运行间隔)', 'error'); await api.monitorVerify(response.responseText, url, method, data, ua); return await api.defaultRequest(url, method, data); } return response; } catch (err) { if (err.error.indexOf("connect list") != -1) { let domain = err.error.match(/:\/\/(.[^/]+)/)[1]; let notice = `由于connect未添加导致无权限请求
// @connect ${domain}`; page.layx_log(notice, 'error'); } return Promise.reject(err); } } , getVerifyCode: async (url) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, responseType: "blob", onload: function (res) { var blob = res.response; var reader = new FileReader(); reader.onload = function (event) { resolve(event.target.result); }; reader.readAsDataURL(blob); } }); }); }, getCourseChapter: async (courseId, classId) => { let url = _self.ServerHost.mooc1Domain + "/gas/clazz?id=" + classId + "&personid=" + courseId + "&fields=id,bbsid,classscore,isstart,allowdownload,chatid,name,state,isfiled,visiblescore,begindate,coursesetting.fields(id,courseid,hiddencoursecover,coursefacecheck),course.fields(id,name,infocontent,objectid,app,bulletformat,mappingcourseid,imageurl,teacherfactor,jobcount,knowledge.fields(id,name,indexOrder,parentnodeid,status,layer,label,jobcount,begintime,endtime,attachment.fields(id,type,objectid,extension).type(video)))&view=json"; let result = await api.defaultRequest(url, 'GET'); return JSON.parse(result.responseText); }, getChapterList: async (courseid, clazzid, nodes, userid, cpi) => { let data = { "view": "json", "nodes": nodes, "clazzid": clazzid, "userid": userid, "cpi": cpi, "courseid": courseid, "time": (new Date()).valueOf() } let result = await api.defaultRequest(_self.ServerHost.mooc1Domain + "/job/myjobsnodesmap", 'post', data); return JSON.parse(result.responseText); }, getChapterInfo: async (id, courseid) => { let data = { "id": id, "courseid": courseid, "fields": "id,parentnodeid,indexorder,label,layer,name,begintime,createtime,lastmodifytime,status,jobUnfinishedCount,clickcount,openlock,card.fields(id,knowledgeid,title,knowledgeTitile,description,cardorder).contentcard(all)", "view": "json", } let url = _self.ServerHost.mooc1Domain + "/gas/knowledge?" + utils.toQueryString(data); let result = await api.defaultRequest(url, 'get'); return JSON.parse(result.responseText); }, getChapterDetail: async (courseid, clazzid, knowledgeid, num, cpi) => { let url = _self.ServerHost.mooc1Domain + "/knowledge/cards?clazzid=" + clazzid + "&courseid=" + courseid + "&knowledgeid=" + knowledgeid + "&num=" + num + "&cpi=" + cpi + "&ut=s&cpi=229749849&v=20160407-1"; let result = await api.defaultRequest(url, 'get'); return result.responseText; }, uploadStudyLog: async (courseid, clazzid, knowledgeid, cpi) => { let url = `${location.origin}/mooc2-ans/mycourse/studentcourse?courseid=${courseid}&clazzid=${clazzid}&cpi=${cpi}&ut=s&t=${utils.getTimestamp()}` let text = await api.defaultRequest(url, 'get', {}, navigator.userAgent); let match = text.responseText.match(/encode=([\w]+)/); if (match) { const encode = match[1]; let url = `${_self.ServerHost.moocTJDomain}/log/setlog?personid=${cpi}&courseId=${courseid}&classId=${clazzid}&encode=${encode}&chapterId=${knowledgeid}&_=${new Date().valueOf()}`; let result = await api.defaultRequest(url, 'get', {}, navigator.userAgent); return result.responseText; } return false; }, docStudy: async (jobid, knowledgeid, courseid, clazzid, jtoken) => { let url = _self.ServerHost.mooc1Domain + "/ananas/job/document?jobid=" + jobid + "&knowledgeid=" + knowledgeid + "&courseid=" + courseid + "&clazzid=" + clazzid + "&jtoken=" + jtoken + "&_dc=" + new Date().valueOf(); let result = await api.defaultRequest(url, 'get', {}, navigator.userAgent); return JSON.parse(result.responseText); }, videoStudy: async (data, dtoken, taskDefaultConfig) => { let url = taskDefaultConfig.reportUrl + "/" + dtoken + "?" + utils.toQueryString(data); let result = await api.defaultRequest(url, 'get', {}, navigator.userAgent); return JSON.parse(result.responseText); }, getVideoConfig: async (objectId) => { let url = _self.ServerHost.mooc1Domain + "/ananas/status/" + objectId + "?k=&flag=normal&_dc=" + new Date().valueOf(); let result = await api.defaultRequest(url, 'get'); return JSON.parse(result.responseText); }, unlockChapter: async (courseid, clazzid, knowledgeid, userid, cpi) => { let url = `${_self.ServerHost.mooc1Domain}/job/submitstudy?node=${knowledgeid}&userid=${userid}&clazzid=${clazzid}&courseid=${courseid}&personid=${cpi}&view=json`; let result = await api.defaultRequest(url, 'get', {}, navigator.userAgent); return result.status; }, initdatawithviewer: async (mid, cpi, classid, taskDefaultConfig) => { let url = `${taskDefaultConfig.initdataUrl}?mid=${mid}&cpi=${cpi}&classid=${classid}&_dc=${new Date().valueOf()}`; let result = await api.defaultRequest(url, 'get'); return JSON.parse(result.responseText); } , submitdatawithviewer: async (classid, cpi, objectid, eventid, memberinfo, answer) => { let url = `${_self.ServerHost.mooc1Domain}/question/quiz-validation?classid=${classid}&cpi=${cpi}&objectid=${objectid}&_dc=${new Date().valueOf()}&eventid=${eventid}&memberinfo=${memberinfo}&answerContent=${answer}`; let result = await api.defaultRequest(url, 'get'); return JSON.parse(result.responseText); } }; var ServerApi = { request: async function(url, method, data, headers = {}){ return new Promise(function (resolve, reject) { GM_xmlhttpRequest({ method: method, url: url, data: JSON.stringify(data), headers: headers, timeout: 5000, onload: function (response) { resolve(response); }, onerror: function (response) { reject(response); }, ontimeout: function (response) { reject(response); } }); }); }, defaultRequest: async function (url, method, data, headers = {}) { if (_self.getCookie == undefined) { _self.getCookie = function (name) { return ''; }; } headers = Object.assign({ 'Content-Type': 'application/json', 'v': script_info.version, 'referer': location.href, 't': utils.getTimestamp(), "token": defaultConfig.token || '', "u": _self.uid || _self.getCookie('UID') || _self.getCookie("_uid") || '', }, headers); for (let i = 0; i < reqUrl.length; i++) { let api = reqUrl[i]; console.log(api) let reqHeaders = Object.assign({}, api.headers, headers); let res = await ServerApi.request(api.api + url, method, data, reqHeaders).catch((e) => { return false; }); console.log(res) if (res && res.status === 200) { return res; } } }, search: async function (data, status = true) { data.key = status && defaultConfig.token || ''; $(".layx_status").html("正在搜索答案"); let params = { "z": data.workType, "t": data.type, "u": _self.uid || _self.getCookie('UID') || _self.getCookie("_uid") || '', } data.source = 'xy_'+script_info.version; var url = 'search?' + utils.toQueryString(params); const res = await ServerApi.defaultRequest(url, 'post', data); return res; }, configRequest: async function (url) { return await ServerApi.defaultRequest(url, 'get'); }, get_msg: async function () { let url = 'def/autoMsg'; let res = await ServerApi.defaultRequest(url, 'get'); try { let reqData = JSON.parse(res.responseText); return reqData.data; } catch (e) { return defaultConfig.notice; } }, searchOther: (data, item) => { return new Promise(async function (resolve, reject) { GM_xmlhttpRequest({ method: item.method, url: item.url, data: item.getdata(data), headers: item.headers, timeout: 5000, onload: function (response) { resolve(response); }, onerror: function (response) { reject(response); }, ontimeout: function (response) { reject(response); } }); }); }, checkKey: async function (key) { if (!key) { page.layx_log("秘钥为空停止检测", "notice"); } let url = 'key'; let data = { "key": key } let res = await ServerApi.defaultRequest(url, 'post', data); try { res = JSON.parse(res.responseText); if (res.code === 200) { reqUrl.num = res.data.num || null; reqUrl.usenum = res.data.usenum || null; } page.layx_log(res.msg, "notice"); } catch (error) { page.layx_log("秘钥验证失败", "notice"); } }, getVerifyCode: async function (img) { let url = 'code'; let data = { "img": img.replace('data:image/png;base64,', '') } let res = await ServerApi.defaultRequest(url, 'post', data); return JSON.parse(res.responseText).data.code; } } var page = { threadWatch: async function () { if (!defaultConfig.threadWatch) { return; } log('线程守护已开启'); let thread = setInterval(async function () { let layx_status_msg = $("#layx_status_msg"); if (!layx_status_msg.length) { alert("未检测到悬浮窗,已自动关闭线程守护"); clearInterval(thread); } if (defaultConfig.lastMsg && defaultConfig.lastMsg.indexOf("每60秒更新一次进度") !== -1) { if (defaultConfig.lastMsg === layx_status_msg.html()) { location.reload(); } } else { log("一切正常"); } defaultConfig.lastMsg = layx_status_msg.html(); log(layx_status_msg.html()); }, 320000); }, init: async function () { GM_addStyle(GM_getResourceText("layxcss")); GM_addStyle(GM_getResourceText("layuicss")); defaultConfig.workinx = 0; defaultConfig.succ = 0; defaultConfig.fail = 0; log(location.pathname); switch (location.pathname) { case '/exam-ans/exam/test/reVersionTestStartNew': case '/exam/test/reVersionTestStartNew': case '/mooc-ans/exam/test/reVersionTestStartNew': if (location.href.includes('newMooc=true')) { await this.layx("ks", { title: "🔥考试界面", // storeStatus:false, width: 350, height: 800 }); $('#layx_log, h2').hide(); $('#layx_content').css('margin', '10px'); const createButton = (text, onClick) => { const btn = document.createElement('button'); btn.innerHTML = text; btn.classList.add('layui-btn', 'layui-btn-primary', 'layui-border-black'); btn.style.margin = '10px 0px 10px 10px'; btn.onclick = onClick; return btn; }; const btn = createButton(defaultConfig.autoSwitch ? '关闭自动切换' : '开启自动切换', () => { defaultConfig.autoSwitch = !defaultConfig.autoSwitch; btn.innerHTML = defaultConfig.autoSwitch ? '关闭自动切换' : '开启自动切换'; defaultConfig.autoSwitch && location.reload(); GM_setValue(cache_key, defaultConfig); }); const btn1 = createButton('配置', () => { log(defaultConfig); page.layx_config(); }); $('#layx_content').before($('
').attr('id', 'btn_cc').css('margin', '10px').append(btn, btn1)); this.layx_status_msg('初始化完成'); let reqData = page.getQuestion("3"); this.layx_status_msg("自动答题中....."); await page.startAsk(reqData); break; } else { let url = location.href; if (!url.includes('newMooc=false')) { url = url + '&newMooc=true'; } else { url = url.replace('newMooc=false', 'newMooc=true'); } location.href = url; break; } case '/mycourse/stu': case '/mooc-ans/mycourse/stu': case '/mooc2-ans/mycourse/stu': await this.layx(); page.threadWatch(); const btn = document.createElement("button"); btn.innerHTML = "配置"; btn.classList.add("layui-btn", "layui-btn-primary", "layui-border-black"); btn.style.margin = "10px 0px 10px 10px"; btn.onclick = () => { page.layx_config() }; document.getElementById("layx_content").appendChild(btn); this.layx_log("正在检测题库", "notice"); ServerApi.checkKey(defaultConfig.token); this.layx_log("正在启动任务,预计耗时" + defaultConfig.interval / 1000 + "秒"); await utils.sleep(defaultConfig.interval); this.layx_status_msg("正在等待任务加载"); this.mainTask(); break; case '/workHandle/handle': case '/mooc-ans/workHandle/handle': case '/mooc2-ans/workHandle/handle': window.parent.postMessage(utils.notify("error", "作业已被删除-跳过"), '*'); break; case '/work/doHomeWorkNew': case '/mooc-ans/work/doHomeWorkNew': case '/mooc2-ans/work/doHomeWorkNew': if (document.body.innerHTML.indexOf("此作业已被老师") !== -1) { window.parent.postMessage(utils.notify("error", "作业已被删除-跳过"), '*'); break; } if (document.body.innerHTML.indexOf("您长时间没有操作") !== -1) { window.parent.postMessage(utils.notify("error", "遇到一个bug,后期修复"), '*'); break; } if (location.href.includes('reEdit=2')) { this.getScore(); await utils.sleep(defaultConfig.interval); window.parent.postMessage(utils.notify("error", "作业待批阅"), '*'); break; } if (location.href.includes('mooc2=1')) { // 删除url中的mooc2=1 // location.href = location.href.replace(/&mooc2=1/g, ''); } if (location.href.includes('oldWorkId')) { try { page.decode(); } catch (e) { log(e); } await page.layx("zj", { closeMenu: false, maxMenu: true, title: '🔥作业答题(本窗口禁止关闭)', width: 600, height: 300, storeStatus: false, position: 'lt' }); const btn1 = $('