// ==UserScript== // @name 自用播放器2.1 // @namespace local.rcpxpt.public // @version 2.1 // @description 修复:算术题正则匹配、答案结果循环检测、章节按钮检索范围扩大 // @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 修复版] 脚本已加载,禁止重复初始化'); return; } unsafeWindow[RUNTIME_KEY] = { version: '3.4.1', 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 = `
🚀 福建培训·修复版控制台
总自动化开关
章节自动连播 监听中
算术自动答题 开启
运行日志:
`; 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) => { if (unsafeWindow.RCX_VideoScheduler) { 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('⏸全部自动化功能已暂停'); } } }; } class VideoAutomationScheduler { constructor() { this.isRunning = true; this.timer = null; this.chapterOpened = false; } init() { RCX_Log('✅【修复版】章节连播调度器初始化'); safeSetTimer(()=>this.autoOpenChapterSidebar(),1200); this.timer = safeSetInterval(() => { if (!this.isRunning) return; this.processVideoTask(); }, 1100); } autoOpenChapterSidebar(){ if(this.chapterOpened) return; // 修复:扩大检索范围:div / span / button 全部查找 const allNodes = document.querySelectorAll('div,span,button'); let chapterBtn = null; for(let el of allNodes){ const text = el.innerText?.trim(); if(text === '章节'){ chapterBtn = el; break; } } if(chapterBtn){ chapterBtn.click(); this.chapterOpened = true; RCX_Log('✅自动点击【章节】,滑出侧边课程栏'); }else{ RCX_Log('⚠️未检测到章节按钮,若需连播请手动点击页面右侧「章节」'); safeSetTimer(()=>{ this.chapterOpened = false; this.autoOpenChapterSidebar(); },3000); } } 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('❌暂未读取课程条目,等待渲染后重试'); 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+)*/; let qText = null; // 在弹窗内搜索任意子节点包含算式 const allTexts = wrapNode.innerText.match(regExp); if(!allTexts || allTexts.length===0){ RCX_Log('❌未识别算术题目,跳过自动答题'); return; } 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(let r of radioList){ const optRaw = r.parentElement.innerText.trim(); const numOnly = optRaw.replace(/[^0-9]/g,''); if(Number(numOnly) === targetAnswer){ r.click(); RCX_Log(`☑自动勾选正确选项:${optRaw}`); 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)); }) })();