// ==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 = `
总自动化开关
章节自动连播
监听中
算术自动答题
开启
🔍手动检索侧边按键
运行日志:
`;
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);});
})
})();