// ==UserScript== // @name 江西智慧教育平台-教师培训-继续教育刷课助手(www.jx.smartedu.cn) // @namespace http://tampermonkey.net/ // @version 1.0 // @description 江西智慧教育平台全自动刷课助手,支持手动加速、批量秒过、弹窗屏蔽,客服微信wkds995 // @author 晓晓 // @match *://*.jx.smartedu.cn/* // @grant GM_getValue // @grant GM_setValue // @run-at document-start // @license MIT // ==/UserScript== (function() { 'use strict'; console.log('[国家智慧教育平台刷课助手 v1.0] 启动'); (function(){ function injectStyles() { if (document.getElementById('xx-popup-styles')) return; var s = document.createElement('style'); s.id = 'xx-popup-styles'; s.textContent = [ '.xx-mask{position:fixed;inset:0;background:rgba(0,0,0,0.75);z-index:99999998;display:flex;align-items:center;justify-content:center;}', '.xx-box{background:#181c2b;border-radius:16px;border:1px solid rgba(255,255,255,0.12);padding:28px;color:#fff;font-family:system-ui,-apple-system,sans-serif;}', '.xx-box h2{margin:0 0 18px;font-size:18px;text-align:center;border-bottom:1px solid rgba(255,255,255,0.1);padding-bottom:14px;color:#fff;}', '.xx-content{line-height:1.8;font-size:14px;color:#e2e8f0;}', '.xx-content p{margin:6px 0;}', '.xx-footer{margin-top:22px;text-align:center;}', '.xx-btn{padding:11px 36px;border:none;border-radius:10px;cursor:pointer;font-size:14px;font-weight:600;transition:opacity .2s;}', '.xx-btn:hover{opacity:0.88;}', '.xx-btn-primary{background:linear-gradient(135deg,#6a11cb,#2575fc);color:#fff;}', '.xx-btn-secondary{background:rgba(255,255,255,0.08);color:#aaa;border:1px solid rgba(255,255,255,0.15);}', '.xx-donate{width:360px;}', '.xx-donate h3{margin:0 0 14px;font-size:16px;text-align:center;letter-spacing:.5px;color:#fff;}', '.xx-wechat-label{text-align:center;font-size:13px;color:#c9d1d9;margin-bottom:10px;letter-spacing:1px;}', '.xx-qr-wrap{width:220px;height:220px;background:#fff;border-radius:12px;margin:0 auto 12px;display:flex;align-items:center;justify-content:center;overflow:hidden;}', '.xx-qr-wrap img{width:200px;height:200px;border-radius:8px;object-fit:cover;}', '.xx-donate-desc{font-size:12px;color:#c9d1d9;margin-bottom:16px;text-align:center;line-height:1.6;}' ].join(''); document.head.appendChild(s); } function createGuidePopup(items, btnText, onClose) { if (document.querySelector('.xx-guide-mask')) return; btnText = btnText || '我已知晓'; onClose = onClose || function(){}; injectStyles(); var lines = items.map(function(item){ var icon = item.ok !== false ? '\u2705' : '\u26a0\ufe0f'; return '

' + icon + ' ' + item.text + '

'; }).join(''); var mask = document.createElement('div'); mask.className = 'xx-mask xx-guide-mask'; mask.innerHTML = [ '
', '

📖 脚本使用须知

', '
' + lines + '
', '
' ].join(''); document.body.appendChild(mask); function close(){ mask.remove(); onClose(); } mask.querySelector('.guide-close-btn').onclick = close; mask.onclick = function(e){ if(e.target === mask) close(); }; } function createDonatePopup(wxQrUrl, desc, onClose) { if (document.querySelector('.xx-donate-mask')) return; onClose = onClose || function(){}; injectStyles(); var descHtml = desc ? '
' + desc + '
' : '
自愿打赏,您的支持是持续更新的动力
'; var mask = document.createElement('div'); mask.className = 'xx-mask xx-donate-mask'; mask.innerHTML = [ '
', '

\💰 感谢支持脚本持续维护更新

