// ==UserScript== // @name 南阳理工学院专业技术人员继续教育学习平台自动挂课助手 // @namespace com.qq.zhijianyuan // @version 1.0.0 // @description 自动拦截 15 分钟暂停、静音播放、自动跳章节、自动换课(仅视频,不含考试) // @author 吾爱汝至 // @match https://nykj.jxjyedu.org.cn/* // @grant unsafeWindow // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; console.log('[全自动脚本] 注入 ' + location.pathname); const pageWin = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; // ================= 通用拦截 ================= const origSetTimeout = pageWin.setTimeout; pageWin.setTimeout = function (fn, delay, ...args) { if (typeof delay === 'number' && delay >= 600000 && delay <= 1800000) { console.log('[拦截长定时器] delay =', delay); return -1; } return origSetTimeout.call(this, fn, delay, ...args); }; try { pageWin.HTMLMediaElement.prototype.pause = function () { console.log('[拦截 pause]'); }; } catch (e) {} pageWin.alert = function (msg) { console.log('[静默 alert]', msg); }; // ================= 黑名单工具 ================= function getBlacklist() { try { return JSON.parse(sessionStorage.getItem('autoStudy_blacklist') || '[]'); } catch (e) { return []; } } function addToBlacklist(courseId) { if (!courseId) return; var list = getBlacklist(); if (list.indexOf(String(courseId)) < 0) { list.push(String(courseId)); sessionStorage.setItem('autoStudy_blacklist', JSON.stringify(list)); console.log('[黑名单] 已加入 ' + courseId + ',当前黑名单:' + list.join(',')); } } function isBlacklisted(courseId) { return getBlacklist().indexOf(String(courseId)) >= 0; } // ================= 分页初始化 ================= function main() { var path = location.pathname; if (path.indexOf('/study.html') >= 0) initStudyPage(); else if (path.indexOf('/course_chapter.html') >= 0) initChapterPage(); else if (path.indexOf('/mycourse.html') >= 0 || path.indexOf('/person_center.html') >= 0) initMyCoursePage(); } // A. 视频播放页 function initStudyPage() { console.log('[视频页] 启动'); setInterval(function () { var v = document.querySelector('video'); if (!v) return; if (v.paused && !v.ended) { v.muted = true; v.play().catch(function () {}); } }, 1000); var attachInterval = setInterval(function () { var v = document.querySelector('video'); if (!v) return; clearInterval(attachInterval); console.log('[视频页] 绑定 ended'); v.addEventListener('ended', function () { console.log('[视频页] 播放完毕'); setTimeout(function () { // 优先用视频页 URL 的 id(真正 courseId) var urlIdM = /[?&]id=(\d+)/.exec(location.search); var urlCourseId = urlIdM ? urlIdM[1] : null; // 兜底用 sessionStorage var ssCourseId = sessionStorage.getItem('autoStudy_courseId'); // URL 里的 id 最可信,优先 var courseId = urlCourseId || ssCourseId; if (!courseId) { console.log('[视频页] 无法确定 courseId,返回首页兜底'); location.href = 'person_center.html'; return; } if (isBlacklisted(courseId)) { console.log('[视频页] ' + courseId + ' 在黑名单中,返回首页'); location.href = 'person_center.html'; return; } var m = /[?&]chapter=(\d+)/.exec(location.search); var currentChap = m ? parseInt(m[1]) : 0; var nextEl = document.getElementById('chapter' + (currentChap + 1)); if (!nextEl) { console.log('[视频页] 无下一章,返回章节列表 id=' + courseId); location.href = 'course_chapter.html?id=' + courseId; } else { console.log('[视频页] 有下一章,等待网站自动跳转'); } }, 2500); }); }, 500); } // B. 章节列表页 function initChapterPage() { console.log('[章节页] 启动'); var idM = /[?&]id=(\d+)/.exec(location.search); var currentId = idM ? idM[1] : null; if (currentId) { // 不覆盖 sessionStorage 里的 courseId,只在没有时写入 if (!sessionStorage.getItem('autoStudy_courseId')) { sessionStorage.setItem('autoStudy_courseId', currentId); } console.log('[章节页] 当前 courseId =', currentId); } // ★ 404 检测:3 秒内表格没出现,说明页面 404 或数据异常 var pageStartAt = Date.now(); var check404 = setInterval(function () { // 页面里已经出现 table.status,正常 if (document.querySelector('table.status')) { clearInterval(check404); return; } // 检测页面文案 var bodyText = document.body ? document.body.innerText : ''; var is404 = bodyText.indexOf('页面不存在') >= 0 || bodyText.indexOf('访问的页面') >= 0; if (is404 || Date.now() - pageStartAt > 5000) { clearInterval(check404); console.log('[章节页] 检测到 404 或页面异常,id=' + currentId); if (currentId) { addToBlacklist(currentId); } // 清掉可能错误的 sessionStorage sessionStorage.removeItem('autoStudy_courseId'); setTimeout(function () { console.log('[章节页] 返回首页'); location.href = 'person_center.html'; }, 1500); } }, 500); // 正常流程 var waitInterval = setInterval(function () { var rows = document.querySelectorAll('table.status tbody tr'); if (rows.length === 0) return; var videoRows = []; for (var i = 0; i < rows.length; i++) { var nameCell = rows[i].querySelector('td:nth-child(2)'); if (!nameCell) continue; if (nameCell.innerText.indexOf('课程测试') >= 0) continue; videoRows.push(rows[i]); } if (videoRows.length === 0) return; clearInterval(waitInterval); clearInterval(check404); var targetBtn = null; var targetName = ''; for (var j = 0; j < videoRows.length; j++) { var stCell = videoRows[j].querySelector('td:nth-child(4)'); if (!stCell) continue; var st = stCell.innerText; if (st.indexOf('未学习') >= 0 || st.indexOf('学习中') >= 0) { targetBtn = videoRows[j].querySelector('.study-btn'); targetName = videoRows[j].querySelector('td:nth-child(2)').innerText; break; } } if (targetBtn) { console.log('[章节页] 自动进入:' + targetName); setTimeout(function () { targetBtn.click(); }, 600); } else { console.log('[章节页] 本门课视频已全部完成,返回首页'); setTimeout(function () { location.href = 'person_center.html'; }, 1500); } }, 800); } // C. 首页 function initMyCoursePage() { console.log('[首页] 启动'); var startTime = Date.now(); var waitInterval = setInterval(function () { var container = document.querySelector('#zyk') || document.body; var allCourses = container.querySelectorAll('.course li'); if (allCourses.length === 0) { if (Date.now() - startTime > 10000) { console.log('[首页] 10 秒内未检测到课程列表,放弃'); clearInterval(waitInterval); } return; } clearInterval(waitInterval); var startBtns = container.querySelectorAll('.start'); if (startBtns.length === 0) { console.log('[首页] 没有未完成的课程'); return; } console.log('[首页] 共有 ' + startBtns.length + ' 门未完成课程,开始逐个筛选...'); var validBtn = null; var validInfo = ''; var skippedList = []; for (var k = 0; k < startBtns.length; k++) { var btn = startBtns[k]; var li = btn.closest('li'); if (!li) continue; var courseId = btn.getAttribute('course'); // ★ 黑名单过滤 if (isBlacklisted(courseId)) { skippedList.push(courseId + '(黑名单)'); continue; } var timerEl = li.querySelector('.timer span'); var txt = timerEl ? timerEl.innerText : ''; var mm = /已完成\s*(\d+)\/(\d+)\s*章/.exec(txt); if (mm) { var done = parseInt(mm[1]); var total = parseInt(mm[2]); if (done < total) { validBtn = btn; validInfo = 'courseId=' + courseId + ' 进度 ' + done + '/' + total; break; } else { skippedList.push(courseId + '(' + done + '/' + total + ' 视频已完成,需考试)'); } } else { skippedList.push(courseId + '(无法解析进度)'); } } if (skippedList.length > 0) { console.log('[首页] 跳过 ' + skippedList.length + ' 门课程:'); skippedList.forEach(function (s) { console.log(' - ' + s); }); } if (validBtn) { console.log('[首页] 进入:' + validInfo); // 记录正确的 courseId 到 sessionStorage var realId = validBtn.getAttribute('course'); sessionStorage.setItem('autoStudy_courseId', realId); setTimeout(function () { validBtn.click(); }, 800); } else { console.log('[首页] 所有未完成课程的视频都已完成,仅剩考试需要手动处理,脚本停止。'); } }, 800); } // ================= 启动 ================= if (document.readyState === 'loading') { window.addEventListener('DOMContentLoaded', main); } else { main(); } })();