此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/537083/1595102/%E5%B2%90%E9%BB%84%E5%A4%A9%E4%BD%BF%E5%88%B7%E8%AF%BE%E5%8A%A9%E6%89%8B%20-%20%E8%A7%86%E9%A2%91%E6%92%AD%E6%94%BE%E6%A8%A1%E5%9D%97.js
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
(我已經安裝了使用者樣式管理器,讓我安裝!)
// ==UserScript==
// @name 岐黄天使刷课助手 - 视频播放模块
// @namespace http://tampermonkey.net/qhtx-modules
// @version 1.3.1
// @description 岐黄天使刷课助手的视频播放控制模块,负责视频的自动播放、暂停和状态管理。
// @author AI助手
// ==/UserScript==
// 视频播放模块
(function() {
'use strict';
// 切换自动学习状态
window.toggleAutoLearn = function() {
// 获取当前状态,如果GM_getValue不可用,则使用localStorage
let isRunning;
if (typeof GM_getValue !== 'undefined') {
isRunning = GM_getValue('qh-is-running', false);
} else {
isRunning = localStorage.getItem('qh-is-running') === 'true';
}
// 切换状态
isRunning = !isRunning;
// 保存新状态
if (typeof GM_setValue !== 'undefined') {
GM_setValue('qh-is-running', isRunning);
} else {
localStorage.setItem('qh-is-running', isRunning.toString());
}
console.log('切换自动学习状态:', isRunning ? '开始' : '暂停');
if (isRunning) {
// 开始自动学习
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('自动学习已开始');
// 设置定时器,定期检查和播放视频
if (!window.qh.autoPlayInterval) {
window.qh.autoPlayInterval = setInterval(autoPlayVideo, 5000);
// 立即执行一次
setTimeout(autoPlayVideo, 500);
}
// 尝试播放所有视频
setTimeout(() => {
try {
// 直接调用视频播放函数
const videos = document.querySelectorAll('video');
if (videos.length > 0) {
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('找到视频,尝试播放');
console.log('找到视频,尝试播放');
videos.forEach(video => {
// 设置视频属性
video.loop = true;
video.muted = true;
video.playbackRate = 2.0;
// 尝试播放视频
try {
const playPromise = video.play();
if (playPromise !== undefined) {
playPromise.then(() => {
console.log('视频播放成功');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('视频播放成功');
}).catch(error => {
console.error('视频播放失败:', error);
// 尝试使用其他方法播放
setTimeout(() => {
try {
video.play();
} catch (e) {
console.error('重试播放失败:', e);
}
}, 1000);
});
}
} catch (e) {
console.error('播放视频出错:', e);
}
});
}
// 检查iframe中的视频
const frames = document.querySelectorAll('iframe');
for (const frame of frames) {
try {
const frameDoc = frame.contentDocument || frame.contentWindow.document;
const frameVideos = frameDoc.querySelectorAll('video');
if (frameVideos.length > 0) {
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('在iframe中找到视频,尝试播放');
console.log('在iframe中找到视频,尝试播放');
frameVideos.forEach(video => {
// 设置视频属性
video.loop = false; // 不循环播放
video.muted = true;
// 不修改播放速度,使用默认速度
// 尝试播放视频
try {
const playPromise = video.play();
if (playPromise !== undefined) {
playPromise.then(() => {
console.log('iframe视频播放成功');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('iframe视频播放成功');
}).catch(error => {
console.error('iframe视频播放失败:', error);
// 尝试使用其他方法播放
setTimeout(() => {
try {
video.play();
} catch (e) {
console.error('重试播放iframe视频失败:', e);
}
}, 1000);
});
}
} catch (e) {
console.error('播放iframe视频出错:', e);
}
});
}
} catch (e) {
console.error('无法访问iframe内容:', e);
}
}
} catch (e) {
console.error('播放视频出错:', e);
}
}, 1000);
} else {
// 暂停自动学习
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('自动学习已暂停');
// 清除定时器
if (window.qh.autoPlayInterval) {
clearInterval(window.qh.autoPlayInterval);
window.qh.autoPlayInterval = null;
}
// 暂停所有视频
pauseAllVideos();
}
// 更新按钮状态
if(window.qh && window.qh.updateButtonStatus) window.qh.updateButtonStatus();
};
// 播放iframe中的视频
window.playAllVideos = function() {
// 尝试播放iframe中的视频
const frames = document.querySelectorAll('iframe');
frames.forEach(frame => {
try {
const frameDoc = frame.contentDocument || frame.contentWindow.document;
const frameVideos = frameDoc.querySelectorAll('video');
frameVideos.forEach(video => {
// 设置视频属性
video.loop = false; // 不循环播放
video.muted = true;
// 不修改播放速度,使用默认速度
// 尝试播放视频
try {
const playPromise = video.play();
// 处理播放承诺
if (playPromise !== undefined) {
playPromise.then(() => {
console.log('iframe视频播放成功');
}).catch(error => {
console.error('iframe视频播放失败:', error);
// 尝试使用其他方法播放
setTimeout(() => {
try {
video.play();
} catch (e) {
console.error('重试播放iframe视频失败:', e);
}
}, 1000);
});
}
} catch (e) {
console.error('播放iframe视频出错:', e);
}
});
} catch (e) {
console.error('无法访问iframe内容:', e);
}
});
};
// 暂停所有视频
window.pauseAllVideos = function() {
document.querySelectorAll('video').forEach(video => video.pause());
const frames = document.querySelectorAll('iframe');
frames.forEach(frame => {
try {
const frameDoc = frame.contentDocument || frame.contentWindow.document;
frameDoc.querySelectorAll('video').forEach(video => video.pause());
} catch (e) { /*忽略*/ }
});
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('所有视频已暂停');
console.log('所有视频已暂停');
};
// 主要功能:自动播放视频
window.autoPlayVideo = function() {
console.log('[自动播放] 检查视频...');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('自动播放检查中...');
let videoPlayed = false;
const videos = Array.from(document.querySelectorAll('video:not([data-played-by-qh])'));
const frames = document.querySelectorAll('iframe');
for (const frame of frames) {
try {
const frameDoc = frame.contentDocument || frame.contentWindow.document;
videos.push(...Array.from(frameDoc.querySelectorAll('video:not([data-played-by-qh])')));
} catch (e) { console.warn('无法访问iframe进行视频搜索:', e); }
}
if (videos.length === 0) {
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('未找到可播放视频');
console.log('[自动播放] 未找到新的视频。');
// 如果没有视频,并且列表存在,尝试导航到下一课
if (window.qh && window.qh.courseList && window.qh.courseList.length > 0 && typeof navigateToNextCourse === 'function') {
console.log('[自动播放] 尝试导航到列表中的下一课。');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('尝试导航下一课');
navigateToNextCourse();
}
return;
}
for (const video of videos) {
if (video.paused || video.ended) {
console.log('[自动播放] 找到已暂停/结束的视频,尝试播放:', video);
video.loop = false; // 确保非循环,以便ended事件触发
video.muted = true;
// video.playbackRate = 2.0; // 可选:根据全局配置设定播放速率
const playPromise = video.play();
if (playPromise !== undefined) {
playPromise.then(() => {
console.log('[自动播放] 视频开始播放:', video);
video.setAttribute('data-played-by-qh', 'true'); // 标记已由脚本处理
updateVideoListeners(video); // 添加或更新事件监听器
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('视频播放中...');
if(window.qh && window.qh.updateCurrentCourse) window.qh.updateCurrentCourse(detectCurrentCourseInHierarchy(video) || '视频课程');
videoPlayed = true;
}).catch(error => {
console.error('[自动播放] 播放视频失败:', error, video);
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('视频播放失败');
});
}
if (videoPlayed) break; // 每次只尝试播放一个新视频
}
}
if (!videoPlayed) {
console.log('[自动播放] 未发现可操作的新视频。');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('无新视频操作');
}
};
// 查找并点击未完成的课程
window.findAndClickUnfinishedCourse = function(doc) {
// 查找未完成的视频链接
const unfinishedLinks = doc.querySelectorAll('.append-plugin-tip > a, .content-unstart a, .content-learning a');
if (unfinishedLinks.length > 0) {
updateStatus('找到未完成的课程,即将播放');
// 收集所有课程链接,用于上一课/下一课导航
if (typeof collectCourseLinks === 'function') {
collectCourseLinks(doc);
}
// 点击第一个未完成的课程
try {
unfinishedLinks[0].click();
} catch (e) {
console.error('点击未完成课程失败:', e);
updateStatus('点击未完成课程失败');
}
} else {
updateStatus('未找到未完成的课程,可能已全部完成');
// 检查是否有课程列表
const coursesInList = doc.querySelectorAll('.mycourse-row');
if (coursesInList.length > 0) {
// 收集课程列表
if (typeof collectCoursesFromList === 'function') {
collectCoursesFromList(doc);
}
// 遍历课程列表,查找未完成的课程
for (let i = 0; i < coursesInList.length; i++) {
const courseRow = coursesInList[i];
const courseState = courseRow.innerText.includes('未完成') || courseRow.innerText.includes('未开始');
if (courseState) {
updateStatus('在课程列表中找到未完成课程,即将打开');
try {
const courseLink = courseRow.querySelector('a');
if (courseLink) {
courseLink.click();
break;
}
} catch (e) {
console.error('点击课程列表中的未完成课程失败:', e);
}
}
}
}
}
};
// 检查进度指示器
window.checkProgressIndicator = function(doc) {
// 首先尝试从<div class="jc_hd w-80">当前视频已观看时长:<span id="schedule">100%</span>获取进度
const scheduleElement = doc.getElementById('schedule');
if (scheduleElement) {
const progressText = scheduleElement.textContent.trim();
const progressMatch = progressText.match(/(\d+)%/);
if (progressMatch && progressMatch[1]) {
const progress = parseInt(progressMatch[1]);
console.log('从schedule元素获取到进度:', progress + '%');
updateProgress(progress);
// 如果进度为100%,自动切换到下一个课程
if (progress === 100) {
// 防止重复触发
if (window.qh.isNavigating) {
console.log('导航已在进行中,忽略进度100%事件');
return;
}
console.log('当前视频已完成,准备切换到下一个课程');
updateStatus('视频播放完成,准备切换到下一个课程');
// 设置导航状态标志
window.qh.isNavigating = true;
// 延迟一秒后切换到下一课
setTimeout(() => {
// 使用navigateToNextCourse函数切换到下一课
if (typeof navigateToNextCourse === 'function') {
navigateToNextCourse();
}
// 5秒后重置导航状态标志,避免卡死
setTimeout(() => {
window.qh.isNavigating = false;
}, 5000);
}, 1000);
}
return;
}
}
// 如果没有找到schedule元素,尝试其他进度指示器
const progressIndicator = doc.getElementById('realPlayVideoTime');
if (progressIndicator) {
const progress = parseInt(progressIndicator.innerText);
updateProgress(progress);
// 如果进度为100%,自动切换到下一个课程
if (progress === 100) {
// 防止重复触发
if (window.qh.isNavigating) {
console.log('导航已在进行中,忽略进度100%事件');
return;
}
console.log('当前视频已完成,准备切换到下一个课程');
updateStatus('视频播放完成,准备切换到下一个课程');
// 设置导航状态标志
window.qh.isNavigating = true;
// 延迟一秒后切换到下一课
setTimeout(() => {
// 使用navigateToNextCourse函数切换到下一课
if (typeof navigateToNextCourse === 'function') {
navigateToNextCourse();
}
// 5秒后重置导航状态标志,避免卡死
setTimeout(() => {
window.qh.isNavigating = false;
}, 5000);
}, 1000);
}
}
// 尝试查找其他可能的进度指示器
const jcHdElements = doc.querySelectorAll('.jc_hd');
for (const jcHd of jcHdElements) {
if (jcHd.textContent.includes('当前视频已观看时长')) {
const progressText = jcHd.textContent;
const progressMatch = progressText.match(/(\d+)%/);
if (progressMatch && progressMatch[1]) {
const progress = parseInt(progressMatch[1]);
console.log('从jc_hd元素获取到进度:', progress + '%');
updateProgress(progress);
// 如果进度为100%,自动切换到下一个课程
if (progress === 100) {
// 防止重复触发
if (window.qh.isNavigating) {
console.log('导航已在进行中,忽略进度100%事件');
return;
}
console.log('当前视频已完成,准备切换到下一个课程');
updateStatus('视频播放完成,准备切换到下一个课程');
// 设置导航状态标志
window.qh.isNavigating = true;
// 延迟一秒后切换到下一课
setTimeout(() => {
// 使用navigateToNextCourse函数切换到下一课
if (typeof navigateToNextCourse === 'function') {
navigateToNextCourse();
}
// 5秒后重置导航状态标志,避免卡死
setTimeout(() => {
window.qh.isNavigating = false;
}, 5000);
}, 1000);
}
return;
}
}
}
};
function updateVideoListeners(videoElement) {
if (!videoElement) return;
const qh = window.qh || {};
const onPlay = () => { if(qh.updateStatus) qh.updateStatus('视频播放中...'); };
const onPause = () => { if(qh.updateStatus) qh.updateStatus('视频已暂停'); };
const onEnded = () => handleVideoEnd(videoElement); // 直接传递videoElement
const onTimeUpdate = () => {
if (videoElement.duration && videoElement.currentTime) {
const progress = (videoElement.currentTime / videoElement.duration) * 100;
if(qh.updateProgress) qh.updateProgress(Math.round(progress));
}
};
videoElement.addEventListener('play', onPlay);
videoElement.addEventListener('pause', onPause);
videoElement.addEventListener('ended', onEnded);
videoElement.addEventListener('timeupdate', onTimeUpdate);
// 存储事件监听器以便移除
videoElement.qhListeners = { onPlay, onPause, onEnded, onTimeUpdate };
if(qh.updateStatus) qh.updateStatus('视频监听器已更新');
}
window.updateVideoListeners = updateVideoListeners;
function handleVideoEnd(videoElement) {
console.log('视频播放结束事件触发');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('视频播放完毕');
if(window.qh && window.qh.updateProgress) window.qh.updateProgress(100);
if (window.qh && window.qh.dailyLimitManager) {
window.qh.dailyLimitManager.notifyVideoWatched();
if (window.qh.dailyLimitManager.state.isLimitReached) {
console.log('[VideoPlayer] 每日上限达到,停止自动播放。');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('每日上限,停止播放');
// 如果 toggleAutoLearn 是全局的,并且当前是运行状态,则调用它来暂停
let isRunning = false;
if (typeof GM_getValue !== 'undefined') { isRunning = GM_getValue('qh-is-running', false); }
else { isRunning = localStorage.getItem('qh-is-running') === 'true'; }
if (isRunning && typeof window.toggleAutoLearn === 'function') {
window.toggleAutoLearn(); // 这会设置 isRunning 为 false 并更新UI
}
return; // 不再尝试播放下一个
}
}
// 尝试播放列表中的下一个视频或课程
if (typeof navigateToNextCourse === 'function') {
console.log('准备导航到下一课...');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('准备导航到下一课...');
setTimeout(navigateToNextCourse, 2000); // 延迟2秒再跳转
} else {
console.warn('navigateToNextCourse 函数不可用');
if(window.qh && window.qh.updateStatus) window.qh.updateStatus('无法自动导航到下一课');
}
}
window.handleVideoEnd = handleVideoEnd;
function detectCurrentCourseInHierarchy(videoElement) {
let currentElement = videoElement;
for (let i = 0; i < 5; i++) { // 向上查找5层
if (!currentElement) break;
// 尝试常见的标题类名或ID (需要根据实际网站结构调整)
const titleEl = currentElement.querySelector('.title, .course-title, #courseName, #videoName');
if (titleEl && titleEl.textContent.trim()) {
return titleEl.textContent.trim();
}
currentElement = currentElement.parentElement;
}
return null;
}
console.log('[模块加载] videoPlayer 模块已加载');
})();