您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically play and close video pages on a learning website
// ==UserScript== // @name 四川干部学院学习助手 // @namespace http://tampermonkey.net/ // @version 0.1.8 // @description Automatically play and close video pages on a learning website // @author grok // @match https://web.scgb.gov.cn/* // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAUCAYAAABSx2cSAAACQElEQVQ4jX2TvWtVQRDFf7N370tyAwkPBQsNzzSmUCwUtFAEQ1IpQWxEIY0fCJJaG0WFaOFfYCGibVBE0cJKERRsDNqmSMAmgoJFkkd4uTsyuzcvNx+4MHB395w5Z3bmio6P012qINIH3AZeUJazZBmsrqYQgd5eyHMIAUd92aVIG9URVL8BZ/jPcpQlMUJIyvatOh0pzr0FrsSkPT0pzInhIjmppbBD5yx+AH8jwvsndDoTLCzA/DwsLSXbkby+RBxra6k2CMBCvDFHef6aZnOIZjMRzd0W5VOI3I1g722/HJ1YwkYDWq3nDA9DUaQzMxUBqYY58vwDzs0SwhtEmhGxXs7Kymmc24dqG+cK4Kejvx8GBkxtLdrJsuMRHMJIJNZXCCeB/ag+M4yjr4+YIM8fRssiBSL3UM22tTGEA7TbgnOjOLfbs7hotg7j/eWq+VOo+krV6kny5sZ7JcsOVWVecrF3jcZMbFE69DW79vEyJkl3R8iyqeqdJqxVo8DItjlKNi0uIvIu7svyHJ3O0ao7QzZhkzsOoBGL4hFF0SGEp92EG676rc97dySX5StUb1X1vgeWtkLMdnsb0bnv5Pl5lpeJ4dwK8HUTRvWXkb/sYPlGtGeTlXU7tlnZ+xnRsbFdwO96TlQ3Zt66kJQWgT1VSSZQWM1/gDs1sr3I9U0PF8KDLjE5ukCj0U6zDfb/toCrFeAxcALVOUSOAWcrdYubDA7O2ED5muI1RD7GSzgITNbasorqZ1TvI/IpugmBf1/u5Q8Br3fMAAAAAElFTkSuQmCC // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function () { 'use strict'; // 日志内容 let LOGS = ``; // 课程页面显示信息 function showLogs() { if (!document.body) { console.log("加载信息框失败, 1秒后重试"); setTimeout(showLogs, 1000); } // 信息框 const noticeDiv = document.createElement('div'); noticeDiv.textContent = "脚本加载完成"; noticeDiv.id = "noticeDiv"; // 日志框 const logsDiv = document.createElement('div'); logsDiv.id = 'logsDiv'; LOGS = `如果只学习"必修/选修"\n点击[课程表-课程类型]中对应选项再点击[开始学习]按钮`; logsDiv.innerText = LOGS; // 开始按钮 const startBtn = document.createElement('button'); startBtn.id = "startBtn"; startBtn.textContent = "开始学习" startBtn.addEventListener("click", () => { startBtn.textContent = "重置学习状态" GM_setValue("isPlaying", false); setTimeout(goToNextVideo, 2000); }) // logsDiv startBtn加入noticeDiv noticeDiv.appendChild(logsDiv); noticeDiv.appendChild(startBtn); // noticeDiv 加入 body document.body.appendChild(noticeDiv); // 设置信息框样式 const style = document.createElement('style'); style.textContent = ` #startBtn { font-weight: bold; background-color: white; color: #5209c794; border: none; cursor: pointer; transition: background-color 0.3s ease; border-radius: 8px; padding: 5px 10px; position: absolute; bottom: 5px; } #startBtn:hover { background-color: #5209c794; color: white; } #noticeDiv{ position: fixed; bottom: 60%; left: 50%; background-color: rgba(0, 0, 0, 0.4); color: #fff; padding: 6px 10px; border-radius: 4px; font-size: 14px; z-index: 99999; min-width: 25%; min-height: 30%; box-shadow: 0 2px 6px rgba(0,0,0,.3); } `; document.head.appendChild(style); } // 更新日志显示 function updateLogs(log) { const logsDiv = document.querySelector("#logsDiv"); if (!logsDiv) { console.log("更新日志失败"); return; } LOGS += `\n${new Date().toLocaleTimeString()} ${log}`; LOGS = LOGS.split('\n').slice(-8).join('\n'); logsDiv.innerText = `\n${LOGS}`; } // 课程列表已激活页码 function getPageNumber() { const activePage = document.querySelector(".ivu-page-item-active"); return activePage ? activePage.title : "未知"; } // 当前页面未学习完成的课程 function getVideoDivs() { const divs = Array.from(document.querySelectorAll('.hover-shadow')).filter((div) => { const timesElement = div.querySelector('.fs_16.c_999'); if (!timesElement) { console.log('未找到学时元素,跳过此 div:', div); return false; } const times = timesElement.innerText.match(/(\d+(\.\d+)?)\s*学时/g)?.map(h => parseFloat(h)) || [0, 0]; console.log('视频学时:', timesElement.innerText, '解析结果:', times); return times[0] < times[1]; }); console.log('找到视频列表,长度:', divs.length); updateLogs("当前页未学习完成课程 " + divs.length + " 个") return divs; } // 标记当前页面点击过的序号 function markAsLearned(index) { const learnedVideos = GM_getValue('learnedVideos', []); if (!learnedVideos.includes(index)) { learnedVideos.push(index); GM_setValue('learnedVideos', learnedVideos); } } // 查找下一个课程,开始学习 function goToNextVideo() { console.log('检查下一个视频:', new Date().toLocaleTimeString(), 'isPlaying:', GM_getValue('isPlaying', false)); // 正在播放视频, 2秒后重试 if (GM_getValue('isPlaying', false)) { setTimeout(goToNextVideo, 2000); return; } // 当前页面未完成学习的课程 const videoDivs = getVideoDivs(); console.log('videoDivs 长度:', videoDivs.length); // 当前页面已点击过的课程序号 const learnedVideos = GM_getValue('learnedVideos', []); // 下一个未点击的课程序号 let nextIndex = videoDivs.findIndex((_, index) => !learnedVideos.includes(index)); // 当前页面学习完成 if (videoDivs.length === 0 || nextIndex === -1) { // 下一页按钮 const nextPageButton = document.querySelector('.ivu-page-next'); console.log('下一页按钮:', nextPageButton, '是否禁用:', nextPageButton?.classList.contains('ivu-page-disabled')); if (nextPageButton && !nextPageButton.classList.contains('ivu-page-disabled')) { console.log('本页视频已学习完成,跳转到下一页'); updateLogs('本页视频已学习完成,跳转到下一页'); GM_setValue('learnedVideos', []); nextPageButton.click(); setTimeout(goToNextVideo, 2000); } else { console.log('所有视频学习完成!'); updateLogs('所有视频学习完成!'); GM_setValue('learnedVideos', []); GM_setValue('isPlaying', false); } return; } // 要学习的视频课程 const videoDiv = videoDivs[nextIndex]; GM_setValue('isPlaying', true); // 标记该序号已点击 markAsLearned(nextIndex); console.log(`播放视频:索引 ${nextIndex}, 时间: ${new Date().toLocaleTimeString()}`); updateLogs(`播放视频:索引 ${nextIndex}`); try { videoDiv.click(); setTimeout(goToNextVideo, 10000); } catch (err) { console.log('点击视频失败:', err); GM_setValue('isPlaying', false); setTimeout(goToNextVideo, 2000); } } // 检查视频播放页正在播放的视频序号 function courseID() { // 左侧视频清单, 一个视频课程可能有多个视频, 清单在此div显示 const tabList = document.querySelectorAll('.tab-list > .item'); // 清单中正在播放序列号 let i = 0; for (i = 0; i < tabList.length; i++) { if (tabList[i].classList.contains("active")) { // 找到正在播放的序号 break; } } return i; } // 检查视频播放状态,服务端错误返回false function checkVideoStat() { // 视频播放控件 const video = document.querySelector('video'); // 服务端错误,无法播放 if (video.currentTime == 0) { return false; } return true; } // 视频播放页面,检查最后一个视频是否完成播放,完成播放->关闭页面 function checkVideoEnd() { // 左侧视频清单, 一个视频课程可能有多个视频 const tabList = document.querySelectorAll('.tab-list > .item'); // 视频播放控件 const video = document.querySelector('video'); // 没有找到视频清单的div,2秒后重试 if (!tabList) { console.log('未找到 tab-list,稍后重试'); setTimeout(checkVideoEnd, 2000); return; } // 没有找到视频控件,2秒后重试 if (!video) { console.log('未找到视频元素,稍后重试'); setTimeout(checkVideoEnd, 2000); return; } // 视频暂停,尝试播放 if (video.paused) { try { video.play(); } catch (err) { console.log('自动播放失败:', err) } } // 清单中正在播放序列号 let i = courseID(); console.log("courseID: ", i); // 2秒后检查是否为服务端错误,视频不能正常播放,尝试播放清单中的下一个 // 如果是列表中最后一个播放失败,关闭标签页 setTimeout(() => { // 服务端异常 if (!checkVideoStat) { // 序号i不是列表中最后一个,播放下一个,20秒后重新检查 if (i < tabList.length - 1) { tabList[i + 1].click(); setTimeout(checkVideoEnd, 20000); return; } else { window.close(); } } }, 2000); // 不是正在播放最后一个视频,20秒后重新检查 if (i != tabList.length - 1) { console.log('未到最后一个 tab,20秒后重试'); setTimeout(checkVideoEnd, 20000); return; } // 播放的是最后一个视频,结束后关闭页面,设置播放状态为未播放 video.onended = () => { console.log('视频播放结束,关闭页面'); GM_setValue('isPlaying', false); try { window.close(); } catch (err) { console.log('关闭页面失败:', err); } }; } window.addEventListener('load', () => { // 课程列表页 const isClassPage = window.location.href.includes('/myClass?id='); // 视频播放页 const isCoursePage = window.location.href.includes('/course?id='); if (isClassPage) { setTimeout(showLogs, 2000); updateLogs(`正在学习第 ${getPageNumber()} 页`); const options = document.querySelector(".ivu-page-options"); if (options) { options.remove(); updateLogs("删除显示数量选项标签"); } GM_setValue('learnedVideos', []); updateLogs("清空已学习记录"); GM_setValue('isPlaying', false); updateLogs("重置播放状态,请手动关闭已打开的播放网页"); return; } // 视频播放页面 if (isCoursePage) { checkVideoEnd(); } }); window.onbeforeunload = () => { GM_setValue('isPlaying', false); }; })();