// ==UserScript== // @name 成学课堂3.0(视频精简版) // @namespace http://tampermonkey.net/ // @version 3.4-video // @description 成学课堂自动化控制面板(仅视频部分:全自动播放、跳转、下一节、定时任务) // @author YourName // @match *://*.cx-online.net/* // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; if (window.autoControlPanelInjected) return; window.autoControlPanelInjected = true; // 样式(精简后无变化,可保留) const style = document.createElement('style'); style.textContent = ` .auto-control-panel { position: fixed; top: 20px; right: 20px; width: 380px; background: white; border-radius: 12px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); z-index: 10000; font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif; overflow: hidden; border: 1px solid #e1e5e9; } .panel-header { background: linear-gradient(135deg, #1E4EE7, #3A7BFF); color: white; padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; cursor: move; } .panel-title { font-weight: 600; font-size: 16px; display: flex; align-items: center; gap: 8px; } .panel-controls { display: flex; gap: 8px; } .panel-btn { background: rgba(255, 255, 255, 0.2); border: none; color: white; width: 24px; height: 24px; border-radius: 4px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.2s; } .panel-btn:hover { background: rgba(255, 255, 255, 0.3); } .panel-body { padding: 16px; max-height: 500px; overflow-y: auto; } .status-section { margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; } .section-title { font-size: 14px; font-weight: 600; margin-bottom: 8px; color: #333; display: flex; align-items: center; gap: 6px; } .status-item { display: flex; justify-content: space-between; margin-bottom: 6px; font-size: 13px; } .status-label { color: #666; } .status-value { font-weight: 500; color: #333; } .status-value.active { color: #1E4EE7; } .status-value.completed { color: #00a854; } .status-value.error { color: #f5222d; } .controls-section { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; } .control-btn { flex: 1; min-width: 150px; padding: 8px 12px; background: #f5f7fa; border: 1px solid #e1e5e9; border-radius: 6px; font-size: 13px; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; gap: 6px; } .control-btn:hover { background: #ebf0f5; } .control-btn.primary { background: #1E4EE7; color: white; border-color: #1E4EE7; } .control-btn.primary:hover { background: #3A7BFF; } .control-btn.danger { background: #f5222d; color: white; border-color: #f5222d; } .control-btn.danger:hover { background: #ff4d4f; } .control-btn.success { background: #00a854; color: white; border-color: #00a854; } .control-btn.success:hover { background: #00c853; } .control-btn.warning { background: #fa8c16; color: white; border-color: #fa8c16; } .control-btn.warning:hover { background: #ffa940; } .control-btn.info { background: #1890ff; color: white; border-color: #1890ff; } .control-btn.info:hover { background: #40a9ff; } .progress-section { margin-top: 16px; } .progress-bar { height: 6px; background: #f0f0f0; border-radius: 3px; overflow: hidden; margin-bottom: 8px; } .progress-fill { height: 100%; background: linear-gradient(90deg, #1E4EE7, #3A7BFF); border-radius: 3px; transition: width 0.3s ease; } .progress-text { font-size: 12px; color: #666; text-align: center; } .log-section { margin-top: 16px; max-height: 120px; overflow-y: auto; border: 1px solid #f0f0f0; border-radius: 6px; padding: 8px; background: #fafafa; } .log-entry { font-size: 12px; margin-bottom: 4px; padding: 4px; border-radius: 3px; background: white; } .log-time { color: #999; margin-right: 6px; } .log-info { color: #1890ff; } .log-success { color: #00a854; } .log-warning { color: #fa8c16; } .log-error { color: #f5222d; } .minimized .panel-body { display: none; } .minimized { width: 200px; } .platform-indicator { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; } .platform-pc { background: #52c41a; } .platform-mobile { background: #1890ff; } .auto-mode-section { background: #f0f7ff; border-radius: 8px; padding: 12px; margin-bottom: 16px; border: 1px solid #d1e9ff; } @media (max-width: 768px) { .auto-control-panel { width: 340px; right: 10px; top: 10px; } } `; document.head.appendChild(style); // 面板HTML(移除了答题相关按钮和状态) const panelHTML = `
成学课堂视频自动化 v3.4
🤖 全自动视频模式
🔍 系统状态
自动化状态: 未启动
平台检测: 检测中...
视频识别: 等待中
播放状态: 等待中
当前任务: 检测中...
弹窗状态: 未检测
⏰ 定时任务
循环次数:
0s
📊 学习进度
等待检测进度...
${getCurrentTime()} 控制面板初始化完成
`; // 全局变量 let isFullAutoMode = false; let autoCheckInterval = null; let timerInterval = null; let timerTimeouts = []; let timerCancelled = false; let currentLoopRemaining = 0; // 注入面板 function injectControlPanel() { if (document.getElementById('autoControlPanel')) return; const tempDiv = document.createElement('div'); tempDiv.innerHTML = panelHTML; const panel = tempDiv.firstElementChild; document.body.appendChild(panel); initPanelFunctionality(); console.log('成学课堂视频控制面板已注入'); } // 初始化面板功能 function initPanelFunctionality() { const panel = document.getElementById('autoControlPanel'); const panelHeader = document.getElementById('panelHeader'); const minimizeBtn = document.getElementById('minimizeBtn'); const closeBtn = document.getElementById('closeBtn'); const fullAutoBtn = document.getElementById('fullAutoBtn'); const stopAutoBtn = document.getElementById('stopAutoBtn'); const startAutoBtn = document.getElementById('startAutoBtn'); const pauseBtn = document.getElementById('pauseBtn'); const jumpToEndBtn = document.getElementById('jumpToEndBtn'); const nextSectionBtn = document.getElementById('nextSectionBtn'); const timerActionSelect = document.getElementById('timerActionSelect'); const timerSecondsInput = document.getElementById('timerSeconds'); const loopCountInput = document.getElementById('loopCount'); const startTimerBtn = document.getElementById('startTimerBtn'); const timerDisplay = document.getElementById('timerDisplay'); detectPlatform(); // 拖拽功能 let isDragging = false; let dragOffset = { x: 0, y: 0 }; panelHeader.addEventListener('mousedown', function(e) { isDragging = true; dragOffset.x = e.clientX - panel.getBoundingClientRect().left; dragOffset.y = e.clientY - panel.getBoundingClientRect().top; panel.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; const x = e.clientX - dragOffset.x; const y = e.clientY - dragOffset.y; const maxX = window.innerWidth - panel.offsetWidth; const maxY = window.innerHeight - panel.offsetHeight; panel.style.left = Math.max(0, Math.min(x, maxX)) + 'px'; panel.style.top = Math.max(0, Math.min(y, maxY)) + 'px'; panel.style.right = 'auto'; }); document.addEventListener('mouseup', function() { isDragging = false; panel.style.cursor = ''; }); // 最小化/关闭 minimizeBtn.addEventListener('click', function() { panel.classList.toggle('minimized'); minimizeBtn.textContent = panel.classList.contains('minimized') ? '+' : '−'; }); closeBtn.addEventListener('click', function() { if (confirm('确定要关闭控制面板吗?')) { panel.style.display = 'none'; stopFullAutoMode(); cancelAllTimers(); } }); // 全自动模式 fullAutoBtn.addEventListener('click', startFullAutoMode); stopAutoBtn.addEventListener('click', stopFullAutoMode); let isAutomationRunning = false; startAutoBtn.addEventListener('click', function() { if (!isAutomationRunning) { isAutomationRunning = true; startAutoBtn.innerHTML = '⏹️ 停止播放'; startAutoBtn.classList.add('danger'); document.getElementById('playbackStatus').textContent = '播放中'; document.getElementById('playbackStatus').className = 'status-value active'; addLog('开始播放视频', 'success'); startRealAutomation(); } else { isAutomationRunning = false; startAutoBtn.innerHTML = '▶️ 开始播放'; startAutoBtn.classList.remove('danger'); document.getElementById('playbackStatus').textContent = '已停止'; document.getElementById('playbackStatus').className = 'status-value'; addLog('停止播放', 'warning'); } }); pauseBtn.addEventListener('click', function() { const videos = document.querySelectorAll('video'); if (videos.length > 0) { if (!videos[0].paused) { videos[0].pause(); addLog('暂停播放', 'warning'); document.getElementById('playbackStatus').textContent = '已暂停'; } else { videos[0].play(); addLog('继续播放', 'info'); document.getElementById('playbackStatus').textContent = '播放中'; } } }); jumpToEndBtn.addEventListener('click', function() { addLog('尝试跳转到视频结尾', 'info'); jumpVideoToEnd(); }); nextSectionBtn.addEventListener('click', function() { addLog('尝试点击"观看下节视频"按钮', 'info'); clickNextSectionButton(); }); // 定时任务(支持循环) function cancelAllTimers() { if (timerInterval) clearInterval(timerInterval); timerTimeouts.forEach(id => clearTimeout(id)); timerTimeouts = []; timerCancelled = true; startTimerBtn.innerHTML = ' 启动定时任务'; timerDisplay.textContent = '0s'; } function executeJumpThenNextLoop(remainingLoops, delaySeconds) { if (timerCancelled || remainingLoops <= 0) { startTimerBtn.innerHTML = ' 启动定时任务'; timerDisplay.textContent = '0s'; return; } currentLoopRemaining = remainingLoops; addLog(`⏳ 开始第 ${remainingLoops} 次循环(共剩余 ${remainingLoops} 次)`, 'info'); jumpVideoToEnd(); let remainingSeconds = delaySeconds; timerDisplay.textContent = `${remainingSeconds}s`; if (timerInterval) clearInterval(timerInterval); timerInterval = setInterval(() => { remainingSeconds -= 1; timerDisplay.textContent = `${remainingSeconds}s`; if (remainingSeconds <= 0) clearInterval(timerInterval); }, 1000); const timeoutId = setTimeout(() => { if (timerInterval) clearInterval(timerInterval); timerInterval = null; if (timerCancelled) { startTimerBtn.innerHTML = ' 启动定时任务'; timerDisplay.textContent = '0s'; return; } const clicked = clickNextSectionButton(); if (clicked && remainingLoops - 1 > 0) { addLog(`⏳ 等待新视频加载,准备第 ${remainingLoops - 1} 次循环...`, 'info'); const waitTimeout = setTimeout(() => { if (!timerCancelled) { executeJumpThenNextLoop(remainingLoops - 1, delaySeconds); } }, 3000); timerTimeouts.push(waitTimeout); } else if (!clicked) { addLog('❌ 点击"观看下节视频"失败,循环终止', 'error'); startTimerBtn.innerHTML = ' 启动定时任务'; timerDisplay.textContent = '0s'; } else { addLog('✅ 定时任务循环执行完毕', 'success'); startTimerBtn.innerHTML = ' 启动定时任务'; timerDisplay.textContent = '0s'; } }, delaySeconds * 1000); timerTimeouts.push(timeoutId); } function startTimer() { if (timerInterval || timerTimeouts.length > 0) { cancelAllTimers(); addLog('定时任务已取消', 'warning'); return; } const seconds = parseInt(timerSecondsInput.value, 10); if (isNaN(seconds) || seconds < 1) { addLog('请输入有效的秒数(≥1)', 'error'); return; } const loops = parseInt(loopCountInput.value, 10); if (isNaN(loops) || loops < 1) { addLog('请输入有效的循环次数(≥1)', 'error'); return; } const action = timerActionSelect.value; timerCancelled = false; if (action === 'jumpThenNext' && loops > 1) { addLog(`🚀 启动循环任务:先跳转后下一节,循环 ${loops} 次,间隔 ${seconds} 秒`, 'info'); executeJumpThenNextLoop(loops, seconds); startTimerBtn.innerHTML = ' 取消定时'; } else { if (action === 'jumpThenNext') { jumpVideoToEnd(); addLog(`已执行跳转,将在 ${seconds} 秒后自动点击观看下节视频`, 'info'); } else { addLog(`定时任务已启动,将在 ${seconds} 秒后执行 ${action === 'jump' ? '跳转到结尾' : '观看下节视频'}`, 'info'); } let remainingSeconds = seconds; timerDisplay.textContent = `${remainingSeconds}s`; startTimerBtn.innerHTML = ' 取消定时'; if (timerInterval) clearInterval(timerInterval); timerInterval = setInterval(() => { remainingSeconds -= 1; timerDisplay.textContent = `${remainingSeconds}s`; if (remainingSeconds <= 0) { clearInterval(timerInterval); timerInterval = null; if (timerCancelled) return; if (action === 'jump') jumpVideoToEnd(); else if (action === 'next') clickNextSectionButton(); else if (action === 'jumpThenNext') clickNextSectionButton(); startTimerBtn.innerHTML = ' 启动定时任务'; timerDisplay.textContent = '0s'; } }, 1000); } } startTimerBtn.addEventListener('click', startTimer); // 初始检测 setTimeout(() => { detectVideoElements(); detectCurrentTask(); detectLearningProgress(); startPopupDetection(); }, 1000); } // 工具函数 function getCurrentTime() { const now = new Date(); return `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`; } function addLog(message, type = 'info') { const logSection = document.getElementById('logSection'); if (!logSection) return; const logEntry = document.createElement('div'); logEntry.className = 'log-entry'; logEntry.innerHTML = `${getCurrentTime()} ${message}`; logSection.appendChild(logEntry); logSection.scrollTop = logSection.scrollHeight; if (logSection.children.length > 20) { logSection.removeChild(logSection.firstChild); } } function detectPlatform() { const platformIndicator = document.getElementById('platformIndicator'); const platformStatus = document.getElementById('platformStatus'); if (!platformIndicator || !platformStatus) return; const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); if (isMobile) { platformIndicator.className = 'platform-indicator platform-mobile'; platformStatus.textContent = '移动端'; addLog('检测到移动端平台', 'info'); } else { platformIndicator.className = 'platform-indicator platform-pc'; platformStatus.textContent = 'PC端'; addLog('检测到PC端平台', 'info'); } } function detectVideoElements() { const videoDetectionStatus = document.getElementById('videoDetectionStatus'); if (!videoDetectionStatus) return; const videos = document.querySelectorAll('video'); if (videos.length > 0) { videoDetectionStatus.textContent = '已找到视频'; videoDetectionStatus.className = 'status-value completed'; addLog(`找到 ${videos.length} 个视频元素`, 'success'); initVideoEventListeners(videos); } else { videoDetectionStatus.textContent = '未找到视频'; videoDetectionStatus.className = 'status-value error'; addLog('未找到视频元素', 'warning'); } } function detectCurrentTask() { const currentTaskElement = document.getElementById('currentTask'); if (!currentTaskElement) return; const taskElements = document.querySelectorAll('.videoItemName'); if (taskElements.length > 0) { let currentTask = '未知任务'; for (let element of taskElements) { if (element.classList.contains('activeClass') || element.parentElement.querySelector('.isAutoplay')) { currentTask = element.textContent.trim(); break; } } currentTaskElement.textContent = currentTask; addLog(`检测到当前任务: ${currentTask}`, 'info'); } } function detectLearningProgress() { const progressFill = document.getElementById('progressFill'); const progressText = document.getElementById('progressText'); if (!progressFill || !progressText) return; const videoItems = document.querySelectorAll('.videoItem'); if (videoItems.length > 0) { let completed = 0; let total = videoItems.length; for (let item of videoItems) { if (item.querySelector('.lastMark') || item.querySelector('.isAutoplay[src*="gif"]')) { completed++; } } const percentage = Math.round((completed / total) * 100); progressFill.style.width = `${percentage}%`; progressText.textContent = `已完成 ${completed}/${total} 个任务 (${percentage}%)`; addLog(`学习进度: ${completed}/${total} (${percentage}%)`, 'info'); } } function initVideoEventListeners(videos) { videos.forEach((video, index) => { video.addEventListener('play', function() { addLog(`视频 ${index + 1} 开始播放`, 'info'); document.getElementById('playbackStatus').textContent = '播放中'; document.getElementById('playbackStatus').className = 'status-value active'; }); video.addEventListener('pause', function() { addLog(`视频 ${index + 1} 已暂停`, 'warning'); document.getElementById('playbackStatus').textContent = '已暂停'; }); video.addEventListener('ended', function() { addLog(`视频 ${index + 1} 播放完成`, 'success'); if (isFullAutoMode) { setTimeout(() => handleVideoEndAutomation(), 2000); } }); }); } function jumpVideoToEnd() { const videos = document.querySelectorAll('video'); if (videos.length > 0) { const video = videos[0]; if (video.duration && video.duration > 0) { video.currentTime = Math.max(0, video.duration - 1); addLog('已跳转到视频结尾', 'success'); if (video.paused) { video.play().then(() => { setTimeout(() => video.pause(), 500); }); } } else { addLog('无法获取视频时长,无法跳转到结尾', 'error'); } } else { addLog('未找到视频', 'error'); } } function clickNextSectionButton() { const nextSectionButtons = document.querySelectorAll('span, button, a, div'); let foundButton = null; for (let element of nextSectionButtons) { if (element.textContent && element.textContent.trim() === '观看下节视频') { foundButton = element; break; } } if (foundButton) { foundButton.click(); addLog('已点击"观看下节视频"按钮', 'success'); document.getElementById('popupStatus').textContent = '已处理'; document.getElementById('popupStatus').className = 'status-value completed'; setTimeout(() => { detectCurrentTask(); detectLearningProgress(); }, 1000); return true; } else { addLog('未找到"观看下节视频"按钮', 'warning'); document.getElementById('popupStatus').textContent = '未找到按钮'; document.getElementById('popupStatus').className = 'status-value error'; return false; } } function startPopupDetection() { const popupCheckInterval = setInterval(() => { const nextSectionButtons = document.querySelectorAll('span, button, a, div'); let foundPopup = false; for (let element of nextSectionButtons) { if (element.textContent && element.textContent.trim() === '观看下节视频') { foundPopup = true; break; } } if (foundPopup) { document.getElementById('popupStatus').textContent = '检测到弹窗'; document.getElementById('popupStatus').className = 'status-value active'; if (isFullAutoMode) { addLog('检测到弹窗,自动点击"观看下节视频"', 'info'); clickNextSectionButton(); } } else { document.getElementById('popupStatus').textContent = '未检测到弹窗'; document.getElementById('popupStatus').className = 'status-value'; } }, 2000); setTimeout(() => clearInterval(popupCheckInterval), 600000); } function startRealAutomation() { addLog('开始播放视频...', 'info'); const videos = document.querySelectorAll('video'); if (videos.length > 0) { videos[0].play().then(() => { addLog('视频开始播放', 'success'); }).catch(e => { addLog(`自动播放失败: ${e.message}`, 'error'); const playButton = document.querySelector('.xgplayer-play, [title*="播放"], .fa-play'); if (playButton) { playButton.click(); addLog('已通过点击播放按钮开始播放', 'info'); } }); } else { addLog('未找到可播放的视频', 'error'); } } function startFullAutoMode() { if (isFullAutoMode) return; isFullAutoMode = true; document.getElementById('autoStatus').textContent = '全自动运行中'; document.getElementById('autoStatus').className = 'status-value active'; addLog('🚀 启动全自动学习模式', 'success'); autoCheckInterval = setInterval(() => { checkPageStateAndAutoProcess(); }, 3000); checkPageStateAndAutoProcess(); } function stopFullAutoMode() { if (!isFullAutoMode) return; isFullAutoMode = false; document.getElementById('autoStatus').textContent = '已停止'; document.getElementById('autoStatus').className = 'status-value'; if (autoCheckInterval) { clearInterval(autoCheckInterval); autoCheckInterval = null; } addLog('⏹️ 停止全自动学习模式', 'warning'); } function checkPageStateAndAutoProcess() { if (!isFullAutoMode) return; // 检查视频是否需要播放 const videos = document.querySelectorAll('video'); if (videos.length > 0 && videos[0].paused) { addLog('检测到暂停的视频,开始播放', 'info'); videos[0].play().catch(e => addLog(`自动播放失败: ${e.message}`, 'error')); } // 检查"观看下节视频"弹窗 const nextSectionButtons = document.querySelectorAll('span, button, a, div'); for (let element of nextSectionButtons) { if (element.textContent && element.textContent.trim() === '观看下节视频') { addLog('检测到弹窗,自动点击"观看下节视频"', 'info'); element.click(); break; } } } function handleVideoEndAutomation() { if (!isFullAutoMode) return; addLog('视频播放完成,自动处理下一步', 'info'); const nextSectionButtons = document.querySelectorAll('span, button, a, div'); for (let element of nextSectionButtons) { if (element.textContent && element.textContent.trim() === '观看下节视频') { element.click(); addLog('自动点击"观看下节视频"按钮', 'success'); break; } } } // 注入面板 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', injectControlPanel); } else { injectControlPanel(); } setTimeout(injectControlPanel, 1000); setTimeout(injectControlPanel, 3000); })();