您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动完成当前课程并跳转下一节
// ==UserScript== // @name 广西高等学校师资培训中心-自动学习课程 // @namespace http://tampermonkey.net/ // @version 1.00 // @description 自动完成当前课程并跳转下一节 // @author RrOrange // @match *://gxgs.study.gspxonline.com/* // @grant GM_setValue // @grant GM_getValue // @license MIT // @icon https://s2.loli.net/2025/02/01/mphjJoCDTgaYFLZ.png // @icon64 https://s2.loli.net/2025/02/01/mphjJoCDTgaYFLZ.png // ==/UserScript== (function() { 'use strict'; // 用户配置 const config = { playbackSpeed: GM_getValue('playbackSpeed', 3), // 默认3倍速 refreshInterval: GM_getValue('refreshInterval', 5) * 60 * 1000, // 默认5分钟刷新一次 progressThreshold: 100, // 进度阈值改为100% maxCheckTimes: 5, // 最大检查次数 autoClickStudy: GM_getValue('autoClickStudy', true), // 自动点击继续学习 autoExpand: GM_getValue('autoExpand', false) // 自动展开所有小节 }; // 生成标签页唯一ID function generateTabId() { return 'tab_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); } // 获取当前标签页ID function getTabId() { let tabId = sessionStorage.getItem('courseTabId'); if (!tabId) { tabId = generateTabId(); sessionStorage.setItem('courseTabId', tabId); } return tabId; } // 获取最后刷新时间 function getLastRefresh() { const tabId = getTabId(); const lastRefresh = GM_getValue(`lastRefresh_${tabId}`); // 如果没有上次刷新时间,设置为当前时间减去一个很小的值,确保倒计时立即开始 return lastRefresh || (Date.now() - 1000); } // 设置最后刷新时间 function setLastRefresh(time) { const tabId = getTabId(); GM_setValue(`lastRefresh_${tabId}`, time); } // 清理过期的标签页刷新时间(可选) function cleanupOldTabs() { const now = Date.now(); const allKeys = Object.keys(GM_getValue('', {})); allKeys.forEach(key => { if (key.startsWith('lastRefresh_')) { const lastRefresh = GM_getValue(key); if (now - lastRefresh > 24 * 60 * 60 * 1000) { // 24小时后清理 GM_deleteValue(key); } } }); } // 修改添加设置界面函数 function addSettingsUI() { const container = document.createElement('div'); container.style.cssText = ` position: fixed; top: 10px; right: 10px; background: rgba(0, 0, 0, 0.7); padding: 10px; border-radius: 5px; color: white; z-index: 9999; display: flex; align-items: center; gap: 10px; font-size: 14px; `; // 播放速度设置区域 const speedContainer = document.createElement('div'); speedContainer.style.display = 'flex'; speedContainer.style.alignItems = 'center'; speedContainer.style.gap = '5px'; const speedLabel = document.createElement('label'); speedLabel.textContent = '播放速度:'; const speedInput = document.createElement('input'); speedInput.type = 'number'; speedInput.min = '0.1'; speedInput.max = '16'; speedInput.step = '0.1'; speedInput.value = config.playbackSpeed; speedInput.style.cssText = ` width: 50px; padding: 2px 5px; border: 1px solid #ccc; border-radius: 3px; background: rgba(255, 255, 255, 0.9); color: #333; `; // 刷新时间设置区域 const refreshContainer = document.createElement('div'); refreshContainer.style.cssText = ` display: flex; align-items: center; gap: 5px; margin-left: 15px; padding-left: 15px; border-left: 1px solid rgba(255, 255, 255, 0.3); `; const refreshLabel = document.createElement('label'); refreshLabel.textContent = '刷新间隔(分钟):'; const refreshInput = document.createElement('input'); refreshInput.type = 'number'; refreshInput.min = '1'; refreshInput.max = '60'; refreshInput.step = '1'; refreshInput.value = config.refreshInterval / (60 * 1000); refreshInput.style.cssText = ` width: 50px; padding: 2px 5px; border: 1px solid #ccc; border-radius: 3px; background: rgba(255, 255, 255, 0.9); color: #333; `; const saveBtn = document.createElement('button'); saveBtn.textContent = '保存'; saveBtn.style.cssText = ` padding: 2px 8px; background: #4CAF50; border: none; border-radius: 3px; color: white; cursor: pointer; `; // 当前速度显示 const currentSpeed = document.createElement('span'); currentSpeed.style.marginLeft = '10px'; currentSpeed.textContent = `当前: ${config.playbackSpeed}x`; // 倒计时显示 const timeDisplay = document.createElement('span'); timeDisplay.style.marginLeft = '15px'; timeDisplay.style.borderLeft = '1px solid rgba(255, 255, 255, 0.3)'; timeDisplay.style.paddingLeft = '15px'; updateTimeDisplay(timeDisplay); saveBtn.onclick = () => { const newSpeed = parseFloat(speedInput.value); const newInterval = parseInt(refreshInput.value); if (newSpeed >= 0.1 && newSpeed <= 16 && newInterval >= 1 && newInterval <= 60) { const speedChanged = newSpeed !== config.playbackSpeed; const intervalChanged = newInterval !== config.refreshInterval / (60 * 1000); // 保存播放速度 config.playbackSpeed = newSpeed; GM_setValue('playbackSpeed', newSpeed); setVideoSpeed(newSpeed); currentSpeed.textContent = `当前: ${newSpeed}x`; // 保存刷新间隔 config.refreshInterval = newInterval * 60 * 1000; GM_setValue('refreshInterval', newInterval); setLastRefresh(Date.now()); // 重置刷新时间 // 如果设置有改变,提示用户并刷新页面 if (speedChanged || intervalChanged) { alert('设置已保存,页面将自动刷新以应用新设置'); window.location.reload(); } else { alert('设置已保存'); } } else { alert('请输入有效的数值\n播放速度: 0.1-16\n刷新间隔: 1-60分钟'); } }; speedContainer.appendChild(speedLabel); speedContainer.appendChild(speedInput); refreshContainer.appendChild(refreshLabel); refreshContainer.appendChild(refreshInput); container.appendChild(speedContainer); container.appendChild(refreshContainer); container.appendChild(saveBtn); container.appendChild(currentSpeed); container.appendChild(timeDisplay); document.body.appendChild(container); return timeDisplay; } // 更新倒计时显示并检查是否需要刷新 function updateTimeDisplay(element) { const now = Date.now(); const lastRefresh = getLastRefresh(); const nextRefresh = lastRefresh + config.refreshInterval; const remaining = Math.max(0, nextRefresh - now); // 更新倒计时显示 const minutes = Math.floor(remaining / 60000); const seconds = Math.floor((remaining % 60000) / 1000); element.textContent = `下次刷新: ${minutes}:${seconds.toString().padStart(2, '0')}`; // 如果剩余时间小于等于0,且当前页面没有在刷新中 if (remaining <= 0 && !window.isRefreshing) { window.isRefreshing = true; console.log('倒计时结束,准备刷新页面...'); setTimeout(() => { refreshPage(); }, 100); return; } } // 设置视频播放速度 function setVideoSpeed(speed) { const video = document.querySelector('video'); if (video) { video.playbackRate = speed; } } // 刷新页面 function refreshPage() { if (window.isRefreshing) { console.log('正在刷新页面...'); setLastRefresh(Date.now()); window.location.reload(); } } // 等待播放器加载完成 function waitForPlayer() { return new Promise(resolve => { const checkPlayer = setInterval(() => { const player = document.querySelector('#aliplayer'); if (player) { clearInterval(checkPlayer); resolve(player); } }, 1000); }); } // 展开所有章节 function expandAllSections() { const expandIcons = document.querySelectorAll('.section .title.section-name i.icon-plus'); expandIcons.forEach(icon => { icon.click(); }); } // 获取所有课程的进度信息 function getAllCoursesProgress() { const courses = Array.from(document.querySelectorAll('.resource li')); return courses.map(course => { const progressIcon = course.querySelector('.learn-status'); const progressText = progressIcon ? progressIcon.textContent : '0%'; const progress = parseInt(progressText); return { element: course, progress: isNaN(progress) ? 0 : progress, title: course.getAttribute('title') }; }); } // 检查是否所有课程都已完成 function checkAllCoursesCompleted() { // 先展开所有章节 expandAllSections(); // 等待一下确保章节都已展开 return new Promise(resolve => { setTimeout(() => { const courses = getAllCoursesProgress(); const totalCourses = courses.length; const completedCourses = courses.filter(c => c.progress >= 100).length; console.log(`课程完成情况: ${completedCourses}/${totalCourses}`); resolve(completedCourses === totalCourses); }, 500); // 等待500ms确保章节展开完成 }); } // 修改查找下一个需要学习的课程函数 async function findNextCourseToLearn() { const courses = getAllCoursesProgress(); const currentCourse = document.querySelector('.resource li.active'); const currentIndex = courses.findIndex(c => c.element === currentCourse); // 统计完成情况 const totalCourses = courses.length; const completedCourses = courses.filter(c => c.progress >= 100).length; console.log(`课程完成情况: ${completedCourses}/${totalCourses}`); // 检查是否真的所有课程都完成了 const allCompleted = await checkAllCoursesCompleted(); if (allCompleted) { alert('恭喜!所有课程已学习完成!'); return null; } // 优先查找未完成的课程(进度小于100%) let nextUnfinished = courses.find((course, index) => index > currentIndex && course.progress < 100 ); // 如果当前位置后面没有未完成的课程,从头开始查找 if (!nextUnfinished) { nextUnfinished = courses.find(course => course.progress < 100); } // 如果找到未完成的课程 if (nextUnfinished) { console.log(`跳转到未完成课程: ${nextUnfinished.title} (进度: ${nextUnfinished.progress}%)`); return nextUnfinished.element; } return null; } // 修改跳转到下一节的函数 async function goToNextSection() { const nextCourse = await getNextCourseLink(); if (nextCourse) { nextCourse.click(); return true; } else { const allCompleted = await checkAllCoursesCompleted(); if (allCompleted) { console.log('所有课程已学习完成'); alert('恭喜!所有课程已学习完成!'); } else { // 当前课程未完成,继续学习 ensureVideoPlaying(); } return false; } } // 修改原有的getNextCourseLink函数 async function getNextCourseLink() { // 先展开所有章节 expandAllSections(); // 获取当前激活的课程 const activeCourse = document.querySelector('.resource li.active'); if (!activeCourse) return null; // 获取当前课程进度 const currentProgress = checkProgress(); // 如果当前课程未完成(进度小于100%),继续学习当前课程 if (currentProgress < 100) { return null; } // 查找下一个需要学习的课程 return await findNextCourseToLearn(); } // 检查学习进度 function checkProgress() { // 检查当前课程的进度标签 const activeLesson = document.querySelector('.resource li.active'); if (!activeLesson) return 0; const progressIcon = activeLesson.querySelector('.learn-status'); if (progressIcon) { const progressText = progressIcon.textContent; // 提取百分比数字 const progress = parseInt(progressText); return isNaN(progress) ? 0 : progress; } return 0; } // 检查并确保视频在播放 function ensureVideoPlaying() { const video = document.querySelector('video'); if (video) { if (video.paused) { clickPlayButton(); } // 设置播放速度 setVideoSpeed(config.playbackSpeed); } } // 点击播放按钮 function clickPlayButton() { // 查找大播放按钮 const bigPlayBtn = document.querySelector('.prism-big-play-btn'); if (bigPlayBtn && bigPlayBtn.style.display !== 'none') { bigPlayBtn.click(); return true; } // 查找控制栏播放按钮 const playBtn = document.querySelector('.prism-play-btn'); if (playBtn) { playBtn.click(); return true; } return false; } // 添加开关按钮 function addToggleButtons(container) { // 添加分隔线 const divider = document.createElement('div'); divider.style.cssText = ` border-left: 1px solid rgba(255, 255, 255, 0.3); margin: 0 15px; height: 20px; `; // 自动点击开关 const clickToggle = document.createElement('div'); clickToggle.style.cssText = ` display: flex; align-items: center; gap: 5px; `; const clickCheckbox = document.createElement('input'); clickCheckbox.type = 'checkbox'; clickCheckbox.checked = config.autoClickStudy; clickCheckbox.style.cursor = 'pointer'; const clickLabel = document.createElement('label'); clickLabel.textContent = '自动点击继续学习'; clickLabel.style.cursor = 'pointer'; clickCheckbox.onchange = (e) => { config.autoClickStudy = e.target.checked; GM_setValue('autoClickStudy', config.autoClickStudy); }; // 展开/收缩开关 const expandToggle = document.createElement('div'); expandToggle.style.cssText = ` display: flex; align-items: center; gap: 5px; margin-left: 15px; `; const expandBtn = document.createElement('button'); expandBtn.textContent = config.autoExpand ? '收缩所有' : '展开所有'; expandBtn.style.cssText = ` padding: 2px 8px; background: #2196F3; border: none; border-radius: 3px; color: white; cursor: pointer; `; expandBtn.onclick = () => { config.autoExpand = !config.autoExpand; GM_setValue('autoExpand', config.autoExpand); expandBtn.textContent = config.autoExpand ? '收缩所有' : '展开所有'; toggleAllSections(config.autoExpand); }; clickToggle.appendChild(clickCheckbox); clickToggle.appendChild(clickLabel); expandToggle.appendChild(expandBtn); container.appendChild(divider); container.appendChild(clickToggle); container.appendChild(expandToggle); } // 展开/收缩所有小节 function toggleAllSections(expand) { const sections = document.querySelectorAll('.section .title.section-name'); sections.forEach(section => { const icon = section.querySelector('i.iconfont'); if (icon) { const isExpanded = icon.classList.contains('icon-minus'); if ((expand && !isExpanded) || (!expand && isExpanded)) { section.click(); } } }); } // 修改检查并点击"继续学习"按钮函数 function checkAndClickStudyButton() { // 如果自动点击已关闭,直接返回 if (!config.autoClickStudy) { return; } let checkCount = 0; let hasClicked = false; const courseUrls = [ 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1068', 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1065', 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1067', 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1066', 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1069', 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1070', 'http://gxgs.study.gspxonline.com/resource/index?route=/study/course/1071', ]; // 检查当前URL是否匹配课程URL if (!courseUrls.some(url => window.location.href.includes(url))) { return; } const checkInterval = setInterval(() => { if (hasClicked || checkCount >= config.maxCheckTimes) { clearInterval(checkInterval); return; } const studyButton = document.querySelector('a.btn.btn-primary.btn-study'); if (studyButton && studyButton.textContent.trim() === '继续学习') { console.log('找到继续学习按钮,准备点击...'); studyButton.click(); hasClicked = true; clearInterval(checkInterval); } checkCount++; if (checkCount >= config.maxCheckTimes) { console.log('已达到最大检查次数,停止检查'); } }, 1000); // 每秒检查一次 } // 主要逻辑 async function main() { // 重置刷新标记 window.isRefreshing = false; // 清理过期标签页数据 cleanupOldTabs(); // 检查是否需要立即刷新 const now = Date.now(); const lastRefresh = getLastRefresh(); if (now - lastRefresh >= config.refreshInterval) { console.log('检测到需要刷新...'); refreshPage(); return; } // 如果是首次加载,设置初始刷新时间 if (!GM_getValue(`lastRefresh_${getTabId()}`)) { setLastRefresh(Date.now()); } // 添加设置界面 const timeDisplay = addSettingsUI(); // 添加开关按钮 addToggleButtons(timeDisplay.parentElement); // 检查并点击"继续学习"按钮 checkAndClickStudyButton(); // 等待播放器加载 const player = await waitForPlayer(); // 监听视频播放结束事件 player.addEventListener('ended', goToNextSection); // 定期检查进度和播放状态 setInterval(() => { const progress = checkProgress(); console.log('当前进度:', progress + '%'); if (progress >= config.progressThreshold) { goToNextSection(); } else { // 如果进度小于100%,确保视频在播放 ensureVideoPlaying(); } }, 5000); // 每5秒检查一次进度 // 定期更新倒计时并检查是否需要刷新 setInterval(() => { updateTimeDisplay(timeDisplay); }, 1000); // 初始自动播放视频 ensureVideoPlaying(); } // 启动脚本 main(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址