中国检察教育培训网络学院全自动学习课程,点击学习中心,最后进入班级即可。
当前为
// ==UserScript==
// @name 中检网自动学习
// @namespace https://github.com/chiupam
// @version 1.4
// @description 中国检察教育培训网络学院全自动学习课程,点击学习中心,最后进入班级即可。
// @author chiupam
// @match https://www.sppet.cn/portal/play.do*
// @match https://www.sppet.cn/examine/index.html*
// @icon https://www.sppet.cn/examine/data/imgs/favicon.ico
// @grant none
// @license GNU GPLv3
// ==/UserScript==
(async function () {
'use strict';
// 动态插入日志容器到页面
function createLogContainer() {
const logContainer = document.createElement('div');
logContainer.id = 'log-container';
logContainer.style.padding = '10px'; // 设置容器内部的边距为 10px
logContainer.style.backgroundColor = '#333'; // 设置背景颜色为深灰色
logContainer.style.color = '#fff'; // 设置文本颜色为白色
logContainer.style.border = '1px solid #ddd'; // 设置边框为 1px 的浅灰色实线,以区分容器和背景
logContainer.style.maxHeight = `${window.innerHeight / 3}px`; // 设置容器的最大高度为 200px
logContainer.style.maxWidth = '400px'; // 设置容器的最大宽度为 400px
logContainer.style.overflowY = 'auto'; // 当内容超过容器高度时,自动显示垂直滚动条
logContainer.style.position = 'fixed'; // 固定位置,始终显示在页面上
logContainer.style.top = `${window.innerHeight / 3}px`; // 设置容器顶部距离页面顶部三分之一窗口高度的位置
logContainer.style.right = '10px'; // 距离页面右侧10px
logContainer.style.zIndex = '1000'; // 确保在页面上层显示
document.body.appendChild(logContainer); // 将日志容器添加到页面中
return logContainer;
}
// 添加日志到日志容器
function logPage(logContainer, message) {
console.log(message); // 同时在控制台输出日志
const logEntry = document.createElement('div');
logEntry.textContent = message; // 设置日志内容
logEntry.style.whiteSpace = 'nowrap'; // 禁止换行
logEntry.style.overflow = 'hidden'; // 超出部分隐藏
logEntry.style.textOverflow = 'ellipsis'; // 超出部分显示省略号
logContainer.appendChild(logEntry); // 将日志内容添加到日志容器中
logContainer.scrollTop = logContainer.scrollHeight; // 自动滚动到容器底部
}
// 格式化日期
function formatDate() {
// 获取 UTC 时间的毫秒数,并加上 8 小时的毫秒数 (8 * 60 * 60 * 1000)
const offsetMilliseconds = 8 * 60 * 60 * 1000;
const beijingTime = new Date(new Date().getTime() + offsetMilliseconds);
// 格式化为 YYYY-MM-DD HH:MM:SS
return beijingTime.toISOString().replace('T', ' ').split('.')[0];
}
// 获取课程列表
function setupStudyControls(logContainer, course, progress, courseName) {
let count = 0; // 用于计数已完成课程的数量
progress.forEach(element => {if (parseFloat(element.textContent.trim()) === 100) count++}); // 如果课程进度为100,计数加1
if (count < progress.length) { // 如果有未完成的课程
const division = `${count}/${progress.length}` // 计算已完成课程的数量和总课程数量
const percentage = `${count / progress.length * 100}%` // 计算已完成课程的百分比
logPage(logContainer, `总课程完成进度: ${division} (${percentage})`);
// 遍历所有课程,找到未完成的课程并点击继续学习按钮
for (let i = 0; i < progress.length; i++) {
logPage(logContainer, `${courseName[i].textContent.trim()}`); // 输出课程名称
let progressFloat = parseFloat(progress[i].textContent.trim()); // 课程进度
if (progressFloat < 100) {
logPage(logContainer, `上述课程进度: ${progressFloat}%,${progressFloat === 0 ? '开始' : '继续'}学习`);
logPage(logContainer, `若未弹出新窗口, 请检查是否被浏览器拦截`); // 新窗口有可能被拦截, 提示一下用户
course[i].click(); // 点击继续学习按钮
break; // 找到并点击按钮后,停止遍历
} else {
logPage(logContainer, `上述课程已学完, 跳过`);
}
}
} else {
logPage(logContainer, '所有课程已完成');
}
}
// 针对视频元素进行特殊处理
function setupVideoControls(video) {
// video.play().catch(); // 播放视频(注释掉是因为只要点击 "开始学习" 或 "继续学习" 按钮就行, 无需程序干预)
video.muted = true; // 静音视频(必须保留的原因是, 不先行静音就无法使事件监听器正常运行)
video.addEventListener('pause', () => {video.play().catch()}); // 事件监听器:视频暂停时自动恢复播放
video.addEventListener('volumechange', () => {video.muted = true}); // 事件监听器:视频音量变化时强制静音
const intervalChoise = setInterval(function() {
const choise = document.querySelector('.user_choise'); // 获取选项元素
if (choise) {
choise.click(); // 点击 "开始学习" 或 "继续学习" 按钮
clearInterval(intervalChoise); // 停止轮询
}
}, 100); // 每隔0.1秒检查一次
}
// 在播放页面执行以下操作
if (window.location.href.includes('play.do')) {
const logContainer = createLogContainer(); // 创建日志容器
logPage(logContainer, `程序执行时间: ${formatDate()}`);
let video; // 声明视频变量
const intervalVideo = setInterval(function() {
if (!video) {
video = document.querySelector('video'); // 获取第一个视频元素
if (video) {
logPage(logContainer, '找到视频, 开始监控学习进度');
logPage(logContainer, '开始播放视频, 开启静音');
setupVideoControls(video); // 设置视频控制
clearInterval(intervalVideo); // 停止轮询
} else {
logPage(logContainer, '未找到视频, 等待加载...');
}
}
}, 1500); // 每1.5秒一次URL
} else {
const logContainer = createLogContainer(); // 创建日志容器
logPage(logContainer, `程序执行时间: ${formatDate()}`);
let hasLoggedMessage = false; // 初始化一个变量控制日志框体输出
const checkLogin = setInterval(function() {
const login = document.querySelector('.login_btn'); // 获取登录元素
if (login.textContent.trim() === "登录") {
if (!hasLoggedMessage) {
logPage(logContainer, `请先登录, 再进行后续的操作`); // 提示用户下一步的操作
hasLoggedMessage = true; // 修改变量, 不让上述提示继续输出到日志框体中
}
} else {
logPage(logContainer, `请点击学习中心, 进入需要学习的班级`); // 进一步提示用户下一步的操作
clearInterval(checkLogin); // 停止轮询
}
}, 1000); // 每隔1秒检查登录状态
const checkInterval = setInterval(function() {
// console.log(`${formatDate()} 请点击学习中心, 进入需要学习的班级`)
if (window.location.href.includes('stady_detail')) {
const intervalId = setInterval(function() {
const course = document.querySelectorAll('.btn'); // 获取所有继续学习的按钮元素
const progress = document.querySelectorAll('.el-progress__text'); // 获取所有进度条的元素
const courseName = document.querySelectorAll('.text_title.oneEllipsis'); // 获取所有课程的名称
if (progress.length === 0) location.reload(); // 如果 progress.length 等于0, 刷新页面
setupStudyControls(logContainer, course, progress, courseName);
clearInterval(intervalId); // 停止轮询
}, 3000); // 每隔3秒轮询一次
clearInterval(checkInterval); // 停止检查
}
}, 1000); // 每隔1秒检查一次URL
}
})();
// 在第一个页面中,添加以下脚本用于检测 localStorage 变化并执行刷新
if (window.location.href.includes('stady_detail')) {
window.addEventListener('storage', function(event) {
if (event.key === 'refresh' && event.newValue === 'true') {
localStorage.removeItem('refresh');
location.reload();
}
});
}