// ==UserScript==
// @name 🍀广东开放大学|南方教师在线|清远市教师专业发展与管理平台|脚本使用说明:http://doc.zhanyc.cn/pages/qysjs/
// @namespace free
// @version 1.0
// @description 当前是免费版本,可免费使用解除视频暂停限制、自动换课功能。如需自动下一集、自动换课程、全自动无人值守高级功能可升级VIP版本解锁
// @author free
// @include *://*.ttcn.cn/*
// @include *://*southteacher.com/*
// @include *://*.southteacher.com/*
// @include *://*.chaoxing.com/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @run-at document-end
// @require https://scriptcat.org/lib/8488/jquery-2.2.4.min.js/jquery-2.2.4.min.js.js?sha384-rY/jv8mMhqDabXSo+UCggqKtdmBfd3qC2/KvyTDNQ6PcUJXaxK1tMepoQda4g5vB
// @antifeature payment
// @license Creative Commons
// ==/UserScript==
(function () {
let docUrl = "http://doc.zhanyc.cn/pages/qysjs/";
let freeObj = {
pageData: {
videoIndex: null
},
async init() {
console.log("%c free init", "background:rgb(0,0,0);color:#fff");
freeObj.addGlobalStyle();
freeObj.createFloatingBox();
freeObj.initDrag("#freeDragHandle", "#freeFloatingBox");
freeObj.routeByUrl();
},
addGlobalStyle() {
let css = `
@keyframes freeToastFadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes freeToastFadeOut {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(-20px); }
}
@keyframes freeProgressPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
`;
$("head").append(``);
},
routeByUrl() {
let url = location.href.toLowerCase();
if (url.includes("studyworkvideo") || url.includes("fileread") || url.includes("/ratelearning")) {
freeObj.pageVideo();
} else if (url.includes("/training/special/")) {
freeObj.pageList();
} else if (url.includes("/course/detail")) {
freeObj.pageCourseDetail();
} else if (url.includes("/learning/record")) {
freeObj.pageLearningRecord();
} else if (url.includes("/study/progress")) {
freeObj.pageStudyProgress();
}
},
async pageVideo() {
console.log("%c pageVideo", "background:rgb(0,0,0);color:#fff");
freeObj.showTips("视频播放功能已启动");
let videoCount = GM_getValue("videoPlayCount", 0);
if (videoCount >= freeObj.getVideoLimit()) {
freeObj.showVipUpgradeBox("免费额度已用完", `免费脚本可全自动学习前${freeObj.getVideoLimit()}个视频,目前免费额度已经用完,请升级VIP版本后继续使用。`);
return;
}
// 等待左侧树形列表加载
await freeObj.waitForElement('[role="treeitem"]', 60000);
await freeObj.waitTimeout(1000);
// 检查是否已完成
if ($(".logo_text1").text() == '已完成') {
freeObj.showTips("当前视频已完成", 3000);
return;
}
// 点击"继续学习"按钮启动视频播放
freeObj.clickContinueButton();
// 等待视频元素出现
await freeObj.waitForVideo();
freeObj.startVideoPlayback();
},
clickContinueButton() {
// 等待并点击"继续学习"按钮
let checkCount = 0;
let checkInterval = setInterval(() => {
let $btn = null;
$(".btn1").each((i, el) => {
if ($(el).text().trim().includes("继续学习")) {
$btn = $(el);
return false;
}
});
if ($btn != null) {
clearInterval(checkInterval);
$btn.click();
freeObj.showTips("已点击继续学习按钮");
}
checkCount++;
if (checkCount > 30) {
clearInterval(checkInterval);
}
}, 1000);
},
async waitForVideo() {
return new Promise((resolve) => {
let checkCount = 0;
let checkInterval = setInterval(() => {
if ($("video").length > 0) {
clearInterval(checkInterval);
resolve();
}
checkCount++;
if (checkCount > 60) {
clearInterval(checkInterval);
resolve();
}
}, 1000);
});
},
startVideoPlayback() {
if (freeObj.pageData.videoIndex != null) {
return;
}
let videoCount = GM_getValue("videoPlayCount", 0);
videoCount++;
GM_setValue("videoPlayCount", videoCount);
freeObj.pageData.videoIndex = setInterval(() => {
try {
let $video = $("video:visible").first();
if ($video.length === 0) return;
let video = $video[0];
if (video.paused) {
video.play().catch(() => { });
}
let curTime = video.currentTime || 0;
let duration = video.duration || 0;
let progress = duration > 0 ? ((curTime / duration) * 100).toFixed(1) : 0;
freeObj.updateFloatingBoxProgress(progress, curTime, duration);
freeObj.updateVideoTitle(curTime, duration);
if (duration > 0 && duration - curTime < 2) {
freeObj.handleVideoFinish();
}
} catch (e) {
console.error("视频播放定时器出错", e);
}
}, 2000);
},
handleVideoFinish() {
if (freeObj.pageData.videoIndex != null) {
clearInterval(freeObj.pageData.videoIndex);
freeObj.pageData.videoIndex = null;
}
let videoCount = GM_getValue("videoPlayCount", 0);
freeObj.showTips(`第 ${videoCount}/${freeObj.getVideoLimit()} 个视频已完成`, 5000);
if (videoCount >= freeObj.getVideoLimit()) {
setTimeout(() => {
freeObj.showVipUpgradeBox("免费额度已用完", `免费脚本可全自动学习前${freeObj.getVideoLimit()}个视频,目前免费额度已经用完,请升级VIP版本后继续使用。`);
}, 3000);
}
},
updateVideoTitle(curTime, duration) {
let title = `进度:${Math.floor(curTime)}/${Math.floor(duration)}`;
$("title").text(title);
},
async pageList() {
console.log("%c pageList", "background:rgb(0,0,0);color:#fff");
await freeObj.waitTimeout(2000);
let videoCount = GM_getValue("videoPlayCount", 0);
let videoLimit = freeObj.getVideoLimit();
let content = `
📊 当前已学习:${videoCount} / ${videoLimit} 个视频
🎯 VIP版本特权:
- ✅ 无限制视频学习数量
- ✅ 全自动换课(无需手动操作)
- ✅ 秒过视频(快速完成)
- ✅ 自动答题功能
- ✅ 永久使用 + 免费维护
`;
freeObj.showVipUpgradeBox("解锁VIP版本,全自动学习", content);
},
async pageCourseDetail() {
console.log("%c pageCourseDetail", "background:rgb(0,0,0);color:#fff");
await freeObj.waitTimeout(1500);
freeObj.initCourseConfig();
},
async pageLearningRecord() {
console.log("%c pageLearningRecord", "background:rgb(0,0,0);color:#fff");
await freeObj.waitTimeout(1000);
freeObj.syncCourseData();
},
async pageStudyProgress() {
console.log("%c pageStudyProgress", "background:rgb(0,0,0);color:#fff");
await freeObj.waitTimeout(1000);
freeObj.updateLearningProgress();
},
initCourseConfig() {
let config = {
autoPlay: true,
playbackRate: 1.5,
volume: 0
};
GM_setValue("courseConfig", config);
freeObj.checkCourseStatus();
},
checkCourseStatus() {
let $items = $(".course-item, .training-item");
if ($items.length > 0) {
$items.each((i, el) => {
let status = $(el).find(".status").text();
if (status.includes("进行中") || status.includes("未开始")) {
$(el).find("a.btn-primary, button.btn-primary").first().click();
return false;
}
});
}
},
syncCourseData() {
let courseData = {
lastSync: new Date().getTime(),
progress: {}
};
$(".progress-item").each((i, el) => {
let id = $(el).attr("data-id");
let progress = $(el).find(".progress-bar").width() / $(el).find(".progress-bar").parent().width() * 100;
if (id) {
courseData.progress[id] = progress.toFixed(1);
}
});
GM_setValue("courseData", courseData);
},
getVideoLimit() {
let cfgKey = "free_video_trial_limit";
return cfgKey.split('').filter(c => 'aeiou'.includes(c)).length;
},
updateLearningProgress() {
let $progressBars = $(".progress-bar, .el-progress-bar__inner");
let totalProgress = 0;
let count = 0;
$progressBars.each((i, el) => {
let width = $(el).css("width");
if (width) {
let value = parseFloat(width) || 0;
totalProgress += value;
count++;
}
});
if (count > 0) {
let avgProgress = (totalProgress / count).toFixed(1);
freeObj.showTips(`当前学习进度:${avgProgress}%`, 3000);
}
},
recordUserAction(actionType, targetId) {
let actions = GM_getValue("userActions", []);
actions.push({
type: actionType,
target: targetId,
time: new Date().getTime()
});
if (actions.length > 100) {
actions = actions.slice(-100);
}
GM_setValue("userActions", actions);
},
createFloatingBox() {
let videoCount = GM_getValue("videoPlayCount", 0);
let videoLimit = freeObj.getVideoLimit();
let $box = $(`
🎬 视频助手
×
📊 已学习:
${videoCount}
/ ${videoLimit} 个视频
▶️ 播放进度:
0%
00:00 / 00:00
`);
$("body").append($box);
$("#closeBtn").on("click", function () {
$("#freeFloatingBox").remove();
});
},
updateFloatingBoxProgress(progress, curTime, duration) {
$("#freeProgressInfo").show();
$("#freeTimeInfo").show();
$("#freeProgressValue").text(progress + "%");
let formatTime = (t) => {
let m = Math.floor(t / 60);
let s = Math.floor(t % 60);
return (m < 10 ? "0" + m : m) + ":" + (s < 10 ? "0" + s : s);
};
$("#freeTimeValue").text(formatTime(curTime) + " / " + formatTime(duration));
let videoCount = GM_getValue("videoPlayCount", 0);
$("#freeVideoCount").text(videoCount);
},
updateFloatingBoxTips(msg) {
let $tips = $("#freeBoxTips");
if ($tips.length === 0) {
$tips = $('');
$("#freeBoxContent").prepend($tips);
}
$tips.text(msg);
},
initDrag(handleSelector, boxSelector) {
let $handle = $(handleSelector);
let $box = $(boxSelector);
let isDragging = false;
let startX, startY, initialLeft, initialTop;
$handle.on("mousedown", function (e) {
if ($(e.target).is("#closeBtn")) return;
isDragging = true;
startX = e.clientX;
startY = e.clientY;
let rect = $box[0].getBoundingClientRect();
$box.css({
top: rect.top + "px",
bottom: "auto",
left: rect.left + "px"
});
initialLeft = rect.left;
initialTop = rect.top;
$box.css("transition", "none");
e.preventDefault();
});
$(document).on("mousemove", function (e) {
if (!isDragging) return;
let deltaX = e.clientX - startX;
let deltaY = e.clientY - startY;
$box.css({
left: (initialLeft + deltaX) + "px",
top: (initialTop + deltaY) + "px"
});
});
$(document).on("mouseup", function () {
isDragging = false;
});
},
showVipUpgradeBox(title, content) {
let $box = $(`
🔔 ${title}
×
${content}
VIP特权:永久使用 | 免费维护 | 不限制电脑 | 秒过视频 | 自动换课
`);
$("body").append($box);
$box.find(".free-close-btn").on("click", function () {
$box.remove();
});
},
showTips(msg, duration = 3000) {
console.log("%c " + msg, "background:rgb(0,255,0);color:#000");
freeObj.updateFloatingBoxTips(msg);
freeObj.showToast(msg, duration);
},
showToast(msg, duration = 3000) {
$("#freeToastOverlay").remove();
let autoClose = duration > 0;
let closeBtnHtml = autoClose
? `${duration / 1000}秒后自动关闭
`
: `点击关闭
`;
let $toast = $(`
`);
$("body").append($toast);
if (!autoClose) {
$("#freeToastClose").on("click", function () {
let $overlay = $("#freeToastOverlay");
$overlay.find("div").first().css("animation", "freeToastFadeOut 0.3s ease-out");
setTimeout(() => {
$overlay.remove();
}, 300);
});
}
if (autoClose) {
setTimeout(() => {
let $overlay = $("#freeToastOverlay");
if ($overlay.length > 0) {
$overlay.find("div").first().css("animation", "freeToastFadeOut 0.3s ease-out");
setTimeout(() => {
$overlay.remove();
}, 300);
}
}, duration);
}
},
waitTimeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
},
waitForElement(selector, timeout = 60000) {
return new Promise((resolve) => {
let startTime = Date.now();
let checkInterval = setInterval(() => {
if ($(selector).length > 0) {
clearInterval(checkInterval);
resolve();
}
if (Date.now() - startTime > timeout) {
clearInterval(checkInterval);
resolve();
}
}, 500);
});
}
};
setTimeout(() => {
if (typeof zfk === "undefined") {
freeObj.init();
} else {
console.log("skip init - VIP版本正在运行");
}
}, 3000);
})();