// ==UserScript== // @name 自用播放器2.2 // @namespace local.rcpxpt.public // @version 2.2 // @description 全边界覆盖自测:侧边播放器章节图标自动点击、算术单选自动作答、切屏弹窗拦截、总开关完整启停、日志防刷屏、DOM延迟兼容 // @author zfk // @match *://*.rcpxpt.com/* // @grant GM_addStyle // @run-at document-start // ==/UserScript== (function () { 'use strict'; const RUNTIME_KEY = '__RCXPPT_PUBLIC_V3_RUNTIME_SINGLE_LOCK__'; if (unsafeWindow[RUNTIME_KEY]) { console.warn('[RCX v3.4.4] 脚本已加载,禁止重复初始化'); return; } unsafeWindow[RUNTIME_KEY] = { version: '3.4.4', startTime: Date.now(), timerList: [] }; const globalTimerStore = unsafeWindow[RUNTIME_KEY].timerList; function safeSetTimer(fn, delay) { const t = setTimeout(fn, delay); globalTimerStore.push(t); return t; } function safeSetInterval(fn, delay) { const t = setInterval(fn, delay); globalTimerStore.push(t); return t; } const UI_STYLE = ` #rcx-modern-panel { position: fixed; top: 20px; right: 20px; width: 340px; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); font-family: system-ui,sans-serif; z-index: 999999; user-select: none; } #rcx-header { display: flex; justify-content: space-between; align-items: center; padding:12px 16px; border-bottom:1px solid #eee; background:#f8fafc; border-radius:12px 12px 0 0; } #rcx-title { font-size:14px; font-weight:600; color:#1e293b; } #rcx-body { padding:16px; } .rcx-control-group { margin-bottom:12px; display:flex; justify-content:space-between; align-items:center; font-size:13px; color:#475569; } .rcx-btn { background:#3b82f6; color:white; border:none; padding:6px 12px; border-radius:6px; cursor:pointer; font-size:12px; transition: background 0.2s; } .rcx-btn.active { background:#10b981; } #rcx-logs { margin-top:10px; background:#0f172a; color:#38bdf8; padding:8px; border-radius:6px; font-family:monospace; font-size:11px; height:100px; overflow-y:auto; } `; GM_addStyle(UI_STYLE); unsafeWindow.RCX_Log = function(msg) { const logs = document.getElementById('rcx-logs'); if (!logs) return; const time = new Date().toTimeString().split(' ')[0]; logs.innerHTML += `[${time}] ${msg}
`; logs.scrollTop = logs.scrollHeight; if(logs.children.length > 100) logs.removeChild(logs.firstChild); }; function createModernUI() { if (document.getElementById('rcx-modern-panel')) return; const panel = document.createElement('div'); panel.id = 'rcx-modern-panel'; panel.innerHTML = `
🚀 福建培训·全边界自测控制台 v3.4.4
总自动化开关
章节自动连播 监听中
算术自动答题 开启
🔍手动检索侧边按键
运行日志:
`; document.body.appendChild(panel); let isMin = false; document.getElementById('rcx-min-btn').onclick = () => { isMin = !isMin; document.getElementById('rcx-body').style.display = isMin ? 'none' : 'block'; document.getElementById('rcx-min-btn').innerText = isMin ? '+' : '_'; }; document.getElementById('rcx-toggle-run').onclick = (e) => { const state = unsafeWindow.RCX_VideoScheduler.toggle(); e.target.innerText = state ? '运行中' : '已暂停'; e.target.className = state ? 'rcx-btn active' : 'rcx-btn'; const vidStatus = document.getElementById('rcx-status-vid'); const quizStatus = document.getElementById('rcx-status-quiz'); if(state){ vidStatus.innerText = "监听中"; vidStatus.style.color = "#10b981"; quizStatus.innerText = "开启"; quizStatus.style.color = "#10b981"; RCX_Log('✅全部自动化功能已恢复运行'); }else{ vidStatus.innerText = "已停用"; vidStatus.style.color = "#ef4444"; quizStatus.innerText = "关闭"; quizStatus.style.color = "#ef4444"; RCX_Log('⏸全部自动化功能已暂停,停止检索侧边按键'); } }; document.getElementById('rcx-find-chapter').onclick = ()=>{ unsafeWindow.RCX_VideoScheduler.autoOpenChapterSidebar(true); } } class VideoAutomationScheduler { constructor() { this.isRunning = true; this.chapterOpened = false; this.warnedChapter = false; } init() { RCX_Log('✅【v3.4.4】播放器侧边图标按键调度器初始化'); safeSetTimer(()=>this.autoOpenChapterSidebar(),1500); this.timer = safeSetInterval(() => { if (!this.isRunning) return; this.processVideoTask(); }, 1100); } autoOpenChapterSidebar(force=false){ if(!this.isRunning && !force) return; if(this.chapterOpened && !force) return; let sideBar = null; const allDivs = document.querySelectorAll('div'); for(let d of allDivs){ const style = getComputedStyle(d); if((style.position === 'fixed' || style.position === 'absolute') && parseFloat(style.right) < 120 && parseFloat(style.width) < 100 && parseFloat(style.height) > 200){ sideBar = d; break; } } let chapterBtn = null; if(sideBar){ const sideItems = sideBar.querySelectorAll('div,span'); for(let el of sideItems){ const txt = el.innerText?.trim(); if(txt === '章节'){ chapterBtn = el; break; } } } if(!chapterBtn){ const allNodes = document.querySelectorAll('div,span,button,a'); for(let el of allNodes){ const text = el.innerText?.trim(); if(text === '章节'){ chapterBtn = el; break; } } } if(chapterBtn){ chapterBtn.click(); this.chapterOpened = true; this.warnedChapter = false; RCX_Log('✅成功点击播放器侧边【章节】图标按键,滑出课程列表'); }else{ if(!this.warnedChapter || force){ RCX_Log('⚠️未检索到播放器侧边「章节」图标按键,可点击【手动重试】按钮重新检索'); this.warnedChapter = true; } if(this.isRunning){ safeSetTimer(()=>{ this.autoOpenChapterSidebar(); },4000); } } } processVideoTask() { const video = document.querySelector('video'); if (!video) return; if (!video.muted) video.muted = true; if (video.paused && !video.ended) { video.play().catch(()=>{}); } const finishPoint = video.duration - 0.6; if (video.duration > 0 && video.currentTime >= finishPoint) { RCX_Log('🎬视频播放完毕,检索侧边课程条目'); this.triggerNextEpisode(); } } triggerNextEpisode() { let listItems = document.querySelectorAll('div[style*="cursor:pointer"]'); if(!listItems.length){ RCX_Log('❌侧边课程列表未渲染完成,500ms后重试读取'); safeSetTimer(()=>{ listItems = document.querySelectorAll('div[style*="cursor:pointer"]'); this.matchAndClickNext(listItems); },500); return; } this.matchAndClickNext(listItems); } matchAndClickNext(listItems){ const itemArr = Array.from(listItems); let currentIndex = -1; for(let i=0; i{ mutList.forEach(m=>{ m.addedNodes.forEach(node=>{ if(node.nodeType!==1) return; const txt = node.innerText; if(txt.includes('单选题') && txt.includes('提交')){ const nodeId = node.innerText.slice(0,30); if(this.handledQuizSet.has(nodeId)) return; this.handledQuizSet.add(nodeId); RCX_Log('📝检测到答题弹窗,等待DOM渲染'); safeSetTimer(()=>this.solveQuiz(node),600); } }) }) }); this.observer.observe(document.body,{childList:true,subtree:true}); } solveQuiz(wrapNode){ const regExp = /\d+[+\-*/]\d+(?:[+\-*/]\d+)*/; const allTexts = wrapNode.innerText.match(regExp); if(!allTexts || allTexts.length===0){ RCX_Log('❌未识别标准算术题目,跳过答题'); return; } const qText = allTexts[0]; let targetAnswer; try{ targetAnswer = eval(qText); RCX_Log(`🧮解析算式:${qText} = ${targetAnswer}`); }catch(e){ RCX_Log('❌算式解析失败,跳过自动答题'); return; } const radioList = wrapNode.querySelectorAll('input[type="radio"]'); let selected = false; for(const r of radioList){ let container = r; let optionText = ""; for(let depth=0; depth<6; depth++){ container = container.parentElement; if(!container) break; const t = container.innerText.trim(); if(t.match(/^[A-Z]\.\s*\d+/)){ optionText = t; break; } } if(!optionText) continue; const numStr = optionText.replace(/[^0-9]/g,''); const numVal = Number(numStr); if(numVal === targetAnswer){ r.click(); RCX_Log(`☑自动勾选正确选项:${optionText}`); selected = true; break; } } if(!selected){ RCX_Log('⚠️未匹配对应答案选项'); return; } safeSetTimer(()=>{ const submitBtn = Array.from(wrapNode.querySelectorAll('button')).find(b=>b.innerText.trim()==='提交'); if(submitBtn){ submitBtn.click(); RCX_Log('📤自动点击【提交】按钮'); const checkTimer = safeSetInterval(()=>{ const allText = document.body.innerText; if(allText.includes('答案正确')){ const finishBtn = Array.from(wrapNode.querySelectorAll('button')).find(b=>b.innerText.trim()==='完成'); if(finishBtn){ finishBtn.click(); RCX_Log('✅校验通过,点击【完成】恢复视频播放'); clearInterval(checkTimer); } } },600); } },400); } } class PopupInterceptor { constructor() { this.observer = null; } init() { RCX_Log('🛡切屏弹窗拦截模块启动'); this.observer = new MutationObserver((mutations) => { for (let mutation of mutations) { if (mutation.addedNodes.length) { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { const text = node.innerText || ''; if (text.includes('切屏') || text.includes('离开') || text.includes('暂停') || text.includes('请继续')) { const closeBtn = node.querySelector('.el-dialog__close, .layui-layer-close, button'); if (closeBtn) { closeBtn.click(); RCX_Log('✅自动关闭切屏弹窗'); } else { node.style.display = 'none'; RCX_Log('ℹ弹窗无关闭按钮,强制隐藏遮罩'); } } } }); } } }); this.observer.observe(document.body, { childList: true, subtree: true }); } } window.addEventListener('DOMContentLoaded', () => { createModernUI(); RCX_Log('✅悬浮控制台加载完成'); unsafeWindow.RCX_VideoScheduler.init(); new PopupInterceptor().init(); new AutoQuizSolver().init(); }); window.addEventListener('beforeunload',()=>{ globalTimerStore.forEach(t=>{clearTimeout(t);clearInterval(t);}); }) })();