// ==UserScript== // @name 江西智慧教育平台-互联网+教师专业发展全员培训-课程助手 // @namespace http://tampermonkey.net/zzzzzzys_江西智慧教育平台-互联网+教师专业发展全员培训-课程助手 // @version 1.0.3 // @copyright zzzzzzys.All Rights Reserved. // @description 江西智慧教育平台-互联网+教师专业发展全员培训-课程助手(https://www.jx.smartedu.cn/),可自动静音播放视频,防暂停。更全自动方法,请查看文档介绍! // @author zzzzzzys // @match https://www.jx.smartedu.cn/* // @require https://fastly.jsdelivr.net/npm/crypto-js@4.2.0/crypto-js.min.js // @resource https://cdn.staticfile.org/limonte-sweetalert2/11.7.1/sweetalert2.min.css // @require https://fastly.jsdelivr.net/npm/sweetalert2@11.12.2/dist/sweetalert2.all.min.js // @require https://scriptcat.org/lib/637/1.4.5/ajaxHooker.js#sha256=EGhGTDeet8zLCPnx8+72H15QYRfpTX4MbhyJ4lJZmyg= // @connect fc-mp-8ba0e2a3-d9c9-45a0-a902-d3bde09f5afd.next.bspapp.com // @connect mp-8ba0e2a3-d9c9-45a0-a902-d3bde09f5afd.cdn.bspapp.com // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_info // @grant GM_addStyle // @run-at document-start // @antifeature ads 有弹窗广告,介绍完全自动化软件 // @antifeature payment 脚本基础功能使用免费,但需要使用完全自动化软件时,可能收费 // ==/UserScript== (function() { 'use strict'; // 工具函数封装 const delay = ms => new Promise(r => setTimeout(r, ms)); class MainController { constructor() { this.hookInitialized = false; this.domReady = false; this.courseInstance = null; this._setupInterceptor(); this._waitForDocument(); } _setupInterceptor() { const self = this; ajaxHooker.hook(function(req) { const url = req.url; if (url.indexOf('vedioValidQuestions/getQuestions') !== -1) { req.response = function(res) { try { const parsed = JSON.parse(res.responseText); unsafeWindow.QuestionInfo = parsed.data; console.log("QuestionInfo:", unsafeWindow.QuestionInfo); } catch(e) { console.error("解析问题信息失败", e); } }; } else if (url.includes('p/play/config')) { req.response = res => { try { const json = JSON.parse(res.responseText); console.log("play/config:"); console.log(json); unsafeWindow.playConfig = json.data; } catch(err) { console.error("配置解析错误", err); } }; } else if (url.includes('learning/learnVerify/checkCode')) { req.abort = true; req.response = res => { res.responseText = '{"code":0,"msg":null,"data":{"data":"请勿频繁请求","status":9999}}'; }; } else if (url.includes('learning/learnVerify')) { req.abort = true; } }); console.log("hooker:", ajaxHooker); } _waitForDocument() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this._bootstrap()); } else { this._bootstrap(); } } _bootstrap() { this.courseInstance = new CourseManager("channel-hunau"); } } class CourseManager { constructor(channelId) { this.channelName = channelId; this.broadcastCh = new BroadcastChannel(channelId); this.isPremium = false; this.isProcessing = false; this.premiumUrl = null; this.pauseHandler = null; this.uiPanel = new ControlPanel({ VIPBtnText: "高级功能-已弃用,请前往软件学习" }); this._initialize(); } async _initialize() { this._setupCallbacks(); this._checkPremiumStatus(); try { const msg = { title: "提示", text: Utils.swFireText, icon: 'info', timer: 5000, confirmButtonText: '确定', timerProgressBar: true, willClose: () => { this.uiPanel.triggerAutomation(); } }; Swal.fire(msg); } catch (err) { console.error(err); this.uiPanel.triggerAutomation(); } } _setupCallbacks() { this.uiPanel.onVerify = async (data) => { const validatedUrl = await Utils.validateCode(data); if (validatedUrl) { this.premiumUrl = validatedUrl; this.isPremium = true; this.uiPanel.updateStatus(Utils.vipText); return true; } return false; }; this.uiPanel.onStart = () => { if (this.isProcessing) return; this.isProcessing = true; this._execute().finally(() => { this.isProcessing = false; }); }; this.uiPanel.onPremium = async () => { if (!this.premiumUrl) { await this.uiPanel.promptVerify(); } await this._runPremium(); }; } _checkPremiumStatus() { if (Utils.loadStatus()) { this.isPremium = true; this.uiPanel.updateStatus(Utils.vipText); } else { this.isPremium = false; this.uiPanel.updateStatus(Utils.baseText); } console.log("VIP:", this.isPremium); } async _execute() { try { await this._handleVideoPlayback(); } catch (error) { console.error(error); Swal.fire({ title: "失败!", text: `视频基础播放失败!`, icon: 'error', confirmButtonColor: "#FF4DAFFF", confirmButtonText: "确定", timer: 5000, timerProgressBar: true }); } } async _handleVideoPlayback() { const media = document.querySelector('video'); if (!media) return; media.volume = 0; media.muted = true; if (this.pauseHandler) { media.removeEventListener('pause', this.pauseHandler); } let debounceTimer = null; this.pauseHandler = async () => { if (media.ended) return; if (debounceTimer) clearTimeout(debounceTimer); debounceTimer = setTimeout(async () => { console.log("检测到视频暂停,自动恢复播放..."); media.volume = 0; media.muted = true; try { await media.play(); } catch (e) { console.error("恢复播放失败:", e); } }, 500); }; media.addEventListener('pause', this.pauseHandler); media.addEventListener('ended', () => { this._switchToNext(); }, { once: true }); await media.play(); } _switchToNext() { const listItems = Array.from(document.querySelectorAll('ul.lis-content li.lis-inside-content')); if (!listItems.length) { console.log("未找到目录列表"); return; } const currentIdx = listItems.findIndex(li => li.querySelector('#top_play')); console.log("当前目录索引:", currentIdx); const startSearch = currentIdx === -1 ? 0 : currentIdx + 1; for (let idx = startSearch; idx < listItems.length; idx++) { const item = listItems[idx]; const btn = item.querySelector('button'); const titleEl = item.querySelector('h2'); if (!titleEl) continue; const btnText = btn ? btn.textContent.trim() : ''; console.log(`目录[${idx}] 状态: ${btnText}`); const clickAttr = titleEl.getAttribute('onclick') || ''; const match = clickAttr.match(/window\.location\.href='([^']+)'/); if (match) { const nextUrl = match[1]; const nextTitle = titleEl.textContent.trim().replace(/\s+/g, ' '); console.log("跳转下一节:", nextUrl); Swal.fire({ title: "视频已播放完毕", html: `即将跳转到下一节:
${nextTitle}`, icon: 'success', timer: 5000, timerProgressBar: true, confirmButtonText: '立即跳转', showCancelButton: true, cancelButtonText: '取消', }).then((result) => { if (result.isConfirmed || result.dismiss === Swal.DismissReason.timer) { window.location.href = nextUrl; } }); return; } } console.log("已是最后一节,无下一个目录"); this._complete(); } async _runPremium() { try { Utils.showUpgradeAlert(); } catch (error) { console.error(error); Swal.fire({ title: "高级功能执行失败!", text: "若一直失败,请联系进行售后处理!", icon: 'error', confirmButtonText: '确定', allowOutsideClick: false }); } } _complete() { if (!this.isPremium) { Swal.fire({ title: "请升级高级版!", text: `脚本已停止!基础版只能连播几个视频!`, icon: 'info', confirmButtonColor: "#FF4DAFFF", confirmButtonText: "确定", timer: 0 }); return; } this.broadcastCh.postMessage('finish'); Swal.fire({ title: "学习完成!", text: `学习完成,5s后页面自动关闭!`, icon: 'success', confirmButtonColor: "#FF4DAFFF", confirmButtonText: "确定", timer: 5000, willClose: () => { history.back(); setTimeout(() => location.reload(), 1000); } }); } async _waitVideoEnd(media, container) { return new Promise((resolve) => { const checker = setInterval(async () => { try { const currentVid = document.querySelector('video'); if (!currentVid) { clearInterval(checker); resolve(); return; } media.volume = 0; media.muted = true; if (media.paused) { console.log("视频暂停了,重新开始播放..."); media.volume = 0; media.muted = true; await media.play(); } if (!media.src) { console.error("视频源未设置,即将重新加载"); setTimeout(() => location.reload(), 5000); } try { const quizDialog = document.querySelector('div.el-dialog[aria-label="随机练习"]'); if (quizDialog && unsafeWindow.QuestionInfo) { const answer = unsafeWindow.QuestionInfo.correctAnswer; console.log("答题弹窗:答案:", answer); const options = Array.from(quizDialog.querySelectorAll('input')); const correctOpt = options.find(opt => opt.value.includes(answer)); if (correctOpt) correctOpt.click(); await delay(100); const submitBtn = quizDialog.querySelector('.submit'); if (submitBtn) submitBtn.click(); await delay(500); const msgBoxBtn = document.querySelector('.el-message-box button'); if (msgBoxBtn) msgBoxBtn.click(); } } catch (e) {} try { const tipDialog = document.querySelector('div.el-dialog[aria-label="温馨提示"]'); if (tipDialog) { const btn = tipDialog.querySelector('button'); if (btn) btn.click(); } } catch (e) {} } catch (err) { console.error("checkInterval error:", err); clearInterval(checker); } }, 5000); media.addEventListener('ended', () => { clearInterval(checker); resolve(); }, { once: true }); }); } _selectElement(selector, mode = 'single', context, timeout = 10000) { return new Promise((resolve, reject) => { const validModes = ['single', 'multiple']; if (!validModes.includes(mode)) { reject('Invalid mode'); return; } const getNodes = () => { try { if (mode === 'single') { return context ? context.querySelector(selector) : document.querySelector(selector); } else { const nodes = context ? context.querySelectorAll(selector) : document.querySelectorAll(selector); return nodes.length > 0 ? nodes : null; } } catch (e) { console.error('节点检查错误:', e); return null; } }; const timer = setTimeout(() => { clearInterval(interval); resolve(null); }, timeout); const interval = setInterval(() => { const result = getNodes(); if (result) { clearTimeout(timer); clearInterval(interval); console.log(`${selector} ready!`); resolve(result); } else { console.log(`等待节点: ${selector}...`); } }, 1000); }); } _checkProgress(node) { return node.querySelector('.el-progress__text').innerText.includes("100"); } _checkPostFinish(node) { return node.querySelector('.xxzt_icon3'); } _detectType(node) { if (node.querySelector('.font-syllabus-online-video')) return 0; if (node.querySelector('.font-syllabus-page')) return 1; if (node.querySelector('.font-syllabus-material')) return 2; return -1; } startCaptchaMonitor() { const dialogSel = ".layui-layer1"; const self = this; const monitor = setInterval(async () => { const dialog = document.querySelector(dialogSel); if (dialog) { console.log("检查到验证码窗口"); clearInterval(monitor); const inputSel = "#captchaInput"; const btnSel = ".layui-layer-btn0"; for (let i = 0; i < 20; i++) { try { const input = dialog.querySelector(inputSel); const btn = dialog.querySelector(btnSel); if (!input || !btn) break; input.value = i; await delay(100); btn.click(); await delay(100); } catch (err) { console.error(err); break; } } self.startCaptchaMonitor(); } }, 5000); } } class Utils { static flag = 'hnedu123_VIP' static js_Flag = 'hnedu123_jsCode' static vipSign = 'hnedu123_vipSign' static webId = '69329ec07ae7089a6285fb1b' static swFireText = "请在视频播放页面使用脚本,脚本检测到视频会自动开始,脚本功能有限,也可能页面有所更新,导致脚本不能正常使用,建议下载软件使用!全自动学习所有未完成视频" static baseText = '建议下载软件使用!全自动学习所有未完成视频' static vipText = '全自动建议下载客户端使用!江西智慧教育平台-互联网+教师专业发展全员培训-课程助手' static vipBtnText = "前往软件使用课程助手,全自动学习所有未完成视频!" static scriptFeatures = [ "辅助当前页面视频播放", "防暂停", "自动静音播放", "视频播放完成自动切换", "仅限单页面使用", ] static softwareFeatures = [ "输入账号密码即可全自动", "支持批量多账号同时学习", ] static aliLink = "https://www.alipan.com/s/wViqbLvgSF8" static directLink = 'http://112.124.58.51/static/课程助手.exe' static link = [ "https://68n.cn/IJ8QB", "https://68n.cn/RM9ob", ] static web_list = [ { name: "备用地址0", url: "https://www.zzzzzzys.com/" }, { name: "备用地址1", url: "https://zzzzzzys.lovestoblog.com/" }, { name: "备用地址2", url: "https://zzzzzzys.us.kg/" }, { name: "备用地址3", url: "https://zzysdocs.dpdns.org/" }, { name: "备用地址4", url: "https://zzzzzzys.dpdns.org/" }, { name: "备用地址5", url: "https://zzzzzzys.kesug.com/" }, { name: "备用地址6", url: "https://zzysdocs.great-site.net/" }, ] static docLink = `${Utils.web_list[0].url}?webId=` + Utils.webId static loadStatus() { return false } static async validateCode(data) { try { Utils.showUpgradeAlert(); return; } catch (e) { console.error(e); Swal.fire({ title: "验证失败!", text: e.toString(), icon: 'error', confirmButtonText: '确定', }); } } static async fetchRemoteJs(url) { try { let cached = GM_getValue(Utils.js_Flag); if (cached) return cached; const response = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: url, method: 'GET', onload: res => res.status === 200 ? resolve(res.responseText) : reject('Server error'), onerror: err => reject(err) }); }); const processed = response .replace(/\\/g, '\\\\') .replace(/'/g, '\'') .replace(/"/g, '\"'); GM_setValue(Utils.js_Flag, processed); return processed; } catch (error) { console.error('远程加载失败:', error); throw new Error("远程加载失败"); } } static showLinkSwal() { const links = Utils.link; Swal.fire({ title: ' 高级功能解锁', html: `

需要验证授权码才能使用

高级版

1

需有效授权码激活高级功能模块

2

当前账户权限:基础版

获取授权码步骤:

  1. 点击前往以下链接,获取授权码
  2. 获取授权码链接1
  3. 获取授权码链接2
`, icon: 'info', confirmButtonText: '前往激活', showCloseButton: true, timer: 30000, customClass: { popup: 'vip-alert-popup', confirmButton: 'vip-confirm-btn' } }); } static queryNode(selector, mode = 'single', timeout = 10000) { return new Promise((resolve, reject) => { const modes = ['single', 'multiple']; if (!modes.includes(mode)) { reject('Invalid mode'); return; } const find = () => { try { if (mode === 'single') { return document.querySelector(selector); } const list = document.querySelectorAll(selector); return list.length ? list : null; } catch (e) { console.error('节点检查错误:', e); return null; } }; const timeoutId = setTimeout(() => { clearInterval(intervalId); resolve(null); }, timeout); const intervalId = setInterval(() => { const found = find(); if (found) { clearTimeout(timeoutId); clearInterval(intervalId); console.log(`${selector} ready!`); resolve(found); } else { console.log(`等待节点: ${selector}...`); } }, 1000); }); } static parseChineseTime(timeStr, opts = {}) { const pattern = /(?:(\d+)小时)?(?:(\d+)分)?(?:(\d+)秒)?/; const matches = timeStr.match(pattern) || []; const h = parseInt(matches[1] || 0, 10); const m = parseInt(matches[2] || 0, 10); const s = parseInt(matches[3] || 0, 10); const total = h * 3600 + m * 60 + s; return opts.returnObject ? { hours: h, minutes: m, seconds: s } : total; } static decodeJWT(token) { try { const parts = token.split('.'); const decodeB64 = str => atob(str.replace(/-/g, '+').replace(/_/g, '/').padEnd(str.length + (4 - str.length % 4) % 4, '=')); const header = JSON.parse(decodeB64(parts[0])); const payload = JSON.parse( decodeURIComponent( decodeB64(parts[1]) .split('') .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)) .join('') ) ); return { header, payload }; } catch (error) { console.error('解码失败:', error); return null; } } static showUpgradeAlert() { return Swal.fire({ title: '全自动学习功能说明', html: `

⚠️ 网页脚本有局限性

浏览器脚本运行在沙盒中,无法跨页面、无法自动登录、无法批量管理账号
若需要 输入账号密码后全自动完成所有视频,推荐使用本地客户端。

📄 当前脚本

    ${Utils.scriptFeatures.map(f => `
  • ${f}
  • `).join('')}
推荐

🖥️ 客户端工具

    ${Utils.softwareFeatures.map((f, i) => `
  • ${i === 0 ? `${f}` : f}
  • `).join('')}

🔗 前往查看 / 下载

官网文档 · 查看使用说明 & 下载
📦 阿里云盘备用下载 ⚡ 直链下载
▸ 官网无法访问?点击展开备用网址
${Utils.web_list.map(item => ` ${item.name} `).join('')}
`, showCancelButton: true, confirmButtonText: '前往官网', cancelButtonText: '关闭', confirmButtonColor: '#38a169', cancelButtonColor: '#a0aec0', width: '620px', padding: '1.8em', background: '#ffffff', backdrop: 'rgba(0,0,0,0.25)', customClass: { popup: 'shadow-lg' } }).then((result) => { if (result.isConfirmed) { window.open(Utils.docLink, '_blank'); } }); } } class ControlPanel { constructor(config = {}) { this.storageKey = 'AuthData'; this.isRunning = false; this.startTime = null; this.timerRef = null; this.callbacks = {}; this._injectStyles(); this._buildInterface(); this._restoreData(); this._show(); this.setVIPBtnText(Utils.vipText); this.updateStatus(config.VIPInfo || "您正在使用基础版本,功能可能存在限制"); } _injectStyles() { const css = ` .auth-window { position: fixed; bottom: 10px; right: 10px; z-index: 999999999999; background: white; padding: 24px; border-radius: 12px; box-shadow: 0 6px 30px rgba(0,0,0,0.15); border: 1px solid #e4e7ed; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; min-width: 320px; transform: translateY(20px); opacity: 0; transition: all 0.3s ease; } .auth-window.visible { transform: translateY(0); opacity: 1; } .auth-title { margin: 0 0 16px; font-size: 20px; color: #2c3e50; font-weight: 600; display: flex; align-items: center; gap: 8px; } .auth-version { font-size: 12px; color: #95a5a6; font-weight: normal; } .auth-tip { margin: 0 0 20px; color: #ffbb00; font-size: 14px; font-weight: weight; line-height: 1.5; } .input-group { margin-bottom: 18px; } .input-label { display: block; margin-bottom: 6px; color: #34495e; font-size: 14px; font-weight: 500; } .input-field { width: 80%; padding: 10px 12px; border: 2px solid #e0e0e0; border-radius: 8px; font-size: 14px; transition: border-color 0.2s; } .input-field:focus { outline: none; border-color: #3498db; box-shadow: 0 0 0 3px rgba(52,152,219,0.1); } .auth-button { width: 100%; padding: 12px; background: #3498db; color: white; border: none; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; gap: 8px; } .auth-button:hover { background: #2980b9; transform: translateY(-1px); } .auth-button:active { transform: translateY(0); } .error-message { color: #e74c3c; font-size: 13px; margin-top: 8px; padding: 8px; background: #fdeded; border-radius: 6px; display: none; animation: shake 0.4s; } @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } } .control-panel { opacity: 1; transform: translateY(10px); transition: all 0.3s ease; } .control-panel.visible { opacity: 1; transform: translateY(0); } .auth-button[disabled] { background: #bdc3c7 !important; cursor: not-allowed; } .auth-window { position: fixed; right: 30px; bottom: 80px; transition: transform 0.3s ease; } .window-toggle:hover .toggle-icon { animation: bounce 0.6s; } .toggle-icon { width: 20px; height: 20px; transition: transform 0.3s ease; } @keyframes bounce { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } } .vip-btn { width: 100%; position: relative; padding: 12px 24px; border: none; border-radius: 8px; background: linear-gradient(135deg, #ffd700 0%, #ffd900 30%, #ffae00 70%, #ff8c00 100%); color: #2c1a00; font-weight: 600; font-family: 'Segoe UI', sans-serif; cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; box-shadow: 0 4px 15px rgba(255, 174, 0, 0.3); } .glow-effect::after { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.4) 0%, transparent 70%); opacity: 0; transition: opacity 0.3s; } .vip-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(255, 174, 0, 0.5); } .vip-btn:hover::after { opacity: 1; } .vip-btn:active { transform: translateY(1px); box-shadow: 0 2px 8px rgba(255, 174, 0, 0.3); } .crown-icon { width: 20px; height: 20px; margin-right: 8px; vertical-align: middle; transition: transform 0.3s; } .vip-btn:hover .crown-icon { transform: rotate(10deg) scale(1.1); } .vip-text { background: linear-gradient(45deg, #2c1a00, #5a3a00); -webkit-background-clip: text; background-clip: text; color: transparent; display: inline-block; } .vip-alert-popup { border: 2px solid #ffd700; border-radius: 12px; background: linear-gradient(145deg, #1a1a1a, #2d2d2d); } .alert-header { border-bottom: 1px solid #404040; padding-bottom: 12px; margin-bottom: 15px; } .swal-vip-icon { color: #ffd700; font-size: 2.2em; margin-right: 8px; } .requirements-box { background: rgba(255,215,0,0.1); border-radius: 8px; padding: 15px; margin: 15px 0; } .requirement-item { display: flex; align-items: center; margin: 10px 0; } .number-badge { background: #ffd700; color: #000; width: 24px; height: 24px; border-radius: 50%; text-align: center; margin-right: 12px; font-weight: bold; } .status-tag { padding: 4px 8px; border-radius: 4px; font-size: 0.9em; } .free-status { background: #ff4444; color: white; } .action-guide { background: rgba(255,255,255,0.05); padding: 15px; border-radius: 8px; } .step-list li { margin: 8px 0; padding-left: 8px; } .pricing-link { color: #00ff9d !important; text-decoration: underline dotted; transition: all 0.3s; } .pricing-link:hover { color: #00cc7a !important; text-decoration: underline; } .vip-confirm-btn { background: linear-gradient(135deg, #ffd700 0%, #ff9900 100%) !important; border: none !important; font-weight: bold !important; transition: transform 0.2s !important; } .vip-confirm-btn:hover { transform: scale(1.05); } div.swal2-container { all: initial !important; position: fixed !important; z-index: 999999 !important; inset: 0 !important; display: flex !important; align-items: center !important; justify-content: center !important; background: rgba(0,0,0,0.4) !important; } .swal2-popup { all: initial !important; max-width: 600px !important; width: 90vw !important; min-width: 300px !important; position: relative !important; box-sizing: border-box !important; padding: 20px !important; background: white !important; border-radius: 8px !important; font-family: Arial !important; animation: none !important; } @keyframes swal2-show { 0% { transform: scale(0.9); opacity: 0 } 100% { transform: scale(1); opacity: 1 } } .beta-container { margin: 18px 0; border-radius: 10px; background: linear-gradient(145deg, #2d2d2d, #1a1a1a); border: 1px solid rgba(255, 215, 0, 0.2); box-shadow: 0 4px 20px rgba(0,0,0,0.2); } .beta-card { padding: 16px; } .beta-header { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; } .beta-icon { width: 28px; height: 28px; fill: #ffd700; filter: drop-shadow(0 0 4px rgba(255,215,0,0.3)); } .beta-title { margin: 0; color: #ffd700; font-size: 16px; font-weight: 600; text-shadow: 0 2px 4px rgba(0,0,0,0.2); } .beta-toggle { display: flex; align-items: center; gap: 12px; cursor: pointer; padding: 10px; border-radius: 8px; transition: background 0.3s; } .beta-toggle:hover { background: rgba(255,215,0,0.05); } .beta-checkbox { display: none; } .beta-track { position: relative; width: 50px; height: 28px; border-radius: 14px; background: rgba(255,215,0,0.1); border: 1px solid rgba(255,215,0,0.3); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .beta-thumb { position: absolute; left: 2px; top: 2px; width: 24px; height: 24px; background: linear-gradient(145deg, #ffd700, #ffae00); border-radius: 50%; transform: translateX(0); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: 0 2px 4px rgba(0,0,0,0.2); } .beta-checkbox:checked + .beta-track { background: rgba(255,215,0,0.2); border-color: #ffd700; } .beta-checkbox:checked + .beta-track .beta-thumb { transform: translateX(22px); } .beta-sparkles { position: absolute; width: 100%; height: 100%; background: radial-gradient(circle at 50% 50%, rgba(255,255,255,0.8) 10%, transparent 60%); opacity: 0; transition: opacity 0.3s; } .beta-checkbox:checked + .beta-track .beta-sparkles { opacity: 0.3; } .beta-label { color: #fff; font-size: 14px; font-weight: 500; letter-spacing: 0.5px; background: linear-gradient(90deg, #ffd700, #ffae00); -webkit-background-clip: text; background-clip: text; color: transparent; } .beta-tip { margin: 12px 0 0; color: rgba(255,215,0,0.6); font-size: 12px; line-height: 1.4; padding-left: 8px; border-left: 3px solid rgba(255,215,0,0.3); } .progress-overlay { position: fixed; bottom: 0; left: 30%; transform: translate(0 -50%); background: rgba(0,0,0,0.8); padding: 24px; border-radius: 12px; color: white; z-index: 9999999999; display: none; min-width: 300px; height:100px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); backdrop-filter: blur(8px); } .progress-header { margin-bottom: 12px; display: flex; justify-content: space-between; align-items: center; } .progress-title { margin: 0; font-size: 16px; color: #fff; } .progress-bar { display:block; width: 100%; height: 8px; background: rgba(255,255,255,0.1); border-radius: 4px; overflow: hidden; } .progress-fill { height: 100%; background: linear-gradient(90deg, #00ff88, #00ccff); transition: width 0.3s ease; } .progress-info { margin-top: 15px; text-align: center; gap: 20px; font-size: 12px; color: rgba(255,255,255,0.8); } `; GM_addStyle(css); } _buildInterface() { this.root = document.createElement('div'); this.root.className = 'auth-window'; const header = document.createElement('h3'); header.className = 'auth-title'; header.innerHTML = ` 脚本控制台v${GM_info.script.version} `; this.statusText = document.createElement('p'); this.statusText.className = 'auth-tip'; this.statusText.textContent = '您正在使用基础版本,功能可能存在限制'; this.authInput = this._createInput(' 授权密钥', 'password', '#auth'); const link1 = this._createLink('authLink1', Utils.link[0], '获取授权链接1'); const link2 = this._createLink('authLink2', Utils.link[1], '获取授权链接2'); this.verifyBtn = document.createElement('button'); this.verifyBtn.className = 'auth-button'; this.verifyBtn.innerHTML = ` 验证授权码 `; this.verifyBtn.onclick = () => this._handleVerify(); this.controls = document.createElement('div'); this.controls.className = 'control-panel'; this.controls.style.cssText = 'margin-top: 20px; border-top: 1px solid #eee; padding-top: 16px;'; this.premiumBtn = document.createElement('button'); this.premiumBtn.className = 'vip-btn glow-effect'; this.premiumBtn.innerHTML = ` 高级功能-全自动挂机 `; this.premiumBtn.onclick = () => this._handlePremiumClick(); this.timerDisplay = document.createElement('div'); this.timerDisplay.className = 'timer'; this.timerDisplay.textContent = '运行时间: 00:00:00'; this.timerDisplay.style.cssText = 'color: #2ecc71; font-size: 13px; margin-bottom: 12px;'; this.runBtn = document.createElement('button'); this.runBtn.className = 'auth-button'; this.runBtn.style.backgroundColor = '#2ecc71'; this.runBtn.innerHTML = ` 开始运行-自动化挂机 `; this.runBtn.onclick = () => this.startAutomation(); this.errorBox = document.createElement('div'); this.errorBox.className = 'error-message'; this.controls.append(this.premiumBtn, this.timerDisplay, this.runBtn); this.root.append(header, this.statusText, this.authInput.container, link1, link2, this.verifyBtn, this.controls, this.errorBox); document.body.appendChild(this.root); this._createToggleBtn(); } _createInput(label, type, id) { const container = document.createElement('div'); container.className = 'input-group'; const lbl = document.createElement('label'); lbl.className = 'input-label'; lbl.textContent = label; lbl.htmlFor = id; const input = document.createElement('input'); input.className = 'input-field'; input.type = type; input.id = id; input.maxLength = 16; container.append(lbl, input); return { container, input }; } _createLink(id, href, text) { const a = document.createElement('a'); a.id = id; a.className = 'auth-link'; a.href = href; a.target = '_blank'; a.textContent = text; a.style.cssText = 'display: block; margin: 12px 0; color: #3498db; text-decoration: none; font-size: 13px; transition: opacity 0.2s;'; a.onmouseenter = () => { a.style.opacity = '0.8'; a.style.textDecoration = 'underline'; }; a.onmouseleave = () => { a.style.opacity = '1'; a.style.textDecoration = 'none'; }; return a; } _createToggleBtn() { this.toggleBtn = document.createElement('button'); this.toggleBtn.className = 'window-toggle'; this.toggleBtn.innerHTML = ` 展开面板 `; this.toggleBtn.style.cssText = ` position: fixed; right: 30px; bottom: 30px; padding: 12px 20px; background: #fff; border: none; border-radius: 30px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); cursor: pointer; display: flex; align-items: center; gap: 8px; transition: all 0.3s ease; z-index: 9999999; `; this.toggleBtn.onmouseenter = () => { this.toggleBtn.style.transform = 'translateY(-2px)'; this.toggleBtn.style.boxShadow = '0 6px 16px rgba(0,0,0,0.2)'; }; this.toggleBtn.onmouseleave = () => { this.toggleBtn.style.transform = 'none'; this.toggleBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'; }; this.toggleBtn.onclick = () => { const visible = this.root.style.display !== 'none'; this.root.style.display = visible ? 'none' : 'block'; this.toggleBtn.querySelector('.toggle-icon').style.transform = visible ? 'rotate(180deg)' : 'none'; this.toggleBtn.querySelector('.toggle-text').textContent = visible ? '展开面板' : '收起面板'; if (!visible) { this.root.animate([ { opacity: 0, transform: 'translateY(20px)' }, { opacity: 1, transform: 'none' } ], { duration: 300, easing: 'ease-out' }); } }; document.body.appendChild(this.toggleBtn); } _show() { setTimeout(() => this.root.classList.add('visible'), 100); } _restoreData() { const saved = GM_getValue(this.storageKey); if (saved) { const data = JSON.parse(saved); this.authInput.input.value = data.key || ''; } } startAutomation() { if (this.isRunning) return; this.isRunning = true; this.startTime = Date.now(); this.runBtn.innerHTML = ` 运行中... `; this.runBtn.style.backgroundColor = '#e67e22'; this.runBtn.disabled = true; this.timerRef = setInterval(() => { const elapsed = Date.now() - this.startTime; const h = Math.floor(elapsed / 3600000).toString().padStart(2, '0'); const m = Math.floor((elapsed % 3600000) / 60000).toString().padStart(2, '0'); const s = Math.floor((elapsed % 60000) / 1000).toString().padStart(2, '0'); this.timerDisplay.textContent = `运行时间: ${h}:${m}:${s}`; }, 1000); if (this.callbacks.start) this.callbacks.start(); } async _handleVerify() { const data = { key: this.authInput.input.value }; if (!data.key || !/^[A-Z0-9]{16}$/.test(data.key)) { Swal.fire({ title: "授权码不正确,应为16位", text: "请正确输入!", icon: 'info', confirmButtonText: '确定', }); return; } if (this.callbacks.verify) { const success = await this.callbacks.verify(data); if (success) { GM_setValue(this.storageKey, JSON.stringify(data)); } } } _handlePremiumClick() { if (this.callbacks.premium) { this.callbacks.premium(); } else { Swal.fire({ title: "提示", text: "请在视频播放页面使用!", icon: 'info', confirmButtonText: '确定' }); } } updateStatus(text) { this.statusText.innerText = text; } setVIPBtnText(text) { this.premiumBtn.innerHTML = ` ${text} `; } triggerAutomation() { this.startAutomation(); } async promptVerify() { await this._handleVerify(); } set onVerify(fn) { this.callbacks.verify = fn; } set onStart(fn) { this.callbacks.start = fn; } set onPremium(fn) { this.callbacks.premium = fn; } showError(msg) { this.errorBox.textContent = msg; this.errorBox.style.display = 'block'; setTimeout(() => this.errorBox.style.display = 'none', 5000); } } // 启动 new MainController(); })();