// ==UserScript== // @name 柳大师 - 学习助手 // @namespace local.liudashi.study-helper // @version 11.0.0 // @description 视频自动播放 + 课件翻页 + AI答题 // @author 柳大师 // @match *://*.chaoxing.com/* // @match *://*.fanya.chaoxing.com/* // @match *://*.edu.cn/* // @match *://*.zhihuishu.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @connect open.bigmodel.cn // @connect * // @run-at document-idle // ==/UserScript== (function () { 'use strict'; if (window._lds_injected) return; window._lds_injected = true; const VERSION = '11.0.0'; const IS_TOP = window.top === window.self; const CFG = { autoPlay: GM_getValue('lds_autoPlay', true), autoNext: GM_getValue('lds_autoNext', true), playbackRate: GM_getValue('lds_rate', 1.5), aiKey: GM_getValue('lds_aiKey', ''), }; function saveCfg() { try { Object.keys(CFG).forEach(k => GM_setValue('lds_' + k, CFG[k])); } catch (e) {} } function setStatus(t) { const el = document.getElementById('lds-status'); if (el) el.textContent = t; } const log = (...a) => console.log('[柳大师]', ...a); // ========== 视频自动播放(每 2 秒检查)========== function autoPlayVideos() { if (!CFG.autoPlay) return; const videos = document.querySelectorAll('video'); videos.forEach(v => { try { // 确保倍速正确 if (Math.abs(v.playbackRate - CFG.playbackRate) > 0.01) { v.playbackRate = CFG.playbackRate; } // 暂停的尝试播放 if (v.paused && !v.ended) { const p = v.play(); if (p && p.catch) { p.catch(() => { // 被浏览器拦截 → 静音重试 if (!v.muted) { v.muted = true; v.play().catch(() => {}); } }); } } } catch (e) {} }); } // ========== 课件自动翻页(每 5 秒检查)========== let lastPptClick = 0; function autoFlipPpt() { if (!CFG.autoNext) return; const now = Date.now(); if (now - lastPptClick < 4000) return; // 防止点太快 const nextSels = [ '.next-btn', '.nextBtn', '.btn-next', '.ppt_next', '.slide-next', '[class*="next-page"]', '[class*="nextPage"]', '[class*="next_page"]', '[title*="下一页"]', '[aria-label*="下一页"]', '.arrow-right', '.icon-next', ]; // 主文档 for (const sel of nextSels) { try { const btns = document.querySelectorAll(sel); for (const b of btns) { const txt = (b.textContent || '').trim(); const title = (b.getAttribute('title') || b.getAttribute('aria-label') || '').trim(); if (/上一页|prev/i.test(txt + title)) continue; if (b.disabled) continue; if (b.offsetParent === null) continue; b.click(); lastPptClick = now; log('📄 点击下一页:', sel); return; } } catch (e) {} } // iframe 内 const iframes = document.querySelectorAll('iframe'); for (const ifr of iframes) { try { const d = ifr.contentDocument; if (!d) continue; for (const sel of nextSels) { const btns = d.querySelectorAll(sel); for (const b of btns) { const txt = (b.textContent || '').trim(); const title = (b.getAttribute('title') || b.getAttribute('aria-label') || '').trim(); if (/上一页|prev/i.test(txt + title)) continue; if (b.disabled || b.offsetParent === null) continue; b.click(); lastPptClick = now; log('📄 点击 iframe 下一页:', sel); return; } } } catch (e) {} } } // ========== 视频结束 → 下一节 ========== function onVideoEnded() { if (!CFG.autoNext) return; const now = Date.now(); if (now - lastPptClick < 30000) return; lastPptClick = now; setStatus('切换下一节...'); log('视频结束,尝试跳转下一节'); // 延迟 5 秒后尝试点击 setTimeout(() => { const nextSels = [ '.next', '.next-btn', '.nextSection', '.next-section', '.chapter-next', '.section-next', '#nextBtn', '[class*="nextBtn"]', '[class*="next"] button', '[title*="下一"]', 'a[href*="next"]', ]; for (const sel of nextSels) { const b = document.querySelector(sel); if (b && b.offsetParent !== null && !b.disabled) { b.click(); log('点击下一节:', sel); return; } } // 文字匹配 const clickables = document.querySelectorAll('a, button, span'); for (const el of clickables) { const t = (el.textContent || '').trim(); if (t.length <= 10 && /^下一[节章课]|继续学习/.test(t) && el.offsetParent !== null) { el.click(); log('点击文字按钮:', t); return; } } }, 5000); } // 监听视频 ended function bindVideoEnded() { document.querySelectorAll('video').forEach(v => { if (v._ldsBound) return; v._ldsBound = true; v.addEventListener('ended', onVideoEnded); }); } // ========== UI ========== function createUI() { if (!IS_TOP) return; // 清理所有旧版本 + 旧实例 ['lds-ball', 'lds-panel', 'sh-ui-host', 'sh-ball', 'sh-sidebar', 'test-ball'] .forEach(id => document.querySelectorAll('#' + id).forEach(el => el.remove())); if (!document.body) { setTimeout(createUI, 500); return; } // ===== 悬浮球 ===== const ball = document.createElement('div'); ball.id = 'lds-ball'; ball.textContent = '🤓'; ball.style.cssText = 'position:fixed;right:24px;top:100px;width:56px;height:56px;border-radius:50%;' + 'background:linear-gradient(135deg,#2f6feb,#5b8dff);color:#fff;font-size:32px;' + 'display:flex;align-items:center;justify-content:center;cursor:pointer;' + 'z-index:2147483647;box-shadow:0 4px 16px rgba(47,111,235,0.5);user-select:none;'; document.body.appendChild(ball); log('✅ 悬浮球已创建'); // ===== 面板 ===== const panel = document.createElement('div'); panel.id = 'lds-panel'; panel.style.cssText = 'position:fixed;right:0;top:0;width:480px;height:100vh;background:#fff;' + 'z-index:2147483646;box-shadow:-4px 0 24px rgba(0,0,0,0.15);' + 'transform:translateX(100%);transition:transform 0.3s ease;' + 'display:flex;flex-direction:column;font-family:-apple-system,"Microsoft YaHei",sans-serif;' + 'color:#1f2328;font-size:15px;'; panel.innerHTML = '