// ==UserScript== // @name 青书学堂网课自动学习助手 // @namespace https://degree.qingshuxuetang.com // @version 1.0.4 // @description 支持视频自动播放、文档自动跳过、课程自动跳转下一节,并提供课程列表进度面板显示学习时长与完成状态 // @author eivy // @match *https://degree.qingshuxuetang.com/xayd/Student/Course/CourseShow* // @match *https://degree.qingshuxuetang.com/xayd/Student/Course/CourseStudy* // @grant GM_addStyle // @grant GM.setValue // @grant GM.getValue // @grant GM_addElement // @license MIT // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/568720/%E9%9D%92%E4%B9%A6%E5%AD%A6%E5%A0%82%E7%BD%91%E8%AF%BE%E8%87%AA%E5%8A%A8%E5%AD%A6%E4%B9%A0%E5%8A%A9%E6%89%8B.user.js // @updateURL https://update.greasyfork.icu/scripts/568720/%E9%9D%92%E4%B9%A6%E5%AD%A6%E5%A0%82%E7%BD%91%E8%AF%BE%E8%87%AA%E5%8A%A8%E5%AD%A6%E4%B9%A0%E5%8A%A9%E6%89%8B.meta.js // ==/UserScript== //整个函数起始位 (function () { "use strict"; // 默认播放速度 //青书学堂是根据课程播放时长计算完成度,对视频播放速度有要求,所以这里设置为1.提高视频播放速度对课程进度没有影响 const speed = 1; const isListPage = window.location.href.includes( "xayd/Student/Course/CourseStudy", ); const isDetailPage = window.location.href.includes( "xayd/Student/Course/CourseShow", ); console.log("脚本加载成功....."); //当前 页面 为列表页时执行该部分内容 if (isListPage) { let url1Promise = new Promise((resolve) => { window.resolveUrl1 = resolve; // 暴露resolve方法,供请求完成时调用 }); let url2Promise = new Promise((resolve) => { window.resolveUrl2 = resolve; // 暴露resolve方法 }); console.log("油猴:开始重写XHR"); const originalXHR = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (method, url, async) { // 匹配目标XHR请求 if (url.includes("GetCoursewareTree")) { console.log("油猴:匹配到目标XHR →", url); // 监听请求加载完成 this.addEventListener( "load", function () { if (this.status >= 200 && this.status < 300) { const data = JSON.parse(this.responseText); window.resolveUrl1(data); // 完成第一个Promise } else { window.resolveUrl1({}); // 失败也resolve,避免Promise.all卡死 } }, 200, ); } // 匹配目标XHR请求 if (url.includes("GetStudyRecordAndScore")) { console.log("油猴:匹配到目标XHR →", url); // 监听请求加载完成 this.addEventListener( "load", function () { if (this.status >= 200 && this.status < 300) { const data = JSON.parse(this.responseText); window.resolveUrl2(data); // 完成第一个Promise } else { window.resolveUrl2({}); // 失败也resolve,避免Promise.all卡死 } }, 100, ); } // 执行原生open方法 originalXHR.call(this, method, url, async); }; Promise.all([url1Promise, url2Promise]).then( ([class_list, class_time_record_list]) => { initListPage(class_list, class_time_record_list); }, ); setTimeout(() => { // 若超时,强制resolve空数据 window.resolveUrl1(null); window.resolveUrl2(null); }, 100000); } function initDelatilsPage() { if (!isDetailPage) { return; } createPEelement(); const class_id = getUrlParameters("courseId"); const currentClassNumber = getUrlParameters("nodeId"); const classItemsCache = GM.getValue("classid_" + class_id); if (!classItemsCache) { return; } classItemsCache .then((data) => { const currentIndex = data.findIndex( (item) => item.id === currentClassNumber, ); if (currentIndex === -1 || currentIndex + 1 >= classItemsCache.length) { alert("没有下一节课程了"); return; } //下一节课程信息 const nextInfo = data[currentIndex + 1]; detailInit(nextInfo); }) .catch((error) => { console.log(error); }); } function detailInit(nextInfo) { if (!nextInfo) { return; } const video = document.querySelector("#vjs_video_3_html5_api"); const doc = document.querySelector("[id^='easyXDM_']"); if (doc || video) { if (doc) { let count = 5; let countdownTimer = setInterval(() => { if (count <= 0) { clearInterval(countdownTimer); } count--; const p = document.getElementById("p-learn-title"); if (p) { p.innerText = " 正在运行中...:文档将在 " + count + " 秒后跳过"; } }, 1000); console.log("当前页面内容为文档"); const timer = setTimeout(() => { CoursewareNodesManager.onMenuClick(nextInfo.id); clearTimeout(timer); }, 5000); } else { console.log("当前页面内容为视频"); autoPlayMedia(video, nextInfo); } } else { const timer = setTimeout(() => { detailInit(nextInfo); clearTimeout(timer); }, 2000); } } //当页面为课程列表页时加载课程列表显示在页面的右边 function loadClassList() { if (!isListPage) { return; } GM_addStyle(` .class-name { width: 100px; text-align: center; overflow: hidden; /* 隐藏溢出内容 */ text-overflow: ellipsis; /* 显示省略号 */ white-space: nowrap; /* 文本不换行 */ } .p-lesson-list{ position: relative; margin-left: 20px; display: inline-block; } .btn{ background-color: #22bb93; color: #fff; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; transition: background-color 0.3s ease; outline: none; display: inline-block; text-align: center; } .btn:hover { background-color: #66b1ff; } .btn:active { background-color: #3a8ee6; } .finish-style{ background: #b3eeff !important; } /* 容器样式 */ .container-dialog { max-width: 500px; background: #fff; border-radius: 3px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); position: absolute; top: 20%; right: 50px; } /* 表格基础样式 - 增强外边框 */ .table-main { position: relative; width: 100%; border-collapse: collapse; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; border: 2px solid #000; border-radius: 4px; overflow: hidden; } /* 表头样式 */ .table-head th { height: 30px; background: linear-gradient(135deg, #00c922 0%, #00c922 100%); color: #fff; padding: 0; text-align: center; font-weight: 300; font-size: 14px; letter-spacing: 0.5px; border: 1px solid #5a67d8; } /* 表格单元格样式 */ .table-body td { padding: 0; border: 1px solid #dcdfe6; color: #333; font-size: 14px; } th, td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #e0e0e0; overflow: hidden; text-overflow: ellipsis; /* 内容过长时省略 */ white-space: nowrap; } /* 关键:表格主体容器,设置高度和滚动 */ .table-body-wrapper { max-height: 300px; /* 控制滚动区域高度,可根据需求调整 */ overflow-y: auto; /* 纵向超出时显示滚动条 */ overflow-x: hidden; /* 横向隐藏,避免出现双滚动条 */ } /* 滚动条样式美化(可选,适配Chrome/Safari) */ .table-body-wrapper::-webkit-scrollbar { width: 6px; /* 滚动条宽度 */ } .table-body-wrapper::-webkit-scrollbar-thumb { background-color: #ccc; border-radius: 3px; } .table-body-wrapper::-webkit-scrollbar-track { background-color: #f9f9f9; } /* 斑马纹效果 */ .table-body tr:nth-child(even) { background-color: #f9f9f9; } /* 悬停效果 */ .table-body tr:hover { background-color: #f0f7ff; transition: background-color 0.2s ease; } /* 圆角处理 */ .table-head th:first-child { border-top-left-radius: 3px; } /* 表格基础样式:取消默认间距,保证列对齐 */ table { border-collapse: collapse; /* 合并边框 */ table-layout: fixed; /* 固定列宽,避免内容撑开列 */ } .table-head th:last-child { border-top-right-radius: 3px; }`); const tableHtml = `
| 课程编号 | 课程名称 | 课程编码 | 学习时长 | 课程状态 | 操作 |
|---|