更新脚本版本号至2026-06-05.7,优化提示消息文本和逻辑,提升用户体验

This commit is contained in:
竟康 2026-06-05 16:37:01 +08:00
parent 8ae3f92996
commit d5100655ee
1 changed files with 34 additions and 34 deletions

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name 平顶山学院(青书学堂)自动学习脚本 // @name 平顶山学院(青书学堂)自动学习脚本
// @namespace http://tampermonkey.net/ // @namespace http://tampermonkey.net/
// @version 2026-06-05.5 // @version 2026-06-05.7
// @description 自动进入青书学堂未完成课件,支持视频播放、文本课件停留和运行状态提示 // @description 自动进入青书学堂未完成课件,支持视频播放、文本课件停留和运行状态提示
// @author JK // @author JK
// @license MIT // @license MIT
@ -40,10 +40,10 @@
// 视频默认播放倍速;想改成 1.5 倍、3 倍可以从 Tampermonkey 菜单配置。 // 视频默认播放倍速;想改成 1.5 倍、3 倍可以从 Tampermonkey 菜单配置。
videoPlaybackRate: 2, videoPlaybackRate: 2,
// toast 默认显示时长单位毫秒4000 表示 4 秒后自动隐藏。 // 提示消息默认显示时长单位毫秒4000 表示 4 秒后自动隐藏。
toastDefaultDuration: 4000, toastDefaultDuration: 4000,
// 运行心跳提示间隔,单位秒;视频播放中、文本课件等待中都会按这个间隔提醒。 // 运行提醒间隔,单位秒;视频播放中、文本课件等待中都会按这个间隔提醒。
heartbeatSeconds: 10, heartbeatSeconds: 10,
// 课程列表最多等待多少秒;超过后认为可能请求失败,触发刷新。 // 课程列表最多等待多少秒;超过后认为可能请求失败,触发刷新。
@ -60,7 +60,7 @@
...GM_getValue(CONFIG_STORAGE_KEY, {}), ...GM_getValue(CONFIG_STORAGE_KEY, {}),
}; };
// toast 容器和样式标签的 id通常不用改除非和页面元素冲突。 // 提示消息容器和样式标签的 id通常不用改除非和页面元素冲突。
const TOAST_CONTAINER_ID = "qingshu-auto-toast-container"; const TOAST_CONTAINER_ID = "qingshu-auto-toast-container";
const TOAST_STYLE_ID = "qingshu-auto-toast-style"; const TOAST_STYLE_ID = "qingshu-auto-toast-style";
@ -71,8 +71,8 @@
location.pathname + location.pathname +
location.search; location.search;
// 创建右下角 toast 容器和样式。 // 创建右下角提示消息容器和样式。
// 每次通知都会创建一个新的 toast,所以多个通知会一起堆叠显示。 // 每次通知都会创建一个新的提示消息,所以多个通知会一起堆叠显示。
const ensureToastContainer = () => { const ensureToastContainer = () => {
let container = document.querySelector("#" + TOAST_CONTAINER_ID); let container = document.querySelector("#" + TOAST_CONTAINER_ID);
@ -141,7 +141,7 @@
return container; return container;
}; };
// 显示一条 toast,同时保留 console 输出。 // 显示一条提示消息,同时保留 console 输出。
// type 可用 info、success、warning、errorduration 是自动隐藏时间。 // type 可用 info、success、warning、errorduration 是自动隐藏时间。
const notify = ( const notify = (
message, message,
@ -175,7 +175,7 @@
const saveConfig = (patch) => { const saveConfig = (patch) => {
Object.assign(CONFIG, patch); Object.assign(CONFIG, patch);
GM_setValue(CONFIG_STORAGE_KEY, CONFIG); GM_setValue(CONFIG_STORAGE_KEY, CONFIG);
notify("配置已保存,刷新页面后完全生效", "success", 6000); notify("设置已保存,刷新页面后生效", "success", 6000);
}; };
const promptNumberConfig = (label, key, unit, currentValue, toStoredValue) => { const promptNumberConfig = (label, key, unit, currentValue, toStoredValue) => {
@ -188,7 +188,7 @@
const value = Number(input); const value = Number(input);
if (!Number.isFinite(value) || value <= 0) { if (!Number.isFinite(value) || value <= 0) {
notify("置失败请输入大于0的数字", "error", 6000); notify("置失败请输入大于0的数字", "error", 6000);
return; return;
} }
@ -209,9 +209,9 @@
); );
}); });
GM_registerMenuCommand("设置最小学习时间", () => { GM_registerMenuCommand("设置课件最小学习时间", () => {
promptNumberConfig( promptNumberConfig(
"设置最小学习时间", "设置课件最小学习时间",
"minStudySeconds", "minStudySeconds",
"分钟", "分钟",
CONFIG.minStudySeconds / 60, CONFIG.minStudySeconds / 60,
@ -219,9 +219,9 @@
); );
}); });
GM_registerMenuCommand("设置心跳提示间隔", () => { GM_registerMenuCommand("设置运行提醒间隔", () => {
promptNumberConfig( promptNumberConfig(
"设置心跳提示间隔", "设置运行提醒间隔",
"heartbeatSeconds", "heartbeatSeconds",
"秒", "秒",
CONFIG.heartbeatSeconds CONFIG.heartbeatSeconds
@ -237,9 +237,9 @@
); );
}); });
GM_registerMenuCommand("设置课程列表最大刷新次数", () => { GM_registerMenuCommand("设置课程列表自动刷新次数", () => {
promptNumberConfig( promptNumberConfig(
"设置课程列表最大刷新次数", "设置课程列表自动刷新次数",
"maxCourseListRefreshCount", "maxCourseListRefreshCount",
"次", "次",
CONFIG.maxCourseListRefreshCount, CONFIG.maxCourseListRefreshCount,
@ -247,9 +247,9 @@
); );
}); });
GM_registerMenuCommand("设置 toast 显示时长", () => { GM_registerMenuCommand("设置提示消息显示时间", () => {
promptNumberConfig( promptNumberConfig(
"设置 toast 显示时长", "设置提示消息显示时间",
"toastDefaultDuration", "toastDefaultDuration",
"秒", "秒",
CONFIG.toastDefaultDuration / 1000, CONFIG.toastDefaultDuration / 1000,
@ -257,15 +257,15 @@
); );
}); });
GM_registerMenuCommand("重置脚本配置", () => { GM_registerMenuCommand("恢复默认设置", () => {
GM_deleteValue(CONFIG_STORAGE_KEY); GM_deleteValue(CONFIG_STORAGE_KEY);
Object.assign(CONFIG, DEFAULT_CONFIG); Object.assign(CONFIG, DEFAULT_CONFIG);
notify("配置已重置,刷新页面后完全生效", "success", 6000); notify("设置已重置,刷新页面后生效", "success", 6000);
}); });
}; };
registerConfigMenus(); registerConfigMenus();
notify("插件加载完成,等待界面渲染", "info"); notify("脚本已启动,等待页面内容加载", "info");
// 等待某个 DOM 条件成立。 // 等待某个 DOM 条件成立。
// 页面里的课程列表、视频、文本课件经常是后加载的,所以不用固定延迟, // 页面里的课程列表、视频、文本课件经常是后加载的,所以不用固定延迟,
@ -398,7 +398,7 @@
document.querySelector(TEXT_SELECTOR) document.querySelector(TEXT_SELECTOR)
); );
// 把秒数格式化成“x分x秒”用于心跳提示 // 把秒数格式化成“x分x秒”用于运行提醒
const formatSeconds = (seconds) => { const formatSeconds = (seconds) => {
if (!Number.isFinite(seconds) || seconds < 0) { if (!Number.isFinite(seconds) || seconds < 0) {
return "未知"; return "未知";
@ -411,10 +411,10 @@
}; };
const onPageLoad = async () => { const onPageLoad = async () => {
notify("页面加载完成,开始执行脚本", "info"); notify("页面加载完成,脚本开始运行", "info");
if (url.includes("CourseStudy")) { if (url.includes("CourseStudy")) {
notify("进入准备阶段,等待课程列表", "info"); notify("进入课程列表页,等待课程列表加载", "info");
// 课程列表是异步渲染的,等到至少有一个课程节点后再开始遍历。 // 课程列表是异步渲染的,等到至少有一个课程节点后再开始遍历。
const items = await waitForCondition( const items = await waitForCondition(
@ -434,7 +434,7 @@
clearCourseStudyRefreshCount(); clearCourseStudyRefreshCount();
notify("获取到课程数量:" + items.length, "success"); notify("已加载课程数量:" + items.length, "success");
// 从上到下找到第一个“没学过”或“学习不足配置时长”的课件并进入。 // 从上到下找到第一个“没学过”或“学习不足配置时长”的课件并进入。
for (const item of items) { for (const item of items) {
@ -442,7 +442,7 @@
const mark = item.querySelector(".study_being"); const mark = item.querySelector(".study_being");
const studiedSeconds = mark ? parseStudySeconds(mark.innerText) : 0; const studiedSeconds = mark ? parseStudySeconds(mark.innerText) : 0;
notify( notify(
"点击未完成学习时长的视频" + "进入未完成学习时长的课件" +
item.querySelector(".title").innerText + item.querySelector(".title").innerText +
",已学习:" + ",已学习:" +
studiedSeconds + studiedSeconds +
@ -454,9 +454,9 @@
return; return;
} }
} }
notify("所有视频均已播放完毕,结束脚本", "success", 6000); notify("所有课件均已达到学习时长,脚本停止", "success", 6000);
} else if (url.includes("CourseShow")) { } else if (url.includes("CourseShow")) {
notify("进入学习阶段,等待课件加载", "info"); notify("进入课件页面,等待课件加载", "info");
// 等到播放页真正渲染出视频或文本课件,再决定如何处理。 // 等到播放页真正渲染出视频或文本课件,再决定如何处理。
const coursewareElement = await waitForCoursewareElement(); const coursewareElement = await waitForCoursewareElement();
@ -464,9 +464,9 @@
// 文本课件没有 video 标签,不需要播放;停留到配置的学习时长后返回列表页。 // 文本课件没有 video 标签,不需要播放;停留到配置的学习时长后返回列表页。
if (coursewareElement.matches(TEXT_SELECTOR)) { if (coursewareElement.matches(TEXT_SELECTOR)) {
notify( notify(
"检测到文本课件,等待" + "检测到文本课件,将停留" +
formatSeconds(CONFIG.minStudySeconds) + formatSeconds(CONFIG.minStudySeconds) +
"后返回准备页面", "后返回课程列表",
"warning", "warning",
6000 6000
); );
@ -478,13 +478,13 @@
if (studiedSeconds >= CONFIG.minStudySeconds) { if (studiedSeconds >= CONFIG.minStudySeconds) {
clearInterval(textInterval); clearInterval(textInterval);
notify("文本课件等待完成,返回准备页面", "success"); notify("文本课件停留完成,返回课程列表", "success");
returnToStudyPage(); returnToStudyPage();
return; return;
} }
notify( notify(
"文本课件学习中,已等待" + "文本课件学习中,已停留" +
formatSeconds(studiedSeconds) + formatSeconds(studiedSeconds) +
",剩余:" + ",剩余:" +
formatSeconds(CONFIG.minStudySeconds - studiedSeconds), formatSeconds(CONFIG.minStudySeconds - studiedSeconds),
@ -509,7 +509,7 @@
// 有些播放器会重建 video 元素,短暂找不到时继续等下一轮。 // 有些播放器会重建 video 元素,短暂找不到时继续等下一轮。
if (!video) { if (!video) {
if (!videoMissingNotified) { if (!videoMissingNotified) {
notify("视频元素暂时不可用,继续等待", "warning"); notify("正在等待视频加载", "warning");
videoMissingNotified = true; videoMissingNotified = true;
} }
return; return;
@ -518,12 +518,12 @@
if (video.paused && video.currentTime === 0) { if (video.paused && video.currentTime === 0) {
video.play(); video.play();
notify("视频未播放,开始播放视频", "success"); notify("视频已开始播放", "success");
return; return;
} }
if (video.currentTime >= video.duration - 1) { if (video.currentTime >= video.duration - 1) {
notify("视频播放结束,返回准备页面", "success"); notify("视频播放结束,返回课程列表", "success");
clearInterval(videoInterval); clearInterval(videoInterval);
returnToStudyPage(); returnToStudyPage();
} }