', '
微信支付
', '
微信收款码
', descHtml, '
' ].join(''); document.body.appendChild(mask); function close(){ mask.remove(); onClose(); } mask.querySelector('.donate-close-btn').onclick = close; mask.onclick = function(e){ if(e.target === mask) close(); }; } window.__popupTemplate = { guide: createGuidePopup, donate: createDonatePopup }; })(); // ===================== 核心功能代码 ===================== const bypassRestrictions = () => { Object.defineProperty(document, 'visibilityState', { value: 'visible', writable: false }); Object.defineProperty(document, 'hidden', { value: false, writable: false }); const stopProp = e => e.stopImmediatePropagation(); window.addEventListener('visibilitychange', stopProp, true); window.addEventListener('blur', stopProp, true); window.addEventListener('seeking', stopProp, true); window.addEventListener('seeked', stopProp, true); }; bypassRestrictions(); const sleep = ms => new Promise(r => setTimeout(r, ms)); function getRoot() { const head = document.querySelector('micro-app-head, #micro-app-head'); if (head && head.shadowRoot) return head.shadowRoot; const micro = document.querySelector('micro-app'); if (micro && micro.shadowRoot) { const inner = micro.shadowRoot.querySelector('micro-app-head, #micro-app-head'); return inner?.shadowRoot || micro.shadowRoot; } return document; } function closePopups() { document.querySelectorAll('button, div, span, i, a').forEach(el => { const text = el.innerText?.trim() || ''; const cls = el.className?.baseVal || el.className || ''; if (/关闭|取消|知道了|确定|继续|重播|再播|倍速|暂停学习|close|cancel/i.test(text) || /el-message-box__close|el-dialog__close|vjs-close-button|close-btn/i.test(cls)) { if (el.offsetWidth > 0) el.click(); } }); ['.el-message-box__wrapper', '.el-dialog__wrapper', '.vjs-modal-dialog', '.course-video-reload', '.speed-popup', '[class*="dialog"]', '[class*="modal"]'].forEach(sel => { document.querySelectorAll(sel).forEach(el => { if (getComputedStyle(el).display !== 'none') { el.style.display = 'none'; const closeBtn = el.querySelector('[class*="close"]'); if (closeBtn) closeBtn.click(); } }); }); } function startPopupObserver() { const observer = new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType === 1) { if (node.matches?.('.el-message-box__wrapper, .el-dialog__wrapper, .vjs-modal-dialog, .course-video-reload, .speed-popup, [class*="dialog"], [class*="modal"]')) { node.style.display = 'none'; closePopups(); } if (node.querySelectorAll) { node.querySelectorAll('.el-message-box__wrapper, .el-dialog__wrapper, .vjs-modal-dialog, .course-video-reload, .speed-popup, [class*="dialog"], [class*="modal"]').forEach(p => { p.style.display = 'none'; closePopups(); }); } } } } }); observer.observe(document.body, { childList: true, subtree: true }); } function isIconFinished(icon) { return icon && icon.classList.contains('icon_checkbox_fill'); } function maintainVideoSettings(video) { if (!video) return; if (video.muted !== true) video.muted = true; if (video.playbackRate !== 16.0) video.playbackRate = 16.0; if (video.paused && !video.ended) video.play().catch(() => {}); if (!video._pauseIntercepted) { video.pause = function() { if (video.currentTime < video.duration - 0.5) return; HTMLMediaElement.prototype.pause.apply(this, arguments); }; video._pauseIntercepted = true; } } const initExtremeController = () => { let loopTimer = null; let isNextTriggered = false; const checkIsItemFinished = () => { const activeItem = document.querySelector('.active, .is-active, .playing, .current, li[class*="active"], div[class*="active"]'); if (!activeItem) return false; const icon = activeItem.querySelector('i.icon_checkbox_linear, i.icon_checkbox_fill'); if (icon && icon.classList.contains('icon_checkbox_fill')) return true; if (activeItem.classList.contains('complete') || activeItem.classList.contains('finished')) return true; return false; }; const doInstantPass = () => { const video = document.querySelector('video'); if (!video) return; video.muted = true; if (video.playbackRate !== 16.0) video.playbackRate = 16.0; if (video.duration && video.currentTime < video.duration - 0.8) { video.currentTime = video.duration - 0.5; } if (video.paused) video.play().catch(() => {}); if (!video.hasPauseIntercepted) { video.pause = function() { if (video.currentTime < video.duration - 1) return; HTMLMediaElement.prototype.pause.apply(this, arguments); }; video.hasPauseIntercepted = true; } closePopups(); if (!isNextTriggered && checkIsItemFinished()) { console.log("✅ 识别完成标记,2秒后下一节"); isNextTriggered = true; setTimeout(() => { playNextVideo(); isNextTriggered = false; }, 2000); } }; const clickPopups = () => { const popupTexts = ["继续学习", "确定", "我知道了", "继续", "确认"]; document.querySelectorAll('button, div, span, a').forEach(el => { if (popupTexts.includes(el.innerText.trim()) && el.offsetWidth > 0) el.click(); }); }; const playNextVideo = () => { const activeItem = document.querySelector('.active, .is-active, .playing, .current'); if (activeItem) { const allList = Array.from(document.querySelectorAll('.video-item, .lesson-item, li, div[class*="item"]')); const curIdx = allList.indexOf(activeItem); if (curIdx !== -1 && curIdx + 1 < allList.length) { allList[curIdx + 1].click(); return; } } const nextKeywords = ["下一节", "下一课", "下一集", "下一页"]; const allButtons = document.querySelectorAll('button, a, div, span'); for (let btn of allButtons) { if (nextKeywords.some(kw => btn.innerText.includes(kw)) && btn.offsetWidth > 0) { btn.click(); break; } } }; if (loopTimer) clearInterval(loopTimer); loopTimer = setInterval(() => { doInstantPass(); clickPopups(); }, 1500); }; async function expandAll() { const root = getRoot(); const collapsed = root.querySelectorAll('.fish-collapse-item:not(.fish-collapse-item-active), .el-collapse-item:not(.is-active)'); for (const item of collapsed) { const header = item.querySelector('.fish-collapse-item__header, .fish-collapse-header, .el-collapse-item__header, [class*="collapse-header"]'); if (header) header.click(); await sleep(400); } if (!document.getElementById('expand-style')) { const style = document.createElement('style'); style.id = 'expand-style'; style.textContent = '.fish-collapse-item__wrap, .el-collapse-item__wrap { display:block!important; height:auto!important; }'; document.head.appendChild(style); } } function getVideoItems() { const root = getRoot(); const icons = root.querySelectorAll('i.icon_checkbox_linear, i.icon_checkbox_fill'); const items = []; icons.forEach(icon => { const parent = icon.closest('div[class*="item"], li, div[class*="row"]') || icon.parentElement; if (!parent) return; const isFinished = isIconFinished(icon); const text = parent.innerText.trim().split('\n')[0].substring(0, 60); items.push({ el: parent, icon, isFinished, text }); }); return [...new Map(items.map(v => [v.el, v])).values()]; } function clickItem(item) { const clickable = item.el.querySelector('a, button, [onclick]') || item.el; clickable.click(); } async function batchPlayVideoAndWait(item) { let video = null; for (let i = 0; i < 30; i++) { video = document.querySelector('video'); if (video) break; await sleep(500); } if (!video) return false; const maintInterval = setInterval(() => { closePopups(); maintainVideoSettings(video); }, 1000); return new Promise(resolve => { const onEnded = () => { clearInterval(maintInterval); video.removeEventListener('ended', onEnded); let tries = 0; const check = setInterval(() => { closePopups(); if (isIconFinished(item.icon) || ++tries >= 6) { clearInterval(check); resolve(true); } }, 500); }; video.addEventListener('ended', onEnded); setTimeout(() => { clearInterval(maintInterval); video.removeEventListener('ended', onEnded); resolve(false); }, 600000); }); } let batchRunning = false; let batchPaused = false; let batchSignal = { running: false }; async function batchLoop() { setBatchStatus('扫描目录...'); await expandAll(); const items = getVideoItems(); const unfinished = items.filter(i => !i.isFinished); if (unfinished.length === 0) { setBatchStatus('所有课程已完成'); batchRunning = false; batchSignal.running = false; updateBatchButton(false); return; } let i = 0; while (i < unfinished.length && batchSignal.running) { while (batchPaused && batchSignal.running) { await sleep(500); } if (!batchSignal.running) break; const item = unfinished[i]; setBatchStatus(`▶ ${item.text} (${i+1}/${unfinished.length})`); clickItem(item); await sleep(2000); await batchPlayVideoAndWait(item); await sleep(3000); i++; } setBatchStatus('批量完成'); batchRunning = false; batchSignal.running = false; updateBatchButton(false); } function startBatch() { if (batchRunning) { batchPaused = !batchPaused; setBatchStatus(batchPaused ? '已暂停' : '继续中...'); updateBatchButton(batchRunning && !batchPaused); return; } batchRunning = true; batchPaused = false; batchSignal.running = true; updateBatchButton(true); batchLoop(); } function stopBatch() { batchSignal.running = false; batchRunning = false; batchPaused = false; setBatchStatus('批量已停止'); } let manualRunning = false; let manualPaused = false; let manualInterval = null; let manualResolve = null; async function manualLoop() { let video = document.querySelector('video'); if (!video) { setManualStatus('未找到视频'); manualRunning = false; updateManualButton(false); return; } manualInterval = setInterval(() => { if (!manualPaused) { closePopups(); maintainVideoSettings(video); } }, 1000); return new Promise(resolve => { manualResolve = resolve; const onEnded = () => { clearInterval(manualInterval); video.removeEventListener('ended', onEnded); setManualStatus('手动加速完成'); manualRunning = false; updateManualButton(false); resolve(); }; video.addEventListener('ended', onEnded); setTimeout(() => { clearInterval(manualInterval); video.removeEventListener('ended', onEnded); setManualStatus('超时停止'); manualRunning = false; updateManualButton(false); resolve(); }, 600000); }); } function startManual() { if (manualRunning) { manualPaused = !manualPaused; setManualStatus(manualPaused ? '已暂停' : '继续加速中...'); updateManualButton(manualRunning && !manualPaused); return; } manualRunning = true; manualPaused = false; updateManualButton(true); manualLoop(); } function stopManual() { if (manualInterval) clearInterval(manualInterval); if (manualResolve) manualResolve(); manualRunning = false; manualPaused = false; setManualStatus('已停止'); } let statusDom, batchStatusDom, manualStatusDom; let batchBtn, manualBtn; function setStatus(msg) { if (statusDom) statusDom.innerText = msg; } function setBatchStatus(msg) { if (batchStatusDom) batchStatusDom.innerText = msg; } function setManualStatus(msg) { if (manualStatusDom) manualStatusDom.innerText = msg; } function updateBatchButton(active) { if (!batchBtn) return; if (!batchRunning) { batchBtn.textContent = '🚀 开始批量秒过'; batchBtn.style.background = 'linear-gradient(135deg, #6a11cb, #2575fc)'; } else if (batchPaused) { batchBtn.textContent = '▶ 继续批量秒过'; batchBtn.style.background = 'linear-gradient(135deg, #f39c12, #e67e22)'; } else { batchBtn.textContent = '⏸ 暂停批量秒过'; batchBtn.style.background = 'linear-gradient(135deg, #e74c3c, #c0392b)'; } } function updateManualButton(active) { if (!manualBtn) return; if (!manualRunning) { manualBtn.textContent = '🎯 开始手动加速'; manualBtn.style.background = 'linear-gradient(135deg, #6a11cb, #2575fc)'; } else if (manualPaused) { manualBtn.textContent = '▶ 继续手动加速'; manualBtn.style.background = 'linear-gradient(135deg, #f39c12, #e67e22)'; } else { manualBtn.textContent = '⏸ 暂停手动加速'; manualBtn.style.background = 'linear-gradient(135deg, #e74c3c, #c0392b)'; } } function createUI() { if (document.getElementById('master-panel')) return; const style = document.createElement('style'); style.textContent = ` .master-panel { background: rgba(18, 22, 40, 0.85); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px); border: 1px solid rgba(255, 255, 255, 0.15); border-radius: 24px; color: #fff; font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif; box-shadow: 0 30px 50px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05) inset; padding: 24px; width: 320px; position: fixed; z-index: 999999; left: 24px; top: 100px; transition: all 0.2s ease; } .master-panel:hover { border-color: rgba(255, 255, 255, 0.25); box-shadow: 0 35px 60px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.08) inset; } .master-title { font-size: 18px; font-weight: 700; margin-bottom: 20px; display: flex; align-items: center; gap: 10px; } .master-title::before { content: ''; width: 4px; height: 22px; background: linear-gradient(180deg, #6a11cb, #2575fc); border-radius: 2px; } .master-btn { background: linear-gradient(135deg, #6a11cb, #2575fc); border: none; border-radius: 14px; color: white; padding: 14px 18px; font-weight: 600; cursor: pointer; width: 100%; margin-bottom: 12px; font-size: 13px; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); letter-spacing: 0.3px; position: relative; overflow: hidden; } .master-btn:hover { transform: translateY(-2px); box-shadow: 0 10px 25px rgba(37, 117, 252, 0.4); } .master-btn:active { transform: translateY(0px); } .status-line { font-size: 11px; color: #a0b4cc; margin-top: 10px; word-break: break-all; padding: 8px 12px; background: rgba(255,255,255,0.05); border-radius: 8px; line-height: 1.4; } .auto-indicator { display: inline-flex; align-items: center; gap: 4px; background: rgba(39, 174, 96, 0.15); color: #2ecc71; padding: 2px 8px; border-radius: 20px; font-size: 10px; font-weight: 600; } .donate-btn{ background:linear-gradient(135deg,#27ae60,#2ecc71) !important; color:#fff !important; } .donate-btn:hover{ color:#ffdd66 !important; } `; document.head.appendChild(style); const html = `
⚡ 江西智慧教育 自动下一集已开启
📌 手动状态:就绪
📦 批量状态:就绪
客服微信:wkds995
`; const panel = document.createElement('div'); panel.id = 'master-panel'; panel.innerHTML = html; document.body.appendChild(panel); manualStatusDom = document.getElementById('manual-status'); batchStatusDom = document.getElementById('batch-status'); manualBtn = document.getElementById('manual-btn'); batchBtn = document.getElementById('batch-btn'); const donateBtn = document.getElementById('donate-btn'); manualBtn.onclick = startManual; batchBtn.onclick = startBatch; donateBtn.onclick = ()=> window.__popupTemplate.donate('https://i.postimg.cc/QdhkjkFG/wxpay.png', '自愿打赏,您的支持是持续更新的动力'); manualBtn.addEventListener('dblclick', stopManual); batchBtn.addEventListener('dblclick', stopBatch); } // ===================== 初始化入口 ===================== window.addEventListener('load', () => { setTimeout(() => { initExtremeController(); startPopupObserver(); // 标准弹窗:启动说明 → 关闭后显示控制面板 var T = window.__popupTemplate; T.guide([ { ok: true, text: '脚本说明:本脚本仅作为辅助,自行承担全部使用风险' }, { ok: true, text: '速度控制:需自行判断,合理控制速度,规避风控' }, { ok: true, text: '💰打赏按钮:自愿支持,不影响脚本任何功能' }, { ok: false, text: '请保持页面前台运行,不要频繁刷新页面' } ], '我已知晓', createUI); }, 2000); }); let activeUrl = location.href; setInterval(() => { if (location.href !== activeUrl) { activeUrl = location.href; setTimeout(()=>{ initExtremeController(); // 页面内切换课程,不再连续弹出双弹窗,只运行挂机功能 }, 2000); } }, 1500); })();