- // ==UserScript==
- // @name 云课堂|职教云|Icve --网课兼考试助手 (绿版v3)
- // @version 3.6.5
- // @description 职教云学习效率提升助手小脚本,中文化高度可定制参数,自动课件,课件一目十行,保险模式,解除Ctrl+C限制,下载课件,自动四项评论,课堂智能跟帖讨论,支持自动答题(作业,测验,考试),搜题填题,软件定制
- // @author tuChanged
- // @run- document-start
- // @grant unsafeWindow
- // @grant GM_xmlhttpRequest
- // @grant GM_registerMenuCommand
- // @match *://*.zjy2.icve.com.cn/*
- // @match *://*zjy2.icve.com.cn/*
- // @exclude *://*zjy2.icve.com.cn/study/homework/docHomeworkPreview.html*
- // @license MIT
- // @namespace https://greasyfork.org/users/449085
- // @connect 可添加 API 地址
- // @supportURL https://github.com/tuchg
- // @require https://greasyfork.org/scripts/404781.js
- // @contributionURL https://greasyfork.org/users/449085
- // ==/UserScript==
- /*jshint esversion:6 */
- 'use strict'
- const setting = {
- /**
- * 根据下方根据提示修改脚本配置
- */
- /*
- * 📣如果您有软件定制(APP,小程序,管理系统等),毕设困扰,又或者课程设计困扰等欢迎联系,
- * 价格从优,源码调试成功,线上稳定运行再付款💰,
- * 支持第三方托管交易
- * 实力保证,包远程,包讲解 QQ:2622321887
- */
-
- // true 为打开,false 为关闭
- //正确率不高,题目格式不适配,不推荐打开
- 自动答题: false,
- //针对某些 nt 老师的点点点,快速完成课堂讨论
- 智能跟帖讨论: true,
- 激活仅评论: false,//与学神模式冲突,需二选一
- // 随机评论,自行扩充格式如 "你好", (英文符号)
- 随机评论词库: ["..", "🇨🇳", "💬"],
- //开启所有选项卡的评论,最高优先等级,打开该项会覆盖下面的细分设置,
- 激活所有选项卡的评论: false,
- 激活评论选项卡: false,
- 激活问答选项卡: false,
- 激活笔记选项卡: false,
- 激活报错选项卡: false,
- 显示评论数: 1000,
- // 刺激!风险未知,暂知时长不良 打开需关闭仅评论
- 学神模式: false,
- 保险模式: false,//如果课件始终不跳下一个,请勿打开该项
- //解除课件下载
- 打开课件下载: true,
- // 部分课件存在无检测机制问题,会尝试自动关闭保险模式
- 自动关闭保险模式: true,
- /*影响速度关键选项,延时非最优解,过慢请自行谨慎调整*/
- 最高延迟响应时间: 4000,//毫秒
- 最低延迟响应时间: 3000,//毫秒
- 组件等待时间: 1500,//毫秒 组件包括视频播放器,JQuery,答题等,视网络,设备性能而定,启动失败则调整
- 考试填题时间: 30000,//30秒 1 秒=1000 毫秒
- //0-高清 1-清晰 2-流畅 3-原画
- //感谢tonylu00提供最新实测参数 --0-原画 1-高清 2-清晰 3-流畅
- 视频清晰度: 3,
- //2倍速,允许开倍速则有效,请放心使用,失败是正常现象
- 视频播放倍速: 2,
- //是否保持静音
- 是否保持静音: true,
- //当前版本可不用理会该项, 题库 IP地址 ,可在553行查看对接接口要求
- 自定义题库服务器: "🔐"// 协议://IP
- }, top = unsafeWindow,
- url = location.pathname
- //产生区间随机数
- const rnd = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
- const classId = getQueryValue("openClassId")
- const cellID = getQueryValue("cellId")
- const stuId = localStorage.getItem("userId")
- // 课件完成相关判定数据
- let pageCount, mediaLong, cellType, startTime, lastArchiveCount
- //课件是否已完成
- let isFinshed = false;
- // 评论标志位
- const isUnFinishedTabs = [setting.激活所有选项卡的评论 || setting.激活评论选项卡, setting.激活所有选项卡的评论 || setting.激活笔记选项卡, setting.激活所有选项卡的评论 || setting.激活问答选项卡, setting.激活所有选项卡的评论 || setting.激活报错选项卡]
-
- //定时任务栈
- let taskStack = 0
- /**
- * 使用异步包装
- * 随机延迟执行方法
- * @param {需委托执行的函数} func
- */
- async function delayExec(func, fixedDelay = null) {
- // taskStack.push(func)
- taskStack++
- const newTask = new Promise((resolve, reject) => {
- const newTime = rnd(fixedDelay || (setting.最低延迟响应时间) * (taskStack / 3), fixedDelay || (setting.最高延迟响应时间) * (taskStack / 2.5));
- setTimeout(() => {
- resolve(func())
- taskStack--
- console.log(`完成延时${newTime}ms的任务,待执行任务总计:${taskStack}`);
- }, newTime);
- console.log(`新增任务,等待时间${newTime}ms,待执行任务总计:${taskStack}`);
- });
- return newTask
- }
- function autoCloseDialog() {
- const $dialog = $(".ui-dialog");
- //关闭限制弹窗
- if ($dialog.length > 0)
- $dialog.find("#studyNow").click()
-
- if ($(".xcConfirm")) {
- $(".xcConfirm").css({ "display": "none" })
- }
- }
-
- GM_registerMenuCommand("🔄重新获取未完成小节", function () {
- sessionStorage.clear()
- goPage("p")
- });
-
- GM_registerMenuCommand("问题反馈", function () {
- top.open("https://github.com/W-ChihC/SimpleIcveMoocHelper/issues")
- });
- GM_registerMenuCommand("🌹为脚本维护工作助力", function () {
- top.open("https://greasyfork.org/zh-CN/users/449085")
- });
- GM_registerMenuCommand("📝检查脚本配置", function () {
- alert(`
- 当前版本:绿版 v3.6.4✅
- 题库:${setting.自定义题库服务器 ? setting.自定义题库服务器 : "❌无"}
- 学神模式: ${setting.学神模式 ? "✅打开" : "❌关闭"}
- 保险模式: ${setting.保险模式 ? "✅打开" : "❌关闭"}
- 仅评论模式: ${setting.激活仅评论 ? "✅打开" : "❌关闭"}
- 自动填题:${setting.自动答题 ? "✅打开" : "❌关闭"}
- 智能跟帖讨论:${setting.智能跟帖讨论 ? "✅打开" : "❌关闭"}
- 当前组件响应时间:${setting.组件等待时间 % (1000 * 60) / 1000} 秒
- 考试填题时间:${setting.考试填题时间 % (1000 * 60) / 1000} 秒
- 当前评论库: [ ${setting.随机评论词库} ]
- 已激活的评论选项卡:${((setting.激活所有选项卡的评论 || setting.激活评论选项卡) ? "评论;" : "") + ((setting.激活所有选项卡的评论 || setting.激活问答选项卡) ? "问答;" : "") + ((setting.激活所有选项卡的评论 || setting.激活笔记选项卡) ? "笔记;" : "") + ((setting.激活所有选项卡的评论 || setting.激活报错选项卡) ? "报错" : "")}\n
-
- 📝修改配置请找到油猴插件的管理面板
-
- 插件仅供提升学习效率减少,繁杂工作,解放双手之用,未利用任何漏洞达成目的,均为网页自动化测试技术,切勿滥用
-
- 脚本完全免费开源,遵循 MIT 协议,严禁倒卖,如果您是购买使用请举报售卖者
- `)
- });
-
-
-
- // 一页页面加载后的工作
- delayExec(() => {
- autoCloseDialog()
- //匹配不需要监听网络的URL
- switch (url) {
- //作业区
- case "/study/homework/preview.html":
- case "/study/homework/do.html":
- case "/study/faceTeachInfo/testPreview.html":
- homeworkHandler()
- break;
- //考试
- case "/study/onlineExam/preview.html":
- case "/study/onlineExam/do.html":
- alert("请勿过快提交,同时也尽量调整脚本考试填题时间设置\n答题过快会被检测然后翻车哦")
- setting.组件等待时间 = setting.考试填题时间
- homeworkHandler()
- break
- //课堂
- case "/study/faceTeachInfo/faceTeachActivityListInfo.html":
- $(".np-hw-li.progressing .np-hw-score:contains('未参加')").each((i, e) => {
- const x = $(e).parent().parent().find(".am-inline-block:not(.zuoda)")
- if (x.length > 0) {
- x.attr("target", "_blank")
- x[0].click()
- }
- })
- break
- case "/study/faceTeachInfo/newDiscussStuInfo.html":
- if (!setting.智能跟帖讨论 || $(`.commentli[data-stuid='${localStorage.getItem("userId")}']`).length > 0) {
- return
- }
- const t = findOneVaildDiscuss()
- if (t) {
- delayExec(() => {
- $(".faceContent").val(t)
- $(".replyOk")[0].click()
- })
- } else {
- alert("暂无人参与")
- }
- break
- }
-
- $(document).ajaxSend((e, xhr, options) => {
- if (!$.parseParams)
- $.extend({
- parseParams: function (e) {
- for (var o, i = /([^&=]+)=?([^&]*)/g, n = /\+/g, c = function (e) {
- return decodeURIComponent(e.replace(n, " "))
- }, r = {}; o = i.exec(e);) {
- var f = c(o[1])
- , a = c(o[2]);
- "[]" === f.substring(f.length - 2) ? (f = f.substring(0, f.length - 2),
- (r[f] || (r[f] = [])).push(a)) : r[f] = a
- }
- return r
- },
- htmlencode: function (o) {
- return e("<div />").text(o).html()
- },
- htmldecode: function (o) {
- return e("<div />").html(o).text()
- }
- })
- if (setting.学神模式 && !setting.激活仅评论)
- if (options.url.indexOf("stuProcessCellLog") > -1) {
-
- const params = $.parseParams && $.parseParams(options.data);
- if (params)
- options.data = $.param({
- ...params,
- studyNewlyTime: mediaLong,
- picNum: pageCount,
- studyNewlyPicNum: pageCount
- })
- }
- // 修改评论页数
- if (options.url.indexOf("getCellCommentData") > -1) {
- const params = $.parseParams && $.parseParams(options.data);
- if (params)
- options.data = $.param({
- ...params,
- pageSize: setting.显示评论数
- })
- }
- });
-
- }, setting.组件等待时间);
- function findOneVaildDiscuss() {
- let str = null
- $(".np-question-detail").each((i, e) => {
- if (i > 0) {
- const text = e.innerText
- if (text.trim().length > 10) {
- str = text
- return false
- }
- }
- })
- return str
- }
-
-
- let lastNum = 10;
- let currentCellData = {};
- let isPassMonit = false;
-
-
-
- // 全局请求拦截器
- (function (open, send) {
-
- // 拦截发出的请求
- XMLHttpRequest.prototype.send = function (data) {
-
- // 学生课件状态检查
- if (data && data.indexOf("studyNewlyTime") >= 0) {
- // 关闭错误弹窗
- $(".sgBtn.ok").click();
- autoCloseDialog()
-
- try {
- isPassMonit = true
- autoCloseDialog()
- if (!setting.激活仅评论) {
- let readedNum = parseInt(getQueryValue("studyNewlyPicNum", "?" + data));
- // 四舍五入留两位与服务器计时同步
- const readedTime = Math.round(parseFloat(getQueryValue("studyNewlyTime", "?" + data)) * 100) / 100;
- const picNum = parseInt(getQueryValue("picNum", "?" + data))
- // 非媒体课件下启动
- if ((!readedTime || setting.学神模式) && !startTime)
- startTime = $.now()
- // 纠正空课件监控问题
- if (pageCount === 1)
- readedNum = 1
- // 损坏课件的问题
- if (picNum === 1 && readedNum === 0)
- pageCount = 1
- console.log(`文档同步进度:${readedNum}/${pageCount}`, `视频同步进度:${readedTime}/${mediaLong}`);
- // 某些课件未被检测
- lastNum = readedNum && readedNum
- if (lastNum === 0 && setting.保险模式) {
- console.log("保险模式启动失败,已尝试关闭");
- if (setting.自动关闭保险模式) {
- setting.保险模式 = false
- requestMatcher("viewDirectory", currentCellData)
- }
- return
- }
-
- // 判断当前课件是否已结束
- if ((readedNum && pageCount && (readedNum >= pageCount)) || setting.学神模式) {
- isFinshed = true
- const endTime = $.now()
- // 应对检测需停留 10 秒
- if (startTime && (endTime - startTime >= 10000)) {
- // 评论任务均已完成则跳转
- if (isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- }
- console.log(`未满足职教云课件完成检测 10 秒要求,继续等待中,已等待:${endTime - startTime}ms`);
- } else {
- if (setting.保险模式)
- pageCount && console.log(`文档类🔐模式:${readedNum}/${pageCount}`);
- nextDOCPPT()
- }
- } else {
- // 评论任务均已完成则跳转
- if (isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- }
- } catch (error) {
- console.log(error);
- }
- }
- send.apply(this, arguments);
- };
-
- // 拦截数据响应
- XMLHttpRequest.prototype.open = function () {
- this.addEventListener("readystatechange", () => {
- if (this.readyState >= 4)
- requestMatcher(this.responseURL, JSON.parse(this.responseText), this)
- }, false);
- open.apply(this, arguments);
- };
- })(XMLHttpRequest.prototype.open, XMLHttpRequest.prototype.send);
-
- /**
- * 请求匹配器,任务调度中心
- */
- async function requestMatcher(url, data, that) {
- autoCloseDialog()
- // debugger
- switch (url) {
- // 评论
- case String(url.match(/.*getCellCommentData$/)):
- if (isUnFinishedTabs[0] || isUnFinishedTabs[1] || isUnFinishedTabs[2] || isUnFinishedTabs[3] || setting.激活所有选项卡的评论) {
- const userId = localStorage.getItem("userId");
- const item = data.list && data.list.find(item => item.userId === userId);
- // 评论已完成
- console.log("我的评论: ", item);
- switch (data.type) {
- case 1: {
- if (setting.激活评论选项卡 || setting.激活所有选项卡的评论) {
- if (!item) {
- await submitComment()
- console.log("已完成评论提交");
- }
- isUnFinishedTabs[data.type - 1] = false
- }
- }
- break;
- case 2:
- {
- if (setting.激活笔记选项卡 || setting.激活所有选项卡的评论) {
- if (!item) {
- await submitNote()
- console.log("已完成笔记提交");
- }
- isUnFinishedTabs[data.type - 1] = false
- }
-
- }
- break;
- case 3:
- {
- if (setting.激活问答选项卡 || setting.激活所有选项卡的评论) {
- if (!item) {
- await submitQuestion()
- console.log("已完成问答提交");
- }
- isUnFinishedTabs[data.type - 1] = false
- }
- }
- break;
- case 4:
- {
- if (setting.激活报错选项卡 || setting.激活所有选项卡的评论) {
- if (!item) {
- await submitReport()
- console.log("已完成报错提交");
- }
- isUnFinishedTabs[data.type - 1] = false
- }
- }
- break;
- }
- if (isUnFinishedTabs.indexOf(true) != -1) {
- if (data.type == 4)
- data.type = 2
- await delayExec(() => {
- $($(".am-tabs-nav>li a")[data.type]).click()
- })
- console.log("完成");
- }
-
- // let tab = isUnFinishedTabs.indexOf(true);
- // if (!setting.激活笔记选项卡 && data.type !== 1)
- // tab -= 1
- // if (tab > -1 && tab + 2 !== data.type) {
- // await delayExec(() => {
- // $($(".am-tabs-nav>li a")[tab]).click()
- // })
- // }
-
-
-
- //解决不同机制判断问题
- if ((setting.激活仅评论 || isFinshed) && isUnFinishedTabs.indexOf(true) === -1 && taskStack === 0) {
- nextCell()
- }
- }
- break;
- // 载入课件
- case String(url.match(/.*viewDirectory|loadCellResource$/)):
- {
- if (data.code === -33) {
- nextCell()
- return
- }
-
- autoCloseDialog()
- if (setting.激活仅评论) {
- console.log("仅开启评论已打开");
- // commentHandler()
- return
- }
-
- if (currentCellData && setting.打开课件下载) {
- // 课件下载 todo
- data.isAllowDownLoad = true
- data.isDownLoad = true
- console.log("当前课件下载地址:", data.downLoadUrl);
- // 修改服务器返回数据
- if (!that._responseText) {
- Object.defineProperty(that, 'responseText', {
- get: () => that['_responseText'] === undefined ? that.responseText : that['_responseText'],
- set: (val) => {
- that['_responseText'] = val
- },
- enumerable: true
- });
- }
- //修改响应数据
- that._responseText = JSON.stringify(data)
- }
- // 课件页数
- pageCount = data.pageCount
- // // 课件当前已阅览时间
- // readTime = data.stuStudyNewlyTime
- // 媒体时间长度
- mediaLong = data.audioVideoLong;
- // 课件进度
- const cellPercent = data.cellPercent
- // 课件类型
- cellType = data.categoryName
- // 如果当前课件为遗漏课件则进入下一个课件
- if (cellPercent === 100 && isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- currentCellData = data
- console.log("当前课件: ", data);
- cellHandlerMatcher()
- }
- break;
-
- case String(url.match(/.*faceTeachActivityInfo$/)):
- {
-
-
- }
- break
- // 课程章节目录
- case String(url.match(/.*getProcessList$/)):
- {
- const localS = sessionStorage.getItem(classId);
- //未在本地找到遗留数据则重新获取
- if (!localS || localS === "[]" || localS === "null") {
-
- if (!confirm("正在获取未完成小节数据,为避免检测,请耐心等待🖥\n✅确定以继续,确认后勿关闭本页\n直到再次弹窗,否则脚本将结束工作\n ‼️插件仅供提升学习效率减少,繁杂工作,解放双手之用,未利用任何漏洞达成目的,均为网页自动化技术,请健康使用勿要滥用\n"))
- return
- const parentNode = data && data.progress;
- //过滤已经学习完的课件
- let dirs = parentNode && parentNode.moduleList.filter(item => item.percent !== 100)
- if (setting.激活仅评论)
- dirs = parentNode.moduleList
- //请求课程所有数据
- const orginalData = (await sendIcveRequest(urls2.courseView_getCourseDetailList)).courseProcessInfo
- //过滤掉已完成的章节
- const list = orginalData && orginalData.filter(item => dirs.find(i => i.id === item.id))
- const cid = getQueryValue("courseOpenId")
- const oid = getQueryValue("openClassId")
- //最终处理数据
- const finalData = []
- //提取未完成的课件
- for (const item of list) {
- for (const i of item.topics) {
- // 最终需要处理的数据
- const cellList = (await sendIcveRequest(urls.process_getCellByTopicId, { courseOpenId: cid, openClassId: oid, topicId: i.id })).cellList
- cellList && cellList.forEach(item => {
- const childList = item.childNodeList;
- if (childList && childList.length !== 0) {
- const childVaildList = childList.filter(i => {
- // if (i.cellType !== 4 && i.fromType !== 4) {
- if (i.cellType !== 4) {
- if (setting.激活仅评论)
- return true
- if (i.stuCellFourPercent !== 100)
- return true
- }
- return false
- });
- console.log(childVaildList);
- finalData.push(...childVaildList)
- // } else if (item.cellType !== 4 && item.fromType !== 4) {
- } else if (item.cellType !== 4) {
- if (setting.激活仅评论)
- finalData.push(item)
- else if (item.stuCellPercent !== 100)
- finalData.push(item)
- console.log(item);
- }
- })
- }
- }
- console.log(`已成功缓存${finalData.length}条未完成小节信息`);
- sessionStorage.setItem(classId, JSON.stringify(finalData.reverse()))
- }
- const data_ = JSON.parse(sessionStorage.getItem(classId))
- console.log(data_);
- if (confirm(`✅已初始化完成,发现${data_.length}个课件未完成,是否立即启动不知疲倦学习🙇🏼♂️📚模式`))
- goPage(null, data_[data_.length - 1])
- }
- break;
- default:
- if (data && data.msg && data.msg.indexOf("操作成功") < 0) {
- console.log("无任务可分配", data);
- }
- break;
- }
- }
- /**
- * 查找下一个课件,并在本地缓存更新相应信息
- */
- function nextCell() {
- // debugger
- const data = JSON.parse(sessionStorage.getItem(classId));
- if (!data) {
- if (confirm("🆇未从缓存中检测到课程数据,是否进入正常运行流程\n如果您是购买使用,请举报售卖方,本脚本完全免费开源使用")) {
- goPage("p")
- return
- }
- }
- const surplusData = data && data.filter(item => item.Id !== cellID);
- sessionStorage.setItem(classId, JSON.stringify(surplusData))
-
- if (surplusData && surplusData.length === 0) {
- alert("课程已完成\n脚本完全免费开源,遵循 MIT 协议,严禁倒卖,如果您是购买使用请举报售卖者")
- return
- }
-
- console.log("当前课件任务已完成----");
-
- delayExec(() => {
- goPage(null, surplusData.pop())
- })
- }
-
-
- /**
- * 跳转到某页面
- */
- function goPage(url, data = undefined) {
- let newPage;
- if (!url) {
- newPage = `${location.origin}/common/directory/directory.html?courseOpenId=${data.courseOpenId}&openClassId=${classId}&cellId=${data.Id}&flag=${data.flag || "s"}&moduleId=${data.parentId}`;
- console.log("下一个课件: ", newPage);
- } else {
- newPage = `${location.origin}/study/process/process.html?courseOpenId=${getQueryValue("courseOpenId")}&openClassId=${getQueryValue("openClassId")}`
- }
- top.location.href = newPage
- }
-
- /**
- * 对网站发送请求集中处理,解析结果,处理成功与否逻辑
- */
- function sendIcveRequest(url, data = {}) {
- return new Promise((resolve, reject) => {
- delayExec(() => {
- _.ajax(url, data, (r) => {
- if (r.code == 1) {
- resolve(r)
- } else {
- console.log("请求出问题了🔐", r)
- reject(r)
- }
- })
- })
- })
- }
-
-
- /**
- * 课件匹配处理调度
- */
- function cellHandlerMatcher() {
-
- if (!setting.激活仅评论)
- switch (cellType) {
- case "图片":
- case "文档":
- case "excel文档":
- case "office文档":
- case "pdf文档":
- case "其它":
- case "ppt文档":
- if (!setting.保险模式)
- delayExec(() => {
- docHandler()
- })
- break;
- case "ppt":
- if (!setting.保险模式)
- delayExec(async () => {
- await pptHandler()
- })
- break;
- case "swf":
- swfHandler()
- break;
- case "视频":
- case "音频":
- delayExec(() => {
- mediaHandler()
- }, setting.组件等待时间)
- break;
- case "图文":
- case "压缩包":
- emptyHandler()
- break;
- default:
- console.log(`课件 : ${cellType} 未提供兼容, ${setting.未做兼容课件打开评论 ? '已开启兼容评论,仅运行评论' : '已跳过处理'},请在github issue (https://github.com/W-ChihC/SimpleIcveMoocHelper) 反馈该日志,与作者取得联系`);
- break
- }
- }
-
-
-
-
-
- /**
- * 获取url查询字段
- * @param {查询字段} query
- * @param 默认为地址栏
- */
- function getQueryValue(query, url = window.location.search) {
- 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];
- }
-
-
- /**
- * 仅仅评论的处理器
- */
- async function emptyHandler() {
- console.log("啥也没干,请联系作者", cellType);
- }
-
- async function swfHandler() {
- //当不支持flash时执行
- if ($('.popBox').length !== 0) {
- $($('.popBox a')[1]).click()
- }
- }
-
- /**
- * 视频/音频类处理
- */
- function mediaHandler() {
- try {
- let player = top.jwplayer($(".jwplayer").attr("id"));
- let state = null;
- state = player.getState();
- //视频暂停状态
- if (state == "paused" || state === 'idle') {
- console.log("媒体已暂停,恢复播放");
- player.play()
- }
- if (player.getDuration() === 0) {
- if (state === "buffering") {
- const timer = setInterval(() => {
- if (player.getPosition() === 0)
- delayExec(() => {
- if (player.getPosition() === 0)
- player.play();
- }, setting.组件等待时间);
- else
- clearInterval(timer)
- }, setting.组件等待时间);
-
- } else {
- if (setting.学神模式 || isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- isFinshed = true
- }
- }
- //播放原已完成
- if (player.getState() == "complete") {
- console.log("媒体播放已完成");
- // 评论任务均已完成则跳转
- if (isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- isFinshed = true
- return
- }
- //播放回调
- player.on("playlistComplete", () => {
- console.log("媒体播放完成");
- // 评论任务均已完成则跳转
- if (isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- isFinshed = true
- })
- //配置
- player.setMute(setting.是否保持静音)//静音
- player.setCurrentQuality(setting.视频清晰度)
- try {
- player.setPlaybackRate(setting.视频播放倍速)
- } catch (error) {
- console.log('倍速开启失败...正常现象.');
- }
- } catch (error) {
- console.log("课件为空或无法解析", error);
- // 评论任务均已完成则跳转
- if (isUnFinishedTabs.indexOf(true) === -1) {
- nextCell()
- return
- }
- isFinshed = true
- }
-
- }
- /**
- * 文档处理
- */
- async function docHandler() {
-
- if ($(".MPreview-pageNext").length !== 0) {
- //根据按钮状态判断是否还有下一页
- while ($(".MPreview-pageNext").hasClass('current')) {
- console.log(`文档翻页,总页数:${pageCount}`);
- //ppt翻页 异步方式
- await delayExec(() => {
- $(".MPreview-pageNext").click()
- })
- }
- } else {
- await pptHandler()
- }
- }
-
-
- /**
- * PPT类别处理
- */
- async function pptHandler() {
- // 异步处理
- return new Promise(async (resolve, reject) => {
- for (let i = 1; i <= pageCount * 2; i++) {
- //点击下一页
- await delayExec(() => {
- nextDOCPPT()
- // console.log(`ppt第${i}页,总页数:${pageCount}`);
- //达到次数解除阻塞
- if (isFinshed || i === pageCount && mediaLong === 0)
- resolve()
- })
- }
- // if (pageCount === 1) {
- // for (let i = 0; i < 5; i++)
- // nextDOCPPT()
- // delayExec(() => {
- // nextCell()
- // resolve()
- // }, 15000)
- // }
- })
- }
- /**
- * 下一页PPT 或文档
- */
- function nextDOCPPT() {
- const pptNext = $(".stage-next"), docNext = $(".MPreview-pageNext"), sNext = $(".stage-next-btn");
- pptNext && pptNext.click()
- docNext && docNext.click()
- sNext && sNext.click()
- }
- /**
- * 对XHR的二次全局封装,方便后期扩展
- * @param {*} method
- * @param {*} url
- * @param {*} headers
- * @param {*} data
- * @param {*} onSuccess
- */
- function requestAPI(method, url, { headers = {}, data, onSuccess } = {}) {
- return new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- method: method,
- url: url,
- headers: headers,
- data: data,
- //关闭 cookie
- anonymous: true,
- timeout: 2000,
- onload: function (xhr) {
- switch (xhr.status) {
- case 200:
- case 404:
- // let obj = $.parseJSON(xhr.responseText) || {};
- if (onSuccess)
- onSuccess(xhr)
- else
- resolve(xhr)
- break;
- default:
- resolve(xhr)
- break;
- }
- },
- onabort: function (params) {
- reject(params)
-
- },
- onerror: function (params) {
- // debugger
- reject(params)
- },
- ontimeout: function (params) {
- reject(params)
- }
- });
- })
-
- }
-
-
- /**
- * 评论
- */
- async function submitComment() {
- // debugger
- return new Promise(async (resolve, reject) => {
-
- //评5星
- $("#star #starImg4").click();
- //随机从词库填写评论
- $(".commentContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)])
- //提交
- await delayExec(async () => {
- $("#btnComment").click();
- resolve()
- });
- })
- }
-
- /**
- * 问答
- */
- async function submitQuestion() {
- // debugger
- return new Promise(async (resolve, reject) => {
- //随机从词库填写评论
- $(".questionContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)])
- //提交
- await delayExec(async () => {
- $("#btnQuestion").click();
- resolve()
- }, 60000);
- })
- }
- const list = []
- /**
- * 笔记
- */
- async function submitNote() {
- // debugger
- return new Promise(async (resolve, reject) => {
- //随机从词库填写评论
- $(".noteContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)])
- //提交
- await delayExec(async () => {
- $("#btnNote").click();
- resolve()
- }, 60000);
- })
- }
- /**
- * 报错
- */
- async function submitReport() {
- return new Promise(async (resolve, reject) => {
- //随机从词库填写评论
- $(".cellErrorContent").text(setting.随机评论词库[rnd(0, setting.随机评论词库.length - 1)])
- //提交
- await delayExec(async () => {
- $("#btnCellError").click();
- resolve()
- }, 60000);
- })
- }
-
-
- /*
- * 解除文本限制
- */
- function uncageCopyLimit() {
- let arr = ["oncontextmenu", "ondragstart", "onselectstart", "onselect", "oncopy", "onbeforecopy"]
- for (let i of arr)
- $(".hasNoLeft").attr(i, "return true")
- console.log("已成功解除复制限制,📣如果您有软件定制(管理系统,APP,小程序等任何形式私活)等欢迎联系\n价格从优,源码调试成功再付款💰\n实力保证,包远程,包讲解 QQ:2622321887")
- }
-
-
- /**
- * 作业处理
- */
- async function homeworkHandler() {
-
- uncageCopyLimit()
- if (!setting.自定义题库服务器) {
- alert("未填写题库📝,无法正常使用答题,仅提供解除网站限制")
- }
- bindBtnToQuestion()
- if (setting.自动答题)
- autoFill()
- }
-
- let isAutoFilling = false
- /**
- * 单选 多选 判断 填空 问答
- */
- async function autoFill() {
- const q = $(".qBtn");
- for (let i = 0; i < q.length; i++) {
- const e = q[i];
- await delayExec(() => {
- isAutoFilling = true
- e.click()
- }, setting.组件等待时间)
- }
- delayExec(() => {
- if (setting.组件等待时间 === setting.考试填题时间) {
- alert("如果你不想被老师打零分,就别智障的过快提交")
- }
- $("#submitHomeWork").click()
- isAutoFilling = false
- }, setting.组件等待时间)
- }
-
-
- // 重新渲染答题区的标志位
- let reRender = false
-
- /**
- * 将查询按钮按ID调用插入到题目区未位
- */
- function bindBtnToQuestion() {
- // $(`<button class="qBtn" type="button">🔍</button>`).appendTo(".e-q-quest")
- // $($(".e-a-g")[2]).prev(".e-q-q")
- $(".e-q-quest").each(async (i, e) => {
- $(`<button class="qBtn" x="${i}" type="button">🔍</button>`).appendTo($(e))
- })
- //去除填空按钮,提高答案匹配
- $('.fillbox').detach()
-
- //绕过网站全局事件注册
- $(".qBtn").on("click", (event) => {
- reRender = true
- searchAnswer(event.srcElement.attributes["x"].value)
- })
- }
-
- const server = setting.自定义题库服务器 || "http://127.0.0.1:5000"
-
- /**
- * //接口对接规范(JSON) 快速通道(/q?q=问题) 更多信息(/q2?q=问题)
- * [
- * {
- * 'question': '问题,可留空',
- * 'answer': '答案', //判断题 1 为正确,其余为错误
- * 'options':'题目选项,可留空',
- * 'msg': '消息,可留空'
- * },{
- *
- * }
- * ]
- *
- */
-
-
- /**
- * 填题
- * @param {*} id 答案 ID
- */
- function fillAnswer(aID, qId) {
- // 多选 及自动答题模块
- //todo 后端: 1,2,3
- let answer = $(`#${aID}`).text();
- const qBody = $($(".qBtn")[qId]).parents(".e-q-body");
- const questionType = qBody.data("questiontype");
- let inputBlock;
- switch (questionType) {
- // <!-- 1:单选 2:多选 -->
- case 1:
- case 2:
- answer.split(",").forEach(e => {
- inputBlock = $(qBody.find(`.e-a-g li:contains("${e}")`));
- inputBlock.click()
- inputBlock.focus()
- })
- break;
- // < !--3:判断题-- >
- case 3:
- answer = answer.trim()
- inputBlock = $(qBody.find(".e-a-g li")[(answer == "1" || answer == "正确" || answer == "对" || answer == "√") ? 0 : 1]);
- //默认第一项为正确
- inputBlock.click()
- inputBlock.focus()
- break;
- // <!-- 4:填空题(主观) 5:填空题(客观) 6 问答-->
- case 4:
- case 5:
- answer.split(",").forEach((e, i) => {
- inputBlock = $(qBody.find(".e-a-g input")[i])
- inputBlock.val(e)
- inputBlock.blur()
- })
- break;
- case 6:
- inputBlock = $(qBody.find("textarea")[0])
- inputBlock.val(answer)
- inputBlock.blur()
- break;
- default:
- break;
- }
- }
- // 查看更多答案的锁
- let nextLock = false
- /**
- * 显示搜索框
- * @param {*} params
- */
- async function showAnswerListDiv(questionTitle, data, id) {
- const title = setting.组件等待时间 === setting.考试填题时间 ? `脚本提倡诚信考试,真材实料应考,<b>答案仅供参考</b>,不可全信<br>为保证考试公平,将会在一定范围内返回随机<em>错误答案</em><br>针对考试特殊处理,请耐心等待,出现提示前勿要乱动,否则<em>按舞弊处理</em>其后果自负<br> ${setting.自动答题 ? `下一道题将在<b>${setting.考试填题时间 % (1000 * 60) / 1000}</b>秒后继续` : ""}` : questionTitle.substr(0, 30)
- if ($("#answerBlock").length == 0) {
- const baseDiv = ` <div id="answerBlock" style="background: #cccccc8c;max-width:50%; float: right; margin-right: 230px;overflow:auto; position: fixed; top: 0; right: 0; z-index: 9999;">
- <table border="1" cellspacing="0" align="center" style="font-size: 14px;">
- <caption style="min-width:200px;">${title}</caption>
- <thead>
- <tr>
- <th>题目</th>
- <th>📝</th>
- <th>消息</th>
- </tr>
- <tr>
- <th colspan="2">选项</th>
- </tr>
- <tr>
- <th colspan="2">结果</th>
- </tr>
- </thead>
- <tbody align="left">
- </tbody>
- </table>
- <center><a type="button" id="nextBtn" >查找更多 (慢)</a></center>
-
- </div>`
- $(baseDiv).appendTo("body")
- // 初次初始化后关闭
- reRender = false
- //允许查看更多
- nextLock = false
- } else {
- if (reRender) {
- //更新对应数据
- $("#answerBlock caption").html(title)
- //删除原有的数据
- $('#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 += `
- <tr>
- <td>${question || ""}</td>
- <td><a class="aBtn" aId="${x}" qId=${id} type="button" style="margin:2px">填入</a></td>
- <td>
- <p>${msg || ""}</p>
- </td>
- </tr>
- <tr style="height:50px">
- <td colspan="3">${options || ""}</td>
- </tr>
- <tr style="height:50px">
- <td colspan="3"><b id=${x} ><a class="aBtn" aId="${x}" qId=${id}> ${answer || ""}</a></b></td>
- </tr>
- `
- }
- });
- /**
- * 查看更多
- */
- if (!nextLock) {
- $("#nextBtn").off("click")
- $("#nextBtn").on("click", async () => {
- if (!nextLock) {
- /**
- * 慢速接口
- * @param questionTitle 问题
- * @param id 对应 div id (用于定位答题)
- */
- slowSearch(questionTitle, 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)
- })
- // if (setting.自动答题)
- /**填写第一项到答案 */
- try {
-
- $(".aBtn")[0].click()
-
- } catch (e) {
-
- }
- }
- /**
- * 搜索答案
- * @param {*} i
- */
- async function searchAnswer(i) {
- // 往前查找同辈元素
- const question = $($(".qBtn")[i]).prevAll(".e-q-q").text().trim();
-
- showAnswerListDiv("搜索中...", [], i)
- /**
- * 快速接口
- * @param questionTitle 问题
- * @param id 对应 div id(用于定位答题)
- */
- try {
- await quickSearch(question, i)
- } catch (e) {
- reRender = true
- showAnswerListDiv("搜索失败...", [{ options: "<center><b>作者删库跑路了</b></center>" }], i)
- }
- }