// ==UserScript== // @name 江西继续医学教育-北京健康在线-好医生继续医学教育课助手 // @version 2.0.2 // @description 好医生课程视频倍速与跳过,考试自动答题并自动切换下一节(含深度 Firefox UA 伪装、自动点击历史进度、悬浮窗底行实时动作显示、倍速持久锁定)。 // @license MIT // @match *://cme.haoyisheng.com/cme/* // @match *://bjsqypx.haoyisheng.com/qypx/bj/* // @match *://*.cmechina.net/cme/* // @match *://*.bokecc.com/* // @match *://*.polyv.net/* // @match *://*.polyv.cn/* // @author wkds995 // @run-at document-start // @grant unsafeWindow // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_openInTab // @grant GM_notification // @grant GM_xmlhttpRequest // ==/UserScript== (function () { 'use strict'; // 1. 深度 UA 伪装(全自包含函数,防止作用域变量未定义报错) function applySpoofing() { var chromeUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"; var targetNav = typeof navigator !== 'undefined' ? navigator : null; if (!targetNav) return; try { var proto = Object.getPrototypeOf(targetNav); var def = function (prop, val) { try { Object.defineProperty(proto, prop, { get: function () { return val; }, configurable: true }); } catch (e) { try { Object.defineProperty(targetNav, prop, { get: function () { return val; }, configurable: true }); } catch (err) {} } }; def('userAgent', chromeUA); def('appVersion', chromeUA.substring(8)); def('vendor', 'Google Inc.'); def('platform', 'Win32'); if (!('userAgentData' in targetNav)) { var uad = { brands: [ { brand: "Chromium", version: "128" }, { brand: "Not;A=Brand", version: "24" }, { brand: "Google Chrome", version: "128" } ], mobile: false, platform: "Windows" }; def('userAgentData', uad); } } catch (e) {} } applySpoofing(); if (typeof unsafeWindow !== 'undefined' && unsafeWindow.navigator) { applySpoofing.call(unsafeWindow); } try { var scriptNode = document.createElement('script'); scriptNode.textContent = '(' + applySpoofing.toString() + ')();'; (document.head || document.documentElement).appendChild(scriptNode); scriptNode.remove(); } catch (e) {} // 第三方播放器域(bokecc / polyv)完成 UA 伪装后即终止主 UI 挂载 var host = location.hostname; if (host.indexOf('bokecc.com') !== -1 || host.indexOf('polyv') !== -1) { return; } // 2. 主页面挂载与业务逻辑 function initMainScript() { try { delete document.querySelector; delete document.querySelectorAll; document.querySelector = Document.prototype.querySelector.bind(document); document.querySelectorAll = Document.prototype.querySelectorAll.bind(document); } catch (e) {} var $ = function (s, root) { root = root || document; try { return (root instanceof Document ? Document.prototype.querySelector : Element.prototype.querySelector).call(root, s); } catch (e) { return root.querySelector ? root.querySelector(s) : null; } }; var $$ = function (s, root) { root = root || document; try { return Array.from((root instanceof Document ? Document.prototype.querySelectorAll : Element.prototype.querySelectorAll).call(root, s)); } catch (e) { return Array.from(root.querySelectorAll ? root.querySelectorAll(s) : []); } }; function addStyle(id, tag, css) { tag = tag || 'style'; css = css || ''; var old = $('#' + id); if (old) old.remove(); var style = document.createElement(tag); style.id = id; if (tag === 'style') { style.innerHTML = css; } else { style.rel = 'stylesheet'; style.href = css; } (document.head || document.body || document.documentElement).appendChild(style); } var getUrlParams = function (name) { return new URLSearchParams(window.location.search).get(name); }; var getLastUrlPath = function () { return window.location.pathname.split('/').pop(); }; var lastPath = getLastUrlPath(); if (typeof unsafeWindow !== 'undefined') { var rawAlert = unsafeWindow.alert; unsafeWindow.alert = function (msg) { if (typeof msg === 'string' && (msg.indexOf("看完课件") !== -1 || msg.indexOf("选修课程") !== -1 || msg.indexOf("暂无") !== -1)) { console.log("[拦截弹窗] 成功阻止阻断弹窗:", msg); return; } return rawAlert ? rawAlert.apply(this, arguments) : undefined; }; } function setBottomStatus(text, color) { color = color || '#38bdf8'; var el = $('#hys-bottom-status'); if (el) { el.innerText = text; el.style.color = color; } } var countdownTimer = null; var isFlowing = false; function startCountdown(seconds, tipText, onComplete, cancelCondition) { if (countdownTimer) clearInterval(countdownTimer); var remain = seconds; var updateTip = function () { var tipEl = $('#hys-remain-tip'); var statusText = remain + 's后' + tipText; if (tipEl) { tipEl.innerText = statusText; tipEl.style.color = '#facc15'; } setBottomStatus('⏱️ ' + statusText, '#facc15'); }; updateTip(); countdownTimer = setInterval(function () { if (cancelCondition && cancelCondition()) { clearInterval(countdownTimer); countdownTimer = null; var tipEl = $('#hys-remain-tip'); if (tipEl) { tipEl.innerText = "已取消跳转"; tipEl.style.color = '#94a3b8'; } setBottomStatus("⏸️ 已取消自动跳转", '#94a3b8'); isFlowing = false; return; } remain--; if (remain > 0) { updateTip(); } else { clearInterval(countdownTimer); countdownTimer = null; onComplete(); } }, 1000); } function stopCountdown(resetTipText) { if (countdownTimer) { clearInterval(countdownTimer); countdownTimer = null; } isFlowing = false; var tipEl = $('#hys-remain-tip'); if (tipEl && resetTipText) { tipEl.innerText = resetTipText; tipEl.style.color = '#94a3b8'; } setBottomStatus(resetTipText || "挂机中", '#94a3b8'); } function doSafeJump(url) { if (!url) return; var urlObj = new URL(url, window.location.href); urlObj.searchParams.set('_t', Date.now().toString()); window.location.href = urlObj.href; } function refreshRightSectionStatus() { try { var cleanUrl = location.pathname + location.search.replace(/&_t=\d+/g, '') + '&_t=' + Date.now(); fetch(cleanUrl, { cache: 'no-store' }).then(function (res) { if (!res.ok) return; return res.text(); }).then(function (html) { if (!html) return; var doc = new DOMParser().parseFromString(html, 'text/html'); ['#s_r_ml', '.s_r_bts'].forEach(function (sel) { var newEl = doc.querySelector(sel), oldEl = $(sel); if (newEl && oldEl) oldEl.innerHTML = newEl.innerHTML; }); }).catch(function () {}); } catch (e) {} } var getNextChoice = function (str) { return str === 'E' ? 'A' : String.fromCharCode(str.charCodeAt(0) + 1); }; function getNextMultipleChoice(str) { var dic = ['ABCDE', 'BCDE', 'ACDE', 'ABDE', 'ABCE', 'ABCD', 'CDE', 'BDE', 'BCE', 'BCD', 'ADE', 'ACE', 'ACD', 'ABE', 'ABD', 'ABC', 'DE', 'CE', 'CD', 'BE', 'BD', 'BC', 'AE', 'AD', 'AC', 'AB', 'E', 'D', 'C', 'B', 'A']; var idx = dic.indexOf(str); return idx === dic.length - 1 ? dic[0] : dic[idx + 1]; } function executeFormSubmit() { setBottomStatus('📤 正在提交考卷...', '#facc15'); var form = $('form[name="form1"]') || $('form'); if (!form) return; form.removeAttribute('target'); if (typeof unsafeWindow !== 'undefined' && typeof unsafeWindow.doSubmit === 'function') { try { unsafeWindow.doSubmit(); return; } catch (e) {} } var tjkj = $('#tjkj') || $('.exam_btn a, .btn1'); if (tjkj) { try { tjkj.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); tjkj.click(); } catch (e) {} } setTimeout(function () { try { HTMLFormElement.prototype.submit.call(form); } catch (e) { try { form.submit(); } catch (err) {} } }, 300); } if (lastPath === 'exam.jsp') { setTimeout(function () { var txt = document.body ? document.body.innerText : ""; if (["已通过考试", "考试已通过", "已完成本节考试"].some(function (k) { return txt.indexOf(k) !== -1; })) { setBottomStatus('✅ 考卷已通过,正在返回...', '#4ade80'); var cId = getUrlParams('course_id'), pId = getUrlParams('paper_id'); if (cId) doSafeJump('study2.jsp?course_id=' + cId + '&courseware_id=' + (pId || '01')); } }, 500); var getQuestionsList = function () { return $$('.exam_list > li, .kaoshi dl'); }; var autoSelectAnswer = function (answerArray) { var indexMap = { 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4 }; var qusListInput = $('input[name="ques_list"]'); if (qusListInput && qusListInput.value) { var qusIds = qusListInput.value.split(',').map(function (s) { return s.trim(); }).filter(Boolean); qusIds.forEach(function (qid, i) { var answer = answerArray[i] || 'A'; $$('input[name="ques_' + qid + '"]').forEach(function (input, idx) { var val = input.value ? input.value.trim().toUpperCase() : ''; if ((val && answer.indexOf(val) !== -1) || idx === indexMap[answer]) { input.checked = true; try { input.click(); } catch(e) {} input.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); input.dispatchEvent(new Event('change', { bubbles: true })); } }); }); return; } getQuestionsList().forEach(function (qBox, i) { var answer = answerArray[i] || 'A'; $$('input[type="radio"], input[type="checkbox"]', qBox).forEach(function (input, idx) { var val = input.value ? input.value.trim().toUpperCase() : ''; if ((val && answer.indexOf(val) !== -1) || idx === indexMap[answer]) { input.checked = true; try { input.click(); } catch(e) {} input.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); input.dispatchEvent(new Event('change', { bubbles: true })); } }); }); }; var startAutoExamFlow = function () { setBottomStatus('✍️ 正在全自动答题中...', '#38bdf8'); var cId = getUrlParams('course_id'), pId = getUrlParams('paper_id'); var examKey = 'correct_ans_' + cId + '_' + pId; var cachedAns = localStorage.getItem(examKey); if (cachedAns) { autoSelectAnswer(JSON.parse(cachedAns)); localStorage.removeItem(examKey); setTimeout(executeFormSubmit, 800); return; } var questionsList = getQuestionsList(); autoSelectAnswer(new Array(questionsList.length || 10).fill('ABCDE')); setTimeout(function () { if (!$('input[type="radio"]:checked, input[type="checkbox"]:checked')) { $$('input[type="radio"]').forEach(function (r, idx) { if (idx % 5 === 0) { r.checked = true; r.click(); } }); } executeFormSubmit(); }, 600); } var examBtn = document.createElement('button'); examBtn.innerText = '⚡ 考试全自动答题'; examBtn.id = 'exam_skip_btn'; examBtn.style.cssText = 'position:absolute;z-index:9999;top:55px;right:150px;padding:8px 16px;cursor:pointer;background:#2563eb;color:#fff;border-radius:10px;box-shadow:0px 0px 12px rgba(0,0,0,.12);border:none;'; examBtn.addEventListener('click', startAutoExamFlow); var container = $('.main') || $('.content'); if (container) container.appendChild(examBtn); var autoFired = false; var examCheckTimer = setInterval(function () { var list = getQuestionsList(); var qusListInput = $('input[name="ques_list"]'); if ((list && list.length > 0) || (qusListInput && qusListInput.value)) { clearInterval(examCheckTimer); if (!autoFired && localStorage.getItem('script_auto_exam') !== 'false') { autoFired = true; setTimeout(startAutoExamFlow, 800); } } else { var startBtn = $$('button, a, input[type="button"], .btn').find(function (btn) { var txt = btn.value || btn.innerText || btn.textContent || ""; return ["开始考试", "立即考试", "确认并开始", "开始答题", "本节考试"].some(function (k) { return txt.indexOf(k) !== -1; }); }); if (startBtn) { startBtn.scrollIntoView({ behavior: 'instant', block: 'center' }); startBtn.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); try { startBtn.click(); } catch (e) {} } } }, 500); return; } if (lastPath === 'examQuizFail.jsp') { var nowAnswerStr = (window.location.search.split('ansList=')[1] || '').split('&')[0] || ''; var nowAnswerList = nowAnswerStr.split(','); var answersList = $$('.answer_list h3'); var finished = true; for (var i = 0; i < answersList.length; i++) { if (answersList[i].className.indexOf('cuo') !== -1) { finished = false; nowAnswerList[i] = nowAnswerList[i].length === 1 ? getNextChoice(nowAnswerList[i]) : getNextMultipleChoice(nowAnswerList[i]); window.location.href = window.location.href.replace(nowAnswerStr, nowAnswerList.join(',')); break; } } if (finished) { var course_id = getUrlParams('course_id'), paper_id = getUrlParams('paper_id'); localStorage.setItem('correct_ans_' + course_id + '_' + paper_id, JSON.stringify(nowAnswerList)); var cxdt = $('#cxdt') || $('.show_exam_btns a'); var backExamUrl = cxdt ? cxdt.href : ('exam.jsp?course_id=' + course_id + '&paper_id=' + paper_id + '&type=7'); setTimeout(function () { doSafeJump(backExamUrl); }, 500); } return; } if (lastPath === 'examQuizPass.jsp') { var pass_course_id = getUrlParams('course_id'), pass_paper_id = getUrlParams('paper_id'); var passTarget = (pass_course_id && pass_paper_id) ? ('study2.jsp?course_id=' + pass_course_id + '&courseware_id=' + pass_paper_id) : (pass_course_id ? ('course.jsp?course_id=' + pass_course_id) : $('.show_exam_btns a, a[href*="course.jsp"], a[href*="study2.jsp"]')?.href); if (passTarget) setTimeout(function () { doSafeJump(passTarget); }, 1800); return; } if (lastPath === 'course.jsp' || lastPath === 'subject2.jsp') { var checkCount = 0; var checkInterval = setInterval(function () { try { var items = $$('li.course_list'); var targetLink = items.map(function (li) { return $('span.wxx', li) ? $('a[onclick*="kjJumpTo"]', li) : null; }).find(Boolean) || items.map(function (li) { return (li.innerText || "").indexOf("待考试") !== -1 ? $('a[onclick*="kjJumpTo"]', li) : null; }).find(Boolean); if (targetLink) { clearInterval(checkInterval); var m = (targetLink.getAttribute('onclick') || '').match(/kjJumpTo\s*\(\s*['"]([^'"]+)['"]/); var targetUrl = m && m[1] ? m[1].replace(/&/g, '&') : ''; targetUrl ? doSafeJump(targetUrl) : targetLink.click(); } else if (++checkCount >= 15) { clearInterval(checkInterval); } } catch (e) {} }, 1000); return; } // 播放引擎与挂机调度 var fuckingPlayer = null; var getStudyMode = function () { return localStorage.getItem('study_mode') === 'skip' ? 'skip' : 'rate'; }; var getTargetRate = function () { var rate = parseFloat(localStorage.getItem('play_back_rate')); return (!isNaN(rate) && rate >= 1 && rate <= 16) ? rate : 6; }; function triggerRealisticClick(el) { if (!el) return; ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click'].forEach(function (evtType) { try { el.dispatchEvent(new MouseEvent(evtType, { bubbles: true, cancelable: true, composed: true })); } catch (err) {} }); try { el.click(); } catch (e) {} } var lastResumeClickTime = 0; function autoClickResumeHistory() { var now = Date.now(); if (now - lastResumeClickTime < 3000) return; var jumpInto = $('#ccH5jumpInto, [id*="jumpInto"]'); if (jumpInto && jumpInto.offsetParent !== null) { var text = (jumpInto.innerText || "").trim(); if (text.indexOf("点击继续") !== -1 || text.indexOf("上次观看到") !== -1) { lastResumeClickTime = now; var childBtn = $('a, span, button', jumpInto); triggerRealisticClick(childBtn || jumpInto); try { jumpInto.style.display = 'none'; } catch (e) {} setBottomStatus('⏩ 已自动恢复历史播放进度', '#4ade80'); } } } var lastPlayCallTime = 0; function forceStartVideoPlay(video) { var now = Date.now(); if (now - lastPlayCallTime < 1500) return; lastPlayCallTime = now; if (!video) video = $('video, .pv-video'); if (video) { video.muted = video.defaultMuted = true; video.volume = 0; ['muted', 'autoplay', 'playsinline'].forEach(function (a) { video.setAttribute(a, 'true'); }); video.play()?.catch?.(function () {}); } var player = unsafeWindow.cc_js_Player || unsafeWindow.player || fuckingPlayer; if (player) { try { player.setVolume?.(0); } catch (e) {} try { player.play?.(); } catch (e) {} try { player.j2s_resumeVideo?.(); } catch (e) {} } setTimeout(function () { if (video && video.paused) { [$('#replaybtn'), $('.ccH5PlayBtn:not([style*="display: none"])'), $('.ccH5PlayBtn2:not([style*="display: none"])')].forEach(function (btn) { triggerRealisticClick(btn); }); } autoClickResumeHistory(); }, 120); } document.addEventListener('click', function () { var v = $('video, .pv-video'); if (v && v.paused && getStudyMode() === 'rate') forceStartVideoPlay(v); }, { capture: true, passive: true }); function executeInstantSkip() { if (getStudyMode() !== 'skip') return; setBottomStatus('⚡ 正在执行秒过跳尾...', '#38bdf8'); var video = $('video, .pv-video'); var player = unsafeWindow.cc_js_Player || unsafeWindow.player || fuckingPlayer; var duration = player?.getDuration?.() || video?.duration || 0; if (isNaN(duration) || duration <= 0) duration = 0; var targetTime = duration > 1 ? duration - 0.5 : 999999; if (video) { video.playbackRate = 1; video.muted = true; video.volume = 0; } if (player) { try { player.setVolume?.(0); player.seek?.(targetTime); player.jumpToTime?.(targetTime); player.play?.(); } catch (e) {} } if (video && video.duration && !isNaN(video.duration)) { try { video.currentTime = Math.max(0, video.duration - 0.5); } catch (e) {} } if (typeof unsafeWindow !== 'undefined') { try { if (unsafeWindow.see) localStorage.setItem(unsafeWindow.see, '1'); if (unsafeWindow.see2) localStorage.setItem(unsafeWindow.see2, String(duration)); localStorage.setItem('see', '1'); localStorage.setItem('see2', String(duration)); unsafeWindow.questionIsOk = true; unsafeWindow.playEnd?.(); unsafeWindow.updatePlayStatus?.(5); } catch (e) {} } forceStartVideoPlay(video); } function bindVideoRateLock(video) { if (!video || video.__rateLocked) return; video.__rateLocked = true; var enforceRate = function () { if (getStudyMode() !== 'rate') { if (video.playbackRate !== 1) video.playbackRate = 1; return; } var target = getTargetRate(); if (Math.abs(video.playbackRate - target) > 0.05) video.playbackRate = target; }; ['play', 'playing', 'loadedmetadata', 'canplay'].forEach(function (evt) { video.addEventListener(evt, enforceRate); }); try { if (unsafeWindow.player && unsafeWindow.player.params) unsafeWindow.player.params.rate_allow_change = true; if (unsafeWindow.cc_js_Player && unsafeWindow.cc_js_Player.params) unsafeWindow.cc_js_Player.params.rate_allow_change = true; } catch (e) {} } setInterval(function () { var targetRate = getStudyMode() === 'rate' ? getTargetRate() : 1; $$('video, .pv-video').forEach(function (v) { bindVideoRateLock(v); if (Math.abs(v.playbackRate - targetRate) > 0.05) v.playbackRate = targetRate; }); }, 1000); function directGotoExam() { setBottomStatus('📝 正在调起考场...', '#facc15'); if (typeof unsafeWindow !== 'undefined') { if (unsafeWindow.see) localStorage.setItem(unsafeWindow.see, '1'); unsafeWindow.questionIsOk = true; } var cId = getUrlParams('course_id') || unsafeWindow?.course_id; var wId = getUrlParams('courseware_id') || unsafeWindow?.courseware_id; if (typeof unsafeWindow !== 'undefined' && typeof unsafeWindow.gotoExam === 'function') { try { unsafeWindow.gotoExam(); return; } catch (e) {} } if (cId && wId) doSafeJump('exam.jsp?course_id=' + cId + '&paper_id=' + wId + '&type=7'); } function getNextUnfinishedTarget(activeLi) { var allItems = $$('#s_r_ml li, .s_r_ml li'); var currentIdx = allItems.indexOf(activeLi); var isFinished = function (txt) { return ["考试通过", "已完成", "已通过"].some(function (k) { return txt.indexOf(k) !== -1; }); }; var targetLi = allItems.slice(currentIdx + 1).find(function (li) { return !isFinished(($('i', li)?.innerText || li.innerText || "").trim()); }) || allItems.filter(function (_, idx) { return idx !== currentIdx; }).find(function (li) { return !isFinished(($('i', li)?.innerText || li.innerText || "").trim()); }); if (targetLi) { var a = $('a', targetLi); var targetUrl = ''; if (a) { var m = (a.getAttribute('onclick') || '').match(/kjJumpTo\s*\(\s*['"]([^'"]+)['"]/); if (m && m[1]) targetUrl = m[1].replace(/&/g, '&'); if (!targetUrl && a.href && !a.href.startsWith('javascript:')) targetUrl = a.href; } return { targetLi: targetLi, a: a, targetUrl: targetUrl }; } return null; } function getSectionRealStatus(activeLi) { var txt = ($('i', activeLi)?.innerText || activeLi.innerText || "").trim(); if (["考试通过", "已完成", "已通过"].some(function (k) { return txt.indexOf(k) !== -1; })) return 'PASSED'; if (txt.indexOf("待考试") !== -1) return 'NEED_EXAM'; return 'LEARNING'; } function handleMainFlow() { if (isFlowing) return; var activeLi = $('#s_r_ml li.active, .s_r_ml li.active'); if (!activeLi) return; autoClickResumeHistory(); var currentStatus = getSectionRealStatus(activeLi); if (currentStatus === 'PASSED') { var nextInfo = getNextUnfinishedTarget(activeLi); if (nextInfo) { isFlowing = true; startCountdown(3, "切下一小节", function () { nextInfo.targetUrl ? doSafeJump(nextInfo.targetUrl) : nextInfo.a?.click(); }); } else { var tipEl = $('#hys-remain-tip'); if (tipEl) { tipEl.innerText = "全部完成"; tipEl.style.color = '#4ade80'; } setBottomStatus('🏆 本课程全部小节已通关!', '#4ade80'); } return; } if (currentStatus === 'NEED_EXAM') { if (localStorage.getItem('script_auto_exam') !== 'false') { isFlowing = true; startCountdown(3, "进入考试", directGotoExam, function () { return localStorage.getItem('script_auto_exam') === 'false'; }); } else { var nextInfo2 = getNextUnfinishedTarget(activeLi); if (nextInfo2) { isFlowing = true; startCountdown(3, "跳过考试切下节", function () { nextInfo2.targetUrl ? doSafeJump(nextInfo2.targetUrl) : nextInfo2.a?.click(); }); } } return; } var video = $('video, .pv-video'); if (!video) return; if (!video.ended && (video.duration <= 0 || video.currentTime < video.duration - 1)) { if (getStudyMode() === 'skip') { executeInstantSkip(); } else { var isBuffering = (video.readyState < 2 || video.seeking); if (video.paused) { if (!isBuffering) { setBottomStatus('⏸️ 模拟点击唤醒播放中...', '#facc15'); forceStartVideoPlay(video); } else setBottomStatus('⏳ 视频高倍速缓冲中...', '#38bdf8'); } else { setBottomStatus(isBuffering ? '⏳ 网络缓冲加载中...' : ('▶ 正在倍速播放中 (' + getTargetRate() + 'x)'), isBuffering ? '#38bdf8' : '#4ade80'); } } } else if (!isFlowing && video.duration > 15 && video.currentTime >= video.duration - 1) { isFlowing = true; setBottomStatus('✅ 本节学时已达标!', '#4ade80'); if (unsafeWindow && unsafeWindow.see) { localStorage.setItem(unsafeWindow.see, '1'); unsafeWindow.questionIsOk = true; } if (localStorage.getItem('script_auto_exam') !== 'false') { startCountdown(3, "进入考试", directGotoExam, function () { return localStorage.getItem('script_auto_exam') === 'false'; }); } else { var nextInfo3 = getNextUnfinishedTarget(activeLi); if (nextInfo3) { startCountdown(3, "切下一节", function () { nextInfo3.targetUrl ? doSafeJump(nextInfo3.targetUrl) : nextInfo3.a?.click(); }); } else doSafeJump(window.location.href); } } } setInterval(handleMainFlow, 1000); function createModernAssistantUI() { var uiCss = '#hys-assistant-panel { position: fixed; top: 60px; right: 20px; width: 215px; background: rgba(22, 24, 30, 0.95); backdrop-filter: blur(14px); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 10px; box-shadow: 0 10px 26px rgba(0,0,0,0.6); color: #e5e7eb; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: 11px; z-index: 999999; padding: 10px 12px; user-select: none; box-sizing: border-box; }' + '.hys-header { display: flex; align-items: center; justify-content: space-between; cursor: move; padding-bottom: 7px; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }' + '.hys-header-left { display: flex; align-items: center; font-weight: 600; font-size: 12px; color: #ffffff; }' + '.hys-status-dot { width: 7px; height: 7px; background-color: #22c55e; border-radius: 50%; margin-right: 6px; box-shadow: 0 0 8px #22c55e; animation: hys-pulse 2s infinite; }' + '@keyframes hys-pulse { 0%, 100% { opacity: 0.6; transform: scale(0.95); } 50% { opacity: 1; transform: scale(1.1); } }' + '.hys-header-right { color: #4ade80; font-size: 11px; font-weight: 600; }' + '.hys-progress-group { margin-top: 8px; }' + '.hys-progress-row { display: flex; justify-content: space-between; margin-bottom: 4px; font-size: 11px; }' + '.hys-progress-label { color: #9ca3af; }' + '.hys-progress-val-blue { color: #38bdf8; font-weight: 600; }' + '.hys-bar-bg { width: 100%; height: 5px; background: rgba(255, 255, 255, 0.1); border-radius: 3px; overflow: hidden; }' + '.hys-bar-fill-blue { height: 100%; width: 0%; background: linear-gradient(90deg, #0284c7, #38bdf8); border-radius: 3px; transition: width 0.3s ease; }' + '.hys-controls { margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(255, 255, 255, 0.08); display: flex; flex-direction: column; gap: 6px; }' + '.hys-checkbox-row { display: flex; justify-content: space-between; align-items: center; }' + '.hys-toggle-item { display: flex; align-items: center; cursor: pointer; }' + '.hys-toggle-item input { cursor: pointer; accent-color: #38bdf8; width: 13px; height: 13px; margin-right: 4px; }' + '.hys-toggle-item span { color: #d1d5db; font-size: 11px; }' + '.hys-rate-wrapper { display: flex; align-items: center; justify-content: space-between; background: rgba(255, 255, 255, 0.05); padding: 4px 6px; border-radius: 6px; }' + '.hys-rate-select { background: #1e293b; color: #38bdf8; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 4px; padding: 1px 4px; font-size: 11px; outline: none; cursor: pointer; }' + '.hys-action-btn { margin-top: 2px; color: #ffffff; border: none; border-radius: 6px; padding: 6px 8px; font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.2s; text-align: center; }' + '.hys-action-btn:hover { filter: brightness(1.1); transform: translateY(-1px); }' + '.hys-action-btn:active { transform: translateY(1px); }' + '.hys-action-tip { margin-top: 6px; font-size: 11px; color: #38bdf8; text-align: center; line-height: 1.3; font-weight: 500; min-height: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }'; addStyle('hys-mini-ui-style', 'style', uiCss); var panel = document.createElement('div'); panel.id = 'hys-assistant-panel'; panel.innerHTML = '
' + '
挂机助手
' + '
运行中
' + '
' + '
' + '
小节进度:-- / --
' + '
' + '
' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '' + '
' + '
正在初始化...
' + '
客服微信:wkds995
'; document.body.appendChild(panel); var rateSelect = $('#hys-rate-select', panel); [1, 1.5, 2, 3, 4, 6, 8, 10, 12, 15, 16].forEach(function (r) { var opt = document.createElement('option'); opt.value = r; opt.innerText = r + 'x'; rateSelect.appendChild(opt); }); var autoSkipCb = $('#hys-auto-skip-cb', panel); var autoExamCb = $('#hys-auto-exam-cb', panel); var rateEnableCb = $('#hys-rate-enable-cb', panel); var actionBtn = $('#hys-action-main-btn', panel); var mode = getStudyMode(); autoSkipCb.checked = (mode === 'skip'); rateEnableCb.checked = (mode === 'rate'); autoExamCb.checked = (localStorage.getItem('script_auto_exam') !== 'false'); rateSelect.value = localStorage.getItem('play_back_rate') || '6'; function syncActionButtonState() { if (getStudyMode() === 'rate') { actionBtn.innerHTML = '▶ 立即倍速播放'; actionBtn.style.background = 'linear-gradient(135deg, #10b981, #059669)'; } else { actionBtn.innerHTML = '⚡ 立即秒过本节'; actionBtn.style.background = 'linear-gradient(135deg, #2563eb, #1d4ed8)'; } } syncActionButtonState(); rateEnableCb.addEventListener('change', function (e) { localStorage.setItem('study_mode', e.target.checked ? 'rate' : 'skip'); autoSkipCb.checked = !e.target.checked; var video = $('video, .pv-video'); if (video && getStudyMode() === 'rate') { video.playbackRate = parseFloat(rateSelect.value) || 6; forceStartVideoPlay(video); } syncActionButtonState(); }); autoSkipCb.addEventListener('change', function (e) { localStorage.setItem('study_mode', e.target.checked ? 'skip' : 'rate'); rateEnableCb.checked = !e.target.checked; if (e.target.checked) { var video = $('video, .pv-video'); if (video) video.playbackRate = 1; executeInstantSkip(); } syncActionButtonState(); }); autoExamCb.addEventListener('change', function (e) { localStorage.setItem('script_auto_exam', JSON.stringify(e.target.checked)); if (!e.target.checked) stopCountdown("已取消开考"); }); rateSelect.addEventListener('change', function (e) { localStorage.setItem('play_back_rate', e.target.value); var video = $('video, .pv-video'); if (video && getStudyMode() === 'rate') video.playbackRate = parseFloat(e.target.value); }); actionBtn.addEventListener('click', function () { var video = $('video, .pv-video'); if (getStudyMode() === 'rate') { if (video) video.playbackRate = parseFloat(rateSelect.value) || 6; forceStartVideoPlay(video); } else { executeInstantSkip(); } }); makeDraggable(panel, $('#hys-drag-handle', panel)); setInterval(function () { updatePanelStats(panel); }, 1000); } function updatePanelStats(panel) { try { var sectionItems = $$('#s_r_ml li, .s_r_ml li, li.course_list'); if (sectionItems.length > 0) { var passedCount = 0, activeIndex = -1; sectionItems.forEach(function (li, idx) { var txt = li.innerText || li.textContent || ""; if (["考试通过", "已完成", "已通过"].some(function (k) { return txt.indexOf(k) !== -1; }) || li.classList.contains("cur")) passedCount++; if (li.classList.contains("active")) activeIndex = idx; }); var total = sectionItems.length; var cwId = parseInt(getUrlParams('courseware_id') || getUrlParams('ware_id'), 10) || 0; var titleEl = $('h1, h2, h3, .title, .video_title'); var match = ((titleEl && titleEl.innerText) || "").match(/第0*(\d+)节/); var titleSecNum = match && match[1] ? parseInt(match[1], 10) : 0; var currentPlayingSec = Math.max(activeIndex + 1, cwId, titleSecNum, 0); var displayProgress = Math.min(total, Math.max(passedCount, currentPlayingSec, 1)); var secText = $('#hys-section-text', panel); if (secText) secText.innerText = displayProgress + ' / ' + total; var secBar = $('#hys-section-bar', panel); if (secBar) secBar.style.width = Math.min(100, Math.round((displayProgress / total) * 100)) + '%'; } if (!countdownTimer) { var tipEl = $('#hys-remain-tip', panel); if (tipEl) { tipEl.style.color = '#4ade80'; tipEl.innerText = getStudyMode() === 'rate' ? (getTargetRate() + 'x 运行') : '秒过模式'; } } } catch (e) {} } function makeDraggable(el, handle) { var posX = 0, posY = 0, mouseX = 0, mouseY = 0; handle.onmousedown = function (e) { e.preventDefault(); mouseX = e.clientX; mouseY = e.clientY; document.onmouseup = function () { document.onmouseup = null; document.onmousemove = null; }; document.onmousemove = function (ev) { ev.preventDefault(); posX = mouseX - ev.clientX; posY = mouseY - ev.clientY; mouseX = ev.clientX; mouseY = ev.clientY; el.style.top = (el.offsetTop - posY) + "px"; el.style.left = (el.offsetLeft - posX) + "px"; el.style.right = 'auto'; }; }; } var p = unsafeWindow.player || unsafeWindow.cc_js_Player; if (p && p.params) { try { p.params.rate_allow_change = true; } catch (e) {} fuckingPlayer = p; } if ($('video, .pv-video, #player, #cc_js_Player, #s_r_ml') || ["polyv", "study2", "cc"].some(function (k) { return lastPath.indexOf(k) !== -1; })) { createModernAssistantUI(); refreshRightSectionStatus(); } handleMainFlow(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initMainScript); } else { initMainScript(); } })();