// ==UserScript== // @name 【改】职教云 // @version 2.16.0 // @description 职教云刷课刷题助手脚本,中文化自定义各项参数,解除作业区复制粘贴限制,提供考试支持,自动三项评论,智能讨论,搜题填题,软件定制 // @author tuChanged // @run-at document-end // @grant unsafeWindow // @grant GM_xmlhttpRequest // @match *://*.zjy2.icve.com.cn/* // @match *zjy2.icve.com.cn/* // @license MIT // @namespace https://greasyfork.org/users/449085 // @supportURL https://github.com/W-ChihC/SimpleIcveMoocHelper // @contributionURL https://greasyfork.org/users/449085 // ==/UserScript== (function () { 'use strict'; const setting = { // 随机评论,自行扩充格式如 "你好", (英文符号) 随机评论词库: ["老师讲的生动形象","学有所获"], //感谢@清酒不浊 提醒,策略改变,已只要求点击 (3月14号更新后,已失效) 激活点即完: false, /*影响刷课速度关键选项,延时非最优解,过慢请自行谨慎调整*/ 最高延迟响应时间: 4000,//毫秒 最低延迟响应时间: 2000,//毫秒 //自行根据课件情况修改 固定PPT页数: 100,//页 //0-高清 1-清晰 2-流畅 3-原画 //感谢tonylu00提供最新实测参数 --0-原画 1-高清 2-清晰 3-流畅 视频清晰度: 3, //倍速开启成功,目测5倍速可以,更高可能到时封号,谨慎使用 视频播放倍速: 5, //是否保持静音 是否保持静音: true, //开启所有选项卡的评论,最高优先等级,打开该项会覆盖下面的细分设置,默认关闭(false),true为打开 激活所有选项卡的评论: false, 激活评论选项卡: false, 激活问答选项卡: false, 激活笔记选项卡: false, 激活报错选项卡: false, //和以上设置保持同步 未做兼容课件打开评论: false, //在完成课件之前打开评论, 激活提前评论: false /* * 📣如果您有软件定制(管理系统,APP,小程序等),毕设困扰,又或者课程设计困扰等欢迎联系, * 价格从优,源码调试成功再付款💰, * 实力保证,包远程,包讲解 QQ:2622321887 */ }, _self = unsafeWindow, url = location.pathname, top = _self /** 等待获取jquery @油猴超星网课助手 wyn665817*/ try { while (top != _self.top) top = top.parent.document ? top.parent : _self.top; } catch (err) { console.log(err); top = _self; } let $ = _self.jQuery || top.jQuery; /** */ //产生区间随机数 const rnd = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); //跳转下一页 // let nextCourse = () => $(".next").click(); const lessonID = getQueryValue("cellId") console.log(`当前课程ID: ${lessonID}`); //脚本处理入口函数,仅运行一次 delayExec(async () => { //出现弹窗时点击下一步 $(".ui-dialog").find("#studyNow").click() //入口 switch (url) { //课件区 case "/common/directory/directory.html": openMenu() await delayExec(async () => { await expandDir(); console.log("目录全展开."); }) await delayExec(() => { locateCurrentLocation() }) handleCurrentLesson(); break; //作业区 case "/study/homework/preview.html": case "/study/homework/do.html": case "/study/onlineExam/preview.html": case "/study/onlineExam/do.html": homeworkHandler() break; // default } console.log(`脚本已启动 当前位置:${url}`); }) //当前页 let current; //处理当前选中的课程 async function handleCurrentLesson() { //打开课程列表 openMenu() //main函数 setTimeout(async () => { //当前小节 current = $(".np-section-level-3.active"); //跳到第一页 if (current.length == 0) { console.log(current); current = $($(".np-section-level-3")[0]) } // //当前已完成直接开始下一轮 // if (isFinshed(current)) { // check(current.next()); // return // } if (setting.激活点即完) { delayExec(commentHandler(current)) return } else { //当前小节课程的类别 let type = current.children(".np-section-type").text().trim() switch (type) { case "图片": case "文档": docHandler(current) break; case "ppt": pptHandler(current) break; case "swf": swfHandler(current) break; case "视频": case "音频": mediaHandler(current) break; case "图文": case "压缩包": emptyHandler(current) break; case "": check(current.next()) break; default: console.log(`课件 : ${type} 未提供兼容, ${setting.未做兼容课件打开评论 ? '已开启兼容评论,仅运行评论' : '已跳过处理'},请在github issue(https://github.com/W-ChihC/SimpleIcveMoocHelper)反馈该日志,与作者取得联系`); check(current.next()) break } console.log(`当前 ${type} 安排完成,等待执行结果中`); } }, 5000); } /** * 递归遍历目录树 */ async function check(currentInner) { //多级跳转 if (currentInner.length == 0) { // current.end(); //往树根遍历 //小章节 let parent = current.closest(".np-section-level-2"); if (parent.next().length == 0) { //大章 let ancestor = parent.closest(".np-section-level-1") //检测是否到终章 if (ancestor.next().length == 0) { alert("任务完成"); //关闭当前窗口 // closeTab(); } else { // first 进来后 next后导致空出一个 check(ancestor.next().find(".np-section-level-3").first()); } } else { check(parent.next().find(".np-section-level-3").first()) } return; } //查询下一项所属类别 switch (currentInner.children(".np-section-type").text().trim()) { case "swf": case "ppt": case "视频": case "文档": case "图片": case "图文": case "压缩包": case "音频": await delayExec(() => gotoUrl(currentInner)) handleCurrentLesson() break case "": await delayExec(() => gotoUrl(currentInner.next())) handleCurrentLesson() break default: await delayExec(() => gotoUrl(currentInner.next())) handleCurrentLesson() } } /** * 使用异步实现 * * 随机延迟执行方法 * @param {需委托执行的函数} func */ //评论限制时间 function delayExec(func,time) { console.log("自定义时间:"+time) return new Promise((resolve, reject) => { setTimeout(async () => { try { await func() } catch (error) { console.log(error); } resolve(); // 自定义时间,或者使用全局时间 }, rnd(time || setting.最低延迟响应时间, time || setting.最高延迟响应时间)); }) } //手动加锁 防止递归失败请求数太多导致封禁 let block = false; //跳转到某小节 通过顶栏 function gotoUrl(page) { if (block) { alert('异步处理异常') while (true) console.log("程序运行异常"); } block = true page.click() block = false // resovle() } //打开菜单 const openMenu = () => { //关闭窗口 if ($('.popBox').length !== 0) { $($('.popBox a')[1]).click() } $(".sildeDirectory").click(); } /** * 获取url查询字段 * @param {查询字段} query */ function getQueryValue(query) { let url = window.location.search; //获取url中"?"符后的字串 let theRequest = new Object(); if (url.indexOf("?") != -1) { let str = url.substr(1); let strs = str.split("&"); for (let i = 0; i < strs.length; i++) theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]); } return theRequest[query]; } /** * 找到从课程列表进来点击的位置 * @param {*} id */ function locateCurrentLocation() { $('.np-section-level-3.cellClick').each((i, e) => { let x = $(e) if (x.data().cellid === lessonID) { console.log(lessonID, e); x.click() return false } }) // console.log($('.np-section-level-3.cellClick').length); } /** * 异步展开全目录 */ function expandDir() { return new Promise((resolve, reject) => { let root = $(".np-section-level-1").children(".np-section-title"); //查找大章节 let endFlag = 0 root.each(async (i1, e1) => { $(e1).click() //点击大章节 //fix 空大章节 if ($(e1).children().length == 0) { endFlag++ } await delayExec(async () => { $(e1).next("ol").find(".np-section-level-2").children("a").each(async (i2, e2) => { await delayExec(async () => { $(e2).click() //执行完成 if (i1 === endFlag) { resolve() } }) }) }) }) }) } /** * 仅仅评论的处理器 * @param {*} current */ async function emptyHandler(current) { if (setting.激活提前评论) { delayExec(commentHandler(current)); return } await delayExec(commentHandler(current)) } async function swfHandler(current) { if (setting.激活提前评论) { delayExec(commentHandler(current)); return } //当不支持flash时执行 if ($('.popBox').length !== 0) { $($('.popBox a')[1]).click() } await delayExec(commentHandler(current)) } /** * 视频/音频类处理 */ function mediaHandler(current) { if (setting.激活提前评论) { delayExec(commentHandler(current)); return } // jw-video let player = top.jwplayer($(".jwplayer").attr("id")); // let player2 = top.jw console.log(player) //视频暂停状态 if (player.getState() == "paused") { console.log("媒体已暂停,恢复播放"); player.play() } //播放回调 if (player.getState() == "complete") { console.log("媒体已播放完毕\n"); delayExec(commentHandler(current)); return; } //配置 player.setMute(setting.是否保持静音)//静音 player.setCurrentQuality(setting.视频清晰度) try { console.log('倍速开启成功,目测5倍速可以,更高可能到时封号,谨慎使用'); // console.log(setting.视频播放倍速) player.setPlaybackRate(setting.视频播放倍速) // player.playbackRate=setting.视频播放倍速 } catch (error) { console.log('倍速开启失败'); console.log(error); } //播放回调 player.on("playlistComplete", () => { console.log("媒体播放完成\n"); delayExec(commentHandler(current)); }); } /** * 文档处理 * @param {*} current */ async function docHandler(current) { if (setting.激活提前评论) { delayExec(commentHandler(current)); } //自定义时间 let customTime=300; //随机秒后执行,避免不正常操作加载时间 //根据按钮状态判断是否还有下一页 while ($(".MPreview-pageNext").hasClass('current')) { console.log("文档翻页了"); //ppt翻页 异步方式 await delayExec(() => { $(".MPreview-pageNext").click() },customTime) } //提交评论? //随机延迟提交评论 // setTimeout("console.log(123)",2000); delayExec(commentHandler(current)); } /** * PPT类别处理 * 指定PPT点击次数(无法获取iframe无法判定是否完成) * TODO 无法跨域获取iframe,暂未解决 */ async function pptHandler(current) { if (setting.激活提前评论) { delayExec(commentHandler(current)); return } // console.log($("iframe").context.images.length); // console.log($(window.frames["frames"].document).find(".SC")); // console.log($(".SC").length) // 异步处理 await new Promise(async (resolve, reject) => { //自定义时间 let customTime=300; if($(".page-bar").length > 0){ // let pageInput=$(".MPreview-pageInput").val().replace(/\b(0+)/gi,""); // console.log("啊啊:"+pageInput); while ($(".MPreview-pageNext").hasClass('current')) { console.log("ppt翻页了"); //ppt翻页 异步方式 await delayExec(() => { $(".MPreview-pageNext").click() },customTime) } resolve() }else{ for (let i = 1; i <= setting.固定PPT页数; i++) { //点击下一页 await delayExec(() => { $(".stage-next-btn").click() console.log(`ppt第${i}页`); //达到次数解除阻塞 if (i == setting.固定PPT页数) resolve() },customTime) } } }) //提交评论? //随机延迟提交评论 delayExec(commentHandler(current)); } /** * 处理评论 * 并准备换页 */ async function commentHandler(current) { if (setting.激活评论选项卡 || setting.激活所有选项卡的评论){ await submitComment(current) } if (setting.激活问答选项卡 || setting.激活所有选项卡的评论) { await submitQuestion(current) } if (setting.激活笔记选项卡 || setting.激活所有选项卡的评论){ await submitNote(current) } if (setting.激活报错选项卡 || setting.激活所有选项卡的评论) { await submitReport(current) } console.log("完成评论环节"); check(current.next()) } /** * 评论 */ async function submitComment() { let customTime = 1000 //自定义时间 await delayExec(() => { $($(".am-tabs-nav>li a")[0]).click() }) return new Promise(async (resolve, reject) => { if (isFinshed(".np-question-remove.commentDel")) { resolve() return } //评5星 $("#star #starImg4").click(); //随机从词库填写评论 $(".commentContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)]) //提交 await delayExec(async () => { $("#btnComment").click(); await delayExec(async () => { $(".sgBtn.ok").click(); console.log("评论成功\n"); resolve() }); },customTime); }) } /** * 问答 */ async function submitQuestion() { let customTime = 1000 //自定义时间 await delayExec(() => { $($(".am-tabs-nav>li a")[1]).click() }) return new Promise(async (resolve, reject) => { if (isFinshed(".np-question-remove.questionDel")) { resolve() return } //随机从词库填写评论 $(".questionContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)]) //提交 await delayExec(async () => { $("#btnQuestion").click(); await delayExec(async () => { $(".sgBtn.ok").click(); console.log("问答成功\n"); resolve() }); },customTime); }) } /** * 笔记 * @param current */ async function submitNote() { let customTime = 1000 //自定义时间 await delayExec(() => { $($(".am-tabs-nav>li a")[2]).click() }) return new Promise(async (resolve, reject) => { if (isFinshed(".np-question-remove.noteDel")) { resolve() return } //随机从词库填写评论 $(".noteContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)]) //提交 await delayExec(async () => { $("#btnNote").click(); await delayExec(async () => { $(".sgBtn.ok").click(); console.log("笔记成功\n"); resolve() }); },customTime); }) } /** * 报错 */ async function submitReport() { let customTime = 1000 //自定义时间 await delayExec(() => { $($(".am-tabs-nav>li a")[3]).click() }) return new Promise(async (resolve, reject) => { if (isFinshed(".np-question-remove.cellErrorDel")) { resolve() return } //随机从词库填写评论 $(".cellErrorContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)]) //提交 await delayExec(async () => { $("#btnCellError").click(); await delayExec(async () => { $(".sgBtn.ok").click(); console.log("报错成功\n"); resolve() }); },customTime); }) } /** * 判断当前页是否已经完成 * @param {string} currentFlag */ function isFinshed(currentFlag) { //防止对话框遮盖 if ($('.popBox').length !== 0) { $($('.popBox a')[1]).click() } //在当前评论页已发现自己的评论,取消评论 if ($(currentFlag).length !== 0) { console.log("已评论过了"); return true } return false } /* * 解除文本限制 */ function uncageCopyLimit() { let arr = ["oncontextmenu", "ondragstart", "onselectstart", "onselect", "oncopy", "onbeforecopy"] for (let i of arr) $(".hasNoLeft").attr(i, "return true") console.log("已成功复制解除限制,📣如果您有软件定制(管理系统,APP,小程序等),毕设困扰,又或者课程设计困扰等欢迎联系,价格从优,源码调试成功再付款💰,实力保证,包远程,包讲解 QQ:2622321887") } /** * 作业处理 */ function homeworkHandler() { uncageCopyLimit() bindBtnToQuestion() } // 重新渲染 let reRender = false /** * 将查询按钮按ID调用插入到题目区未位 */ function bindBtnToQuestion() { // $(``).appendTo(".e-q-quest") // $($(".e-a-g")[2]).prev(".e-q-q") $(".e-q-quest").each(async (i, e) => { $(``).appendTo($(e)) }) //去除填空按钮,提高答案匹配 $('.fillbox').detach() //绕过网站全局事件注册 $(".qBtn").on("click", (event) => { reRender = true searchAnswer(event.srcElement.attributes["x"].value) }) } const server = "http://127.0.0.1:5000" /** * 接口对接规范(JSON) 快速通道(/q?q=问题) 更多信息(/q2?q=问题) * [ * { * 'question': '问题', * 'answer': '答案', * 'options':'题目选项,可留空', * 'msg': '消息,可留空' * },{ * * } * ] * */ /** * 搜索答案 * @param {*} i */ function searchAnswer(i) { // 往前查找同辈元素 const question = $($(".qBtn")[i]).prevAll(".e-q-q").text().trim(); requestAPI('GET', `${server}/q?q=${question}`, { onSuccess: (xhr) => { const body = JSON.parse(xhr.responseText) showAnswerListDiv(question, body, i) } }) } // 查看更多答案的锁 let nextLock = false /** * 显示搜索框 * @param {*} params */ function showAnswerListDiv(questionTitle, data, id) { if ($("#answerBlock").length == 0) { const baseDiv = `
${questionTitle}
标题 填题目📝 消息
选项
结果
` $(baseDiv).appendTo("body") // 初次初始化后关闭 reRender = false //允许查看更多 nextLock = false } else { if (reRender) { //更新对应数据 $("#answerBlock caption").text(questionTitle) //删除原有的数据 $('#answerBlock tbody tr').detach() // 换题后立即关闭 reRender = false //允许查看更多 nextLock = false } } let tbody = ""; data && data.forEach((item, i) => { if (item != null) { let { question, answer, options, msg } = item const x = rnd(10, 1000000) + i tbody += ` ${question || ""}

