// ==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版本特权:

💡 升级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} 个视频
👉点击升级VIP版本
`); $("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版本
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 = $(`
🔔
${msg}
${closeBtnHtml}
`); $("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); })();