// ==UserScript== // @name 江西专技学习网-江西师范大学-全自动倍速播放刷课助手(zjpt.jxnu.edu.cn) // @version 1.0.0 // @description 江西专技学习网(江西师范大学)专用版:倍速播放+静音+自动播放+记忆进度,兼容公需课/专业课所有视频 // @author 晓晓 // @match https://zjpt.jxnu.edu.cn/* // @match https://zjpt-web.jxnu.edu.cn/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @run-at document-end // @license MIT // ==/UserScript== (function () { 'use strict'; var SETTINGS_KEY = 'zjpt_speed_settings'; var defaults = { speed: 2, muted: true, autoplay: true, remember: true }; var S = Object.assign({}, defaults, GM_getValue(SETTINGS_KEY, {})); function save() { GM_setValue(SETTINGS_KEY, S); } // ==================== 工具 ==================== function $1(s, ctx) { return (ctx || document).querySelector(s); } function $A(s, ctx) { return Array.from((ctx || document).querySelectorAll(s)); } function log(msg) { var el = $1('#zjpt-log'); if (el) { var t = new Date().toLocaleTimeString('zh-CN', { hour12: false }); el.value += '[' + t + '] ' + msg + '\n'; el.scrollTop = el.scrollHeight; } console.log('[江西专技]', msg); } // 遍历shadow root function* getShadowRoots(root) { if (!root) return; var walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT); var node; while (node = walker.nextNode()) { if (node.shadowRoot) { yield node.shadowRoot; yield* getShadowRoots(node.shadowRoot); } } } function qsa(selector, ctx) { ctx = ctx || document; var r = $A(selector, ctx); for (var sr of getShadowRoots(ctx)) { r = r.concat($A(selector, sr)); } return r; } // ==================== 视频控制 ==================== function applyToAllVideos(action) { qsa('video').forEach(function(v) { try { action(v); } catch (e) {} }); $A('iframe').forEach(function(frame) { try { qsa('video', (frame.contentDocument || frame.contentWindow.document)).forEach(action); } catch (e) {} }); } function applySpeed(v) { if (v.playbackRate !== S.speed) v.playbackRate = S.speed; } function applyMuted(v) { if (v.muted !== S.muted) v.muted = S.muted; } function applyAutoplay(v) { if (S.autoplay && v.paused && v.readyState >= 3) v.play().catch(function(){}); } function applyAll() { applyToAllVideos(function(v) { applySpeed(v); applyMuted(v); applyAutoplay(v); }); } // 记忆进度 function saveProgress() { if (!S.remember) return; qsa('video').forEach(function(v) { if (v.duration > 5 && v.currentTime > 1) { var key = 'zjpt_prog_' + location.host + '_' + v.src; GM_setValue(key, v.currentTime); } }); } function restoreProgress() { if (!S.remember) return; applyToAllVideos(function(v) { var key = 'zjpt_prog_' + location.host + '_' + v.src; var t = GM_getValue(key, 0); if (t > 1 && t < v.duration - 3) { v.currentTime = t; log('\u8bb0\u5fc6\u8fdb\u5ea6\u6062\u590d: ' + Math.floor(t/60) + '\u5206' + (t%60).toFixed(0) + '\u79d2'); } }); } // ==================== UI面板 ==================== function createPanel() { if ($1('#zjpt-panel')) return; var el = document.createElement('div'); el.id = 'zjpt-panel'; el.style.cssText = [ 'position:fixed;top:20px;right:20px;z-index:999999;', 'background:linear-gradient(135deg,#1a1a2e,#16213e);', 'color:#e0e0e0;padding:14px 18px;border-radius:12px;', 'min-width:300px;box-shadow:0 8px 32px rgba(0,0,0,0.5);', 'font-family:"PingFang SC","Microsoft YaHei",sans-serif;', 'border:1px solid rgba(255,255,255,0.08);font-size:13px;' ].join(''); el.innerHTML = '