${(msg && msg.length > 10) ? "" : msg}

${options || ""} ` } }); /** * 查看更多 */ if (!nextLock) { $("#nextBtn").off("click") $("#nextBtn").on("click", (event) => { if (!nextLock) requestAPI('GET', `${server}/q2?q=${questionTitle}`, { onSuccess: (xhr) => { const body = JSON.parse(xhr.responseText) console.log(body); showAnswerListDiv(questionTitle, body, id) //不再允许重复访问 nextLock = true } }) }) } /** * tbody区 */ $(tbody).appendTo("#answerBlock table tbody") $('#answerBlock p').css({ margin: '0', wordwrap: 'break-word', maxwidth: '50px' }); $('#answerBlock em').css({ color: 'red' }) //绕过网站全局事件注册 $(".aBtn").on("click", (event) => { fillAnswer(event.srcElement.attributes["aId"].value, event.srcElement.attributes["qId"].value) }) } /** * 填题 * @param {*} id 答案 ID */ function fillAnswer(aID, qId) { //todo 后端: 1,2,3 const answer = $(`#${aID}`).val(); const qBody = $($(".qBtn")[qId]).parents(".e-q-body"); const questionType = qBody.data("questiontype"); switch (questionType) { // case 1: $(qBody.find(`.e-a-g li:contains('${answer}')`)).click() break; case 2: break; // < !--3:判断题-- > case 3: //默认第一项为正确 $(qBody.find(".e-a-g li")[answer == "√" ? 0 : 1]).click() break; // case 4: case 5: $(qBody.find(".e-a-g input")[0]).val(answer) break; case 6: $(qBody.find("textarea")[0]).val(answer) break; default: break; } } /** * 对XHR的二次全局封装,方便后期扩展 * @param {*} method * @param {*} url * @param {*} headers * @param {*} data * @param {*} onSuccess */ function requestAPI(method, url, { headers, data, onSuccess }) { GM_xmlhttpRequest({ method: method, url: url, headers: headers, data: data, timeout: setting.请求超时, onload: function (xhr) { switch (xhr.status) { case 200: // let obj = $.parseJSON(xhr.responseText) || {}; onSuccess(xhr) break; default: alert(xhr) console.log(xhr); break; } }, ontimeout: function () { alert("响应超时") } }); } })();