// ==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));
})
})();