// ==UserScript== // @name 辽宁省干部在线学习网-课程助手 // @namespace http://tampermonkey.net/zzzzzzys_辽宁省干部在线学习网-课程助手 // @version 1.0.1 // @copyright zzzzzzys.All Rights Reserved. // @description 辽宁省干部在线学习网-课程助手(https://www.lngbzx.gov.cn/),脚本免费功能有限,可自动静音播放视频,防暂停。更全自动方法,请查看文档介绍!客户端课程助手,可学习所有未完成课程,最高支持2倍速!注意此平台网址!一定要和网页上的网址相对应! // @author zzzzzzys // @match https://www.lngbzx.gov.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== // 延迟函数 const delay = ms => new Promise(r => setTimeout(r, ms)); // 主入口类 - 重构后 class MainEntry { constructor() { this.courseHandler = null; this.setupAjaxInterceptor(); this.checkDocumentReady(); } setupAjaxInterceptor() { const that = this; ajaxHooker.hook(req => { const url = req.url; if (url.indexOf('vedioValidQuestions/getQuestions') !== -1) { req.response = res => { try { const parsed = JSON.parse(res.responseText); window.QuestionInfo = parsed.data; console.log("题目信息:", window.QuestionInfo); } catch (ex) { console.error("解析题目失败:", ex); } }; } else if (url.indexOf('p/play/config') !== -1) { req.response = res => { try { const parsed = JSON.parse(res.responseText); console.log("播放配置:", parsed); window.playConfig = parsed.data; } catch (ex) { console.error("解析配置失败:", ex); } }; } else if (url.indexOf('learning/learnVerify/checkCode') !== -1) { req.abort = true; req.response = res => { res.responseText = '{"code":0,"msg":null,"data":{"data":"请勿频繁请求","status":9999}}'; }; } else if (url.indexOf('learning/learnVerify') !== -1) { req.abort = true; } }); console.log("AJAX拦截器已启用"); } checkDocumentReady() { if (document.readyState !== 'loading') { this.boot(); } else { document.addEventListener('DOMContentLoaded', () => this.boot()); } } boot() { this.courseHandler = new CourseManager("channel-hunau"); } } // 课程管理类 - 重构后 class CourseManager { constructor(channelId = "channel-my") { this.channelId = channelId; this.isVipUser = false; this.isProcessing = false; this.broadcastCh = new BroadcastChannel(channelId); this.uiPanel = new ControlPanel({ VIPBtnText: "高级功能-已弃用,请前往软件学习" }); this.initialize(); } initialize() { // 设置验证回调 this.uiPanel.onVerify = async (formData) => { const apiUrl = await Helper.validateCode(formData); if (apiUrl) { this.uiPanel.updateTip(Helper.vipText); this.isVipUser = true; return true; } return false; }; // 启动按钮回调 this.uiPanel.onStart = () => { if (this.isProcessing) return; this.isProcessing = true; console.log("开始运行,VIP状态:", this.isVipUser); this.execute().finally(() => { this.isProcessing = false; }); }; // VIP按钮回调 this.uiPanel.onVipClick = async () => { if (!this.apiEndpoint) { await this.uiPanel.triggerVerify(); } await this.runPremiumFeatures(); }; this.restoreVipState(); this.showWelcomeAlert(); } showWelcomeAlert() { try { // 手动关闭的提示弹窗 const alertOptions = { title: "使用须知", text: Helper.swFireText, icon: 'info', confirmButtonText: '明白,开始使用', allowOutsideClick: false, allowEscapeKey: false, showCloseButton: false, willClose: () => { this.uiPanel.triggerStart(); } }; Swal.fire(alertOptions); } catch (err) { console.error("弹窗异常:", err); this.uiPanel.triggerStart(); } } restoreVipState() { const saved = Helper.loadStatus(); this.isVipUser = saved; if (saved) { this.uiPanel.updateTip(Helper.vipText); } else { this.uiPanel.updateTip(Helper.baseText); } console.log("VIP状态恢复:", this.isVipUser); } async runPremiumFeatures() { try { Helper.showUpgradeAlert(); } catch (err) { console.error("高级功能错误:", err); Swal.fire({ title: "高级功能执行失败!", text: "若一直失败,请联系进行售后处理!", icon: 'error', confirmButtonText: '确定', allowOutsideClick: false, willClose: () => { console.log('用户确认错误,脚本已停止'); } }); } } async execute() { try { await this.handleVideoPlayback(); } catch (err) { console.error("执行错误:", err); Swal.fire({ title: "失败!", text: "视频基础播放失败!", icon: 'error', confirmButtonColor: "#FF4DAFFF", confirmButtonText: "确定", timer: 5000, timerProgressBar: true, willClose: () => {} }); } } async handleVideoPlayback() { const media = document.querySelector('video'); if (!media) { console.warn("未找到视频元素"); return; } // 静音设置 media.volume = 0; media.muted = true; // 清理旧监听器 if (this._pauseGuard) { media.removeEventListener('pause', this._pauseGuard); } // 防暂停处理 let debounceTimer = null; this._pauseGuard = 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 (ex) { console.error("恢复播放失败:", ex); } }, 500); }; media.addEventListener('pause', this._pauseGuard); media.addEventListener('ended', () => { this.navigateToNext(); }, { once: true }); await media.play(); } navigateToNext() { const catalogItems = Array.from( document.querySelectorAll('ul.lis-content li.lis-inside-content') ); if (!catalogItems.length) { console.log("目录列表为空"); return; } const activeIdx = catalogItems.findIndex(li => li.querySelector('#top_play')); console.log("当前位置:", activeIdx); const startIdx = activeIdx === -1 ? 0 : activeIdx + 1; for (let i = startIdx; i < catalogItems.length; i++) { const item = catalogItems[i]; const btn = item.querySelector('button'); const titleEl = item.querySelector('h2'); if (!titleEl) continue; const status = btn ? btn.textContent.trim() : ''; console.log(`项目[${i}] 状态: ${status}`); const clickAttr = titleEl.getAttribute('onclick') || ''; const urlMatch = clickAttr.match(/window\.location\.href='([^']+)'/); if (urlMatch) { const targetUrl = urlMatch[1]; const lessonName = titleEl.textContent.trim().replace(/\s+/g, ' '); console.log("准备跳转:", targetUrl); Swal.fire({ title: "视频已播放完毕", html: `即将跳转到下一节:
${lessonName}`, icon: 'success', timer: 5000, timerProgressBar: true, confirmButtonText: '立即跳转', showCancelButton: true, cancelButtonText: '取消', }).then((result) => { if (result.isConfirmed || result.dismiss === Swal.DismissReason.timer) { window.location.href = targetUrl; } }); return; } } console.log("已是最后一节"); this.complete(); } broadcast(msg) { this.broadcastCh.postMessage(msg); } complete() { if (!this.isVipUser) { Swal.fire({ title: "请升级高级版!", text: "脚本已停止!基础版只能连播几个视频!", icon: 'info', confirmButtonColor: "#FF4DAFFF", confirmButtonText: "确定", timer: 0, willClose: () => {} }); return; } this.broadcast('finish'); Swal.fire({ title: "学习完成!", text: "学习完成,5s后页面自动关闭!", icon: 'success', confirmButtonColor: "#FF4DAFFF", confirmButtonText: "确定", timer: 5000, willClose: () => { history.back(); setTimeout(() => location.reload(), 1000); } }); } async monitorVideoProgress(videoEl, container) { return new Promise(resolve => { const checkId = setInterval(async () => { try { const current = document.querySelector('video'); if (!current) { clearInterval(checkId); resolve(); return; } videoEl.volume = 0; videoEl.muted = true; if (videoEl.paused && !videoEl.ended) { console.log("视频暂停,重新播放"); videoEl.volume = 0; videoEl.muted = true; await videoEl.play(); } if (!videoEl.src) { console.error("视频源丢失,准备刷新"); setTimeout(() => location.reload(), 5000); } // 处理答题弹窗 try { const quizDialog = document.querySelector('div.el-dialog[aria-label="随机练习"]'); if (quizDialog && window.QuestionInfo) { const answer = window.QuestionInfo.correctAnswer; console.log("自动答题:", answer); const choices = Array.from(quizDialog.querySelectorAll('input')); const correct = choices.find(opt => opt.value.includes(answer)); if (correct) { correct.click(); await delay(100); quizDialog.querySelector('.submit').click(); await delay(500); const msgBox = document.querySelector('.el-message-box button'); if (msgBox) msgBox.click(); } } } catch (quizErr) {} // 处理温馨提示 try { const tipDialog = document.querySelector('div.el-dialog[aria-label="温馨提示"]'); if (tipDialog) { const closeBtn = tipDialog.querySelector('button'); if (closeBtn) closeBtn.click(); } } catch (tipErr) {} } catch (monitorErr) { console.error("监控错误:", monitorErr); clearInterval(checkId); } }, 5000); videoEl.addEventListener('ended', () => { clearInterval(checkId); resolve(); }, { once: true }); }); } async waitForElement(selector, mode = 'single', root, timeoutMs = 10000) { return new Promise((resolve, reject) => { const modes = ['single', 'multiple']; if (!modes.includes(mode)) { reject('模式错误,需为 single 或 multiple'); return; } const cleanup = (tId, iId) => { clearTimeout(tId); clearInterval(iId); }; const success = (result, tId, iId) => { console.log(`${selector} 已就绪`); cleanup(tId, iId); resolve(result); }; const fail = (tId, iId) => { cleanup(tId, iId); resolve(null); }; const check = () => { try { if (mode === 'single') { const el = root ? root.querySelector(selector) : document.querySelector(selector); return el; } else { const list = root ? root.querySelectorAll(selector) : document.querySelectorAll(selector); return list.length > 0 ? list : null; } } catch (ex) { console.error('查询节点错误:', ex); reject(ex); } }; const interval = setInterval(() => { const found = check(); if (found) { success(found, timer, interval); } else { console.log(`等待中: ${selector}`); } }, 1000); const timer = setTimeout(() => { console.error(`等待超时: ${selector}`); fail(timer, interval); }, timeoutMs); }); } checkCompletion(domNode) { const progressText = domNode.querySelector('.el-progress__text'); return progressText && progressText.innerText.indexOf("100") !== -1; } checkCompletionPost(domNode) { return domNode.querySelector('.xxzt_icon3'); } detectContentType(domNode) { if (domNode.querySelector('.font-syllabus-online-video')) { return 0; // 视频 } if (domNode.querySelector('.font-syllabus-page')) { return 1; // 文档 } if (domNode.querySelector('.font-syllabus-material')) { return 2; // 材料 } return -1; } } // 辅助工具类 - 重构后 class Helper { // 存储键名 static vipKey = 'hnedu123_VIP'; static jsKey = 'hnedu123_jsCode'; static signKey = 'hnedu123_vipSign'; // 网站配置 static siteId = '689ee33b8b0da441dcc4b83d'; // 提示文本 - 保持不变 static swFireText = "请在视频播放页面使用脚本,脚本检测到视频会自动开始,脚本功能有限,也可能页面有所更新,导致脚本不能正常使用,建议下载软件使用!全自动学习所有未完成视频"; static baseText = '建议下载软件使用!全自动学习所有未完成视频'; static vipText = '全自动建议下载客户端使用!辽宁省干部在线学习网'; static vipBtnText = "前往软件使用课程助手,全自动学习所有未完成视频!"; // 功能列表 static scriptFeatures = [ "辅助当前页面视频播放", "防暂停", "自动静音播放", "仅限单页面使用", ]; static softwareFeatures = [ "输入账号密码即可全自动", "全自动完成所有未完成课程", "支持批量多账号同时学习", "最高2倍速(开发时可用)", ]; // 下载链接 static aliYunLink = "https://www.alipan.com/s/wViqbLvgSF8"; static directLink = 'http://112.124.58.51/static/课程助手.exe'; // 购买链接 static purchaseLinks = [ "https://68n.cn/IJ8QB", "https://68n.cn/RM9ob", ]; // 备用站点 static mirrorSites = [ { 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 docUrl = `${Helper.mirrorSites[0].url}?webId=${Helper.siteId}`; static loadStatus() { return false; } static async validateCode(formData) { try { Helper.showUpgradeAlert(); return; // 以下代码实际不会执行,因上方已return const response = await new Promise((resolve, reject) => { const query = new URLSearchParams(formData).toString(); GM_xmlhttpRequest({ url: `https://fc-mp-8ba0e2a3-d9c9-45a0-a902-d3bde09f5afd.next.bspapp.com/utils/validCodeCas?${query}`, method: 'GET', onload: (res) => { if (res.status === 200) { const data = JSON.parse(res.response); console.log("验证响应:", data); resolve(data); } else { reject('请求失败: ' + res.response); } }, onerror: (err) => { console.error("请求错误:", err); reject('网络错误: ' + err.toString()); } }); }); if (response.code !== 200) { GM_deleteValue(Helper.vipKey); GM_deleteValue(Helper.jsKey); throw new Error('验证失败: ' + response.data); } Swal.fire({ title: "高级功能已启用!", text: "校验成功!", icon: 'success', confirmButtonText: '确定', }); GM_setValue(Helper.vipKey, true); return response.data; } catch (ex) { console.error("验证异常:", ex); Swal.fire({ title: "验证失败!", text: ex.toString(), icon: 'error', confirmButtonText: '确定', }); } } static async fetchRemoteJs(endpoint) { try { let cached = GM_getValue(Helper.jsKey); if (cached) return cached; const jsContent = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: endpoint, method: 'GET', onload: (res) => { if (res.status === 200) { resolve(res.responseText); } else { reject('服务器拒绝: ' + res.response); } }, onerror: (err) => { console.error("JS加载错误:", err); reject('请求失败: ' + err.toString()); } }); }); const escaped = jsContent .replace(/\\/g, '\\\\') .replace(/'/g, '\\\'') .replace(/"/g, '\\\"'); GM_setValue(Helper.jsKey, escaped); return escaped; } catch (ex) { console.error('远程加载失败:', ex); throw new Error("远程加载失败"); } } static showPurchaseDialog() { const links = Helper.purchaseLinks; 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' }, willClose: () => {} }); } static async findElement(selector, mode = 'single', timeoutMs = 10000) { return new Promise((resolve, reject) => { const validModes = ['single', 'multiple']; if (!validModes.includes(mode)) { reject('无效模式参数'); return; } const clear = (t, i) => { clearTimeout(t); clearInterval(i); }; const done = (result, t, i) => { console.log(`${selector} 就绪`); clear(t, i); resolve(result); }; const timeout = (t, i) => { clear(t, i); resolve(null); }; const query = () => { try { if (mode === 'single') { return document.querySelector(selector); } const list = document.querySelectorAll(selector); return list.length ? list : null; } catch (ex) { console.error('查询错误:', ex); reject(ex); } }; const interval = setInterval(() => { const el = query(); if (el) { done(el, timer, interval); } else { console.log(`等待: ${selector}`); } }, 1000); const timer = setTimeout(() => { console.error(`超时: ${selector}`); timeout(timer, interval); }, timeoutMs); }); } static parseDuration(timeString, opts = {}) { const pattern = /(?:(\d+)小时)?(?:(\d+)分)?(?:(\d+)秒)?/; const matches = timeString.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 decodeToken(token) { try { const parts = token.split('.'); const decodeB64 = (str) => { const padded = str.replace(/-/g, '+').replace(/_/g, '/') .padEnd(str.length + (4 - str.length % 4) % 4, '='); return atob(padded); }; const header = JSON.parse(decodeB64(parts[0])); const payloadRaw = decodeB64(parts[1]); const payload = JSON.parse( decodeURIComponent( payloadRaw.split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('') ) ); return { header, payload }; } catch (ex) { console.error('Token解码失败:', ex); return null; } } static showUpgradeAlert() { const mirrors = Helper.mirrorSites; return Swal.fire({ title: '全自动学习功能说明', html: `

⚠️ 网页脚本有局限性

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

📄 当前脚本

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

🖥️ 客户端工具

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

🔗 前往查看 / 下载

官网文档 · 查看使用说明 & 下载
📦 阿里云盘备用下载 ⚡ 直链下载
▸ 官网无法访问?点击展开备用网址
${mirrors.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(Helper.docUrl, '_blank'); } }); } } // 控制面板类 - 重构后 class ControlPanel { constructor(options = {}) { this.storeKey = 'AuthData'; this.verifyHandler = null; this.startHandler = null; this.vipHandler = null; this.injectStyles(); this.buildDOM(); this.loadSavedData(); this.showPanel(); this.setVIPBtnText(Helper.vipBtnText); this.updateTip(options.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); } `; const swalCss = ` 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 } } `; const betaCss = ` .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); GM_addStyle(swalCss); GM_addStyle(betaCss); } buildDOM() { // 主容器 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.tipEl = document.createElement('p'); this.tipEl.className = 'auth-tip'; this.tipEl.textContent = '您正在使用基础版本,功能可能存在限制'; // 授权码输入 this.codeInput = this.createInput('授权密钥', 'password', 'auth-code'); // 购买链接 const buyLinks = Helper.purchaseLinks; const link1 = this.createLink('buy-link-1', buyLinks[0], '获取授权链接1'); const link2 = this.createLink('buy-link-2', buyLinks[1], '获取授权链接2'); // 验证按钮 this.verifyBtn = document.createElement('button'); this.verifyBtn.className = 'auth-button'; this.verifyBtn.innerHTML = ` 验证授权码 `; this.verifyBtn.onclick = () => this.triggerVerify(); // 控制区 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;'; // VIP按钮 this.premiumBtn = document.createElement('button'); this.premiumBtn.className = 'vip-btn glow-effect'; this.premiumBtn.innerHTML = ` 高级功能-全自动挂机 `; this.premiumBtn.addEventListener('click', () => this.handleVipClick()); // 计时器 this.timerEl = document.createElement('div'); this.timerEl.className = 'timer'; this.timerEl.textContent = '运行时间: 00:00:00'; this.timerEl.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.triggerStart(); // 错误提示 this.errorEl = document.createElement('div'); this.errorEl.className = 'error-message'; // 组装 this.controls.append(this.premiumBtn, this.timerEl, this.runBtn); this.root.append(header, this.tipEl, this.codeInput.container, link1, link2, this.verifyBtn, this.controls, this.errorEl); document.body.appendChild(this.root); this.createToggleBtn(); } createToggleBtn() { this.toggleBtn = document.createElement('button'); this.toggleBtn.className = 'window-toggle'; this.toggleBtn.innerHTML = ` 展开面板 `; const btnStyle = ` 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.style.cssText = btnStyle; // 悬停效果 this.toggleBtn.addEventListener('mouseenter', () => { this.toggleBtn.style.transform = 'translateY(-2px)'; this.toggleBtn.style.boxShadow = '0 6px 16px rgba(0,0,0,0.2)'; }); this.toggleBtn.addEventListener('mouseleave', () => { this.toggleBtn.style.transform = 'none'; this.toggleBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'; }); // 点击切换 this.toggleBtn.onclick = () => { const isHidden = this.root.style.display === 'none'; this.root.style.display = isHidden ? 'block' : 'none'; const icon = this.toggleBtn.querySelector('.toggle-icon'); const text = this.toggleBtn.querySelector('.toggle-text'); icon.style.transform = isHidden ? 'none' : 'rotate(180deg)'; text.textContent = isHidden ? '收起面板' : '展开面板'; if (isHidden) { this.root.animate([ { opacity: 0, transform: 'translateY(20px)' }, { opacity: 1, transform: 'none' } ], { duration: 300, easing: 'ease-out' }); } }; document.body.appendChild(this.toggleBtn); } createInput(label, type, id) { const wrap = document.createElement('div'); wrap.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; wrap.append(lbl, input); return { container: wrap, input }; } createLink(id, url, text) { const a = document.createElement('a'); a.id = id; a.href = url; 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.addEventListener('mouseenter', () => { a.style.opacity = '0.8'; a.style.textDecoration = 'underline'; }); a.addEventListener('mouseleave', () => { a.style.opacity = '1'; a.style.textDecoration = 'none'; }); return a; } showPanel() { setTimeout(() => this.root.classList.add('visible'), 100); } showError(msg) { this.errorEl.textContent = msg; this.errorEl.style.display = 'block'; setTimeout(() => { this.errorEl.style.display = 'none'; }, 5000); } async triggerVerify() { const data = { key: this.codeInput.input.value }; console.log("验证数据:", data); if (!data.key || !/^[A-Z0-9]{16}$/.test(data.key)) { Swal.fire({ title: "授权码不正确,应为16位", text: "请正确输入!", icon: 'info', confirmButtonText: '确定', }); return; } if (this.verifyHandler) { const ok = await this.verifyHandler(data); if (ok) { GM_setValue(this.storeKey, JSON.stringify(data)); } } } handleVipClick() { if (this.vipHandler) { this.vipHandler(); } else { Swal.fire({ title: "提示", text: "请在视频播放页面使用!", icon: 'info', confirmButtonText: '确定', willClose: () => { console.log('用户确认错误,脚本已停止'); } }); } } loadSavedData() { let saved = GM_getValue(this.storeKey); if (saved) { try { saved = JSON.parse(saved); this.codeInput.input.value = saved.key || ''; } catch (e) { console.error("加载保存数据失败:", e); } } } triggerStart() { if (this.isRunning) return; this.isRunning = true; this.startTime = Date.now(); this.runBtn.innerHTML = ` 运行中... `; this.runBtn.style.backgroundColor = '#e67e22'; this.runBtn.disabled = true; this.timerId = setInterval(() => { const elapsed = Date.now() - this.startTime; const h = Math.floor(elapsed / 3600000); const m = Math.floor((elapsed % 3600000) / 60000); const s = Math.floor((elapsed % 60000) / 1000); this.timerEl.textContent = `运行时间: ${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`; }, 1000); if (this.startHandler) { this.startHandler(); } } updateTip(text) { this.tipEl.innerText = text; } setVIPBtnText(text) { this.premiumBtn.innerHTML = ` ${text} `; } // 属性设置器 set onVerify(fn) { this.verifyHandler = fn; } set onStart(fn) { this.startHandler = fn; } set onVipClick(fn) { this.vipHandler = fn; } } // 启动入口 new MainEntry();