// ==UserScript== // @name 智慧树共享课刷课(你的页面专属适配) // @namespace zhihuishu-your-page-fit // @version 11.0.0 // @description 针对你的智慧树页面专属适配,100%识别共享课+可拖动+自动刷课 // @author 专属适配 // @match *://onlineweb.zhihuishu.com/onlinestuh5* // @match *://studyvideoh5.zhihuishu.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @connect tk.enncy.cn // @run-at document-end // ==/UserScript== (function () { 'use strict'; // ===================== 核心配置 ===================== const CONFIG = { watchMinutes: 25, // 单课刷课时长 playbackRate: 1.25, // 倍速 autoSwitch: true, // 自动切课 }; // 言溪题库 const BANK_API = "https://tk.enncy.cn/query"; const BANK_TOKEN = "0abc866e094c4714936e88a84ae3cb93"; // 全局变量 let state = { running: false, currentIndex: 0, currentTime: 0, totalCourses: 0, timer: null, }; let courseList = []; let selectedCourses = []; let panel = null; let isDragging = false; // ===================== 【核心】精准获取你的共享课 ===================== function getCourses() { let list = []; // ----------------===== 你的页面专属精准选择器 =====---------------- // 完全匹配你截图里的DOM:#sharingClassed 里的 .datalist 下的 dl 课程卡片 const courseElements = document.querySelectorAll("#sharingClassed .datalist dl"); courseElements.forEach((el, index) => { // 提取课程标题(精准过滤) const titleEl = el.querySelector("dt h3, dt .course-title, dt"); let title = ""; if (titleEl) { title = titleEl.textContent.trim().replace(/\s+/g, " "); } else { // 兜底提取标题 title = el.innerText.trim().split("在学:")[0].split("进度:")[0].trim(); } // 过滤无效内容 if (!title || title.length < 4) return; if (list.some(item => item.title === title)) return; list.push({ id: `course_${index}`, index: index, title: title, element: el }); }); courseList = list; console.log("【脚本调试】找到课程:", list); // 控制台可以看到找到的课程 return list; } // ===================== 监听DOM变化,自动刷新课程 ===================== function watchDomChange() { const observer = new MutationObserver(() => { // 课程列表有变化,自动刷新 if (document.querySelector("#sharingClassed .datalist")) { refreshCourseList(); } }); observer.observe(document.body, { childList: true, subtree: true }); } // ===================== 可拖动面板 ===================== function createPanel() { const oldPanel = document.getElementById("zhs-panel"); if (oldPanel) oldPanel.remove(); panel = document.createElement("div"); panel.id = "zhs-panel"; panel.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 320px; background: #161d30; border-radius: 12px; box-shadow: 0 0 20px rgba(0,0,0,0.6); z-index: 999999; font-family: system-ui; color: #fff; overflow: hidden; `; panel.innerHTML = `
智慧树共享课刷课
正在加载课程...
状态: 未运行
当前: 0/0
计时: 00:00/${CONFIG.watchMinutes}分钟
`; document.body.appendChild(panel); initDrag(); } // 拖动功能 function initDrag() { const header = panel.querySelector(".panel-header"); header.addEventListener("mousedown", (e) => { isDragging = true; const rect = panel.getBoundingClientRect(); const offsetX = e.clientX - rect.left; const offsetY = e.clientY - rect.top; const moveHandler = (e) => { if (!isDragging) return; let x = e.clientX - offsetX; let y = e.clientY - offsetY; // 边界限制 x = Math.max(0, Math.min(x, window.innerWidth - panel.offsetWidth)); y = Math.max(0, Math.min(y, window.innerHeight - panel.offsetHeight)); panel.style.left = x + "px"; panel.style.top = y + "px"; panel.style.right = "unset"; }; const upHandler = () => { isDragging = false; document.removeEventListener("mousemove", moveHandler); document.removeEventListener("mouseup", upHandler); }; document.addEventListener("mousemove", moveHandler); document.addEventListener("mouseup", upHandler); e.preventDefault(); }); } // 刷新课程列表 function refreshCourseList() { const list = getCourses(); const container = document.getElementById("courseList"); if (list.length === 0) { container.innerHTML = `
未找到课程,请确保在共享课标签页
`; return; } let html = ""; list.forEach(course => { const checked = selectedCourses.some(item => item.id === course.id) ? "checked" : ""; html += `
`; }); container.innerHTML = html; // 绑定勾选事件 bindCheckEvent(); updateUI(); } // 勾选事件 function bindCheckEvent() { document.querySelectorAll("#courseList input[type=checkbox]").forEach(input => { input.onchange = () => { const courseId = input.id; const course = courseList.find(item => item.id === courseId); if (input.checked) { if (!selectedCourses.some(item => item.id === courseId)) { selectedCourses.push(course); } } else { selectedCourses = selectedCourses.filter(item => item.id !== courseId); } updateUI(); }; }); } // ===================== 刷课核心逻辑 ===================== function start() { if (selectedCourses.length === 0) { alert("请先勾选要刷的课程!"); return; } if (state.running) return; state.running = true; state.currentTime = 0; state.currentIndex = 0; updateUI(); openCourse(); } function stop() { state.running = false; clearInterval(state.timer); updateUI(); } function openCourse() { if (!state.running) return; if (state.currentIndex >= selectedCourses.length) { alert("✅ 全部课程刷完!"); stop(); return; } const course = selectedCourses[state.currentIndex]; course.element.click(); updateUI(); // 进入课程后启动计时 setTimeout(() => { startTimer(); setupVideo(); startPopupHandler(); }, 3000); } function startTimer() { clearInterval(state.timer); state.timer = setInterval(() => { if (!state.running) return; state.currentTime++; updateUI(); // 时长到了,切课 if (state.currentTime >= CONFIG.watchMinutes * 60) { clearInterval(state.timer); state.currentTime = 0; state.currentIndex++; backToList(); setTimeout(openCourse, 3000); } }, 1000); } function backToList() { const backBtn = document.querySelector('a:has-text("返回学堂"), .back-btn'); if (backBtn) { backBtn.click(); } else { window.location.href = "https://onlineweb.zhihuishu.com/onlinestuh5"; } } function setupVideo() { let tryCount = 0; const timer = setInterval(() => { const video = document.querySelector("video"); if (video) { clearInterval(timer); video.playbackRate = CONFIG.playbackRate; video.play().catch(() => { }); // 自动续播下一节 video.addEventListener("ended", () => { setTimeout(() => { document.querySelector(".next-btn, .nav-next")?.click(); }, 1500); }); } if (tryCount > 30) clearInterval(timer); tryCount++; }, 500); } // 弹窗&答题处理 function startPopupHandler() { setInterval(() => { // 关闭挂机弹窗 document.querySelectorAll('.continue-btn, .confirm-btn, .dialog-ok, .close')?.forEach(btn => btn.click()); // 弹题处理 const questionPopup = document.querySelector('.question-modal, .test-popup'); if (questionPopup) handleQuestion(questionPopup); }, 2000); } async function handleQuestion(popup) { if (popup.dataset.done) return; popup.dataset.done = "true"; const stem = popup.querySelector('.question-stem, .question-title')?.textContent?.trim() || ""; const options = Array.from(popup.querySelectorAll('.option-item, .answer-option')); if (!stem || options.length === 0) { popup.dataset.done = ""; return; } const optionTexts = options.map(el => el.textContent.trim()); // 搜题 let answers = await searchBank(stem, optionTexts); // 随机选择兜底 if (answers.length === 0) { answers = [optionTexts[Math.floor(Math.random() * optionTexts.length)]]; } // 点击选项 answers.forEach(ans => { const target = options.find(el => el.textContent.includes(ans)); target?.click(); }); // 提交 setTimeout(() => { popup.querySelector('.submit-btn, .confirm-btn')?.click(); popup.dataset.done = ""; }, 1000); } async function searchBank(title, options) { return new Promise((resolve) => { const params = new URLSearchParams({ token: BANK_TOKEN, title: title, options: options.join("\n"), type: "single" }); GM_xmlhttpRequest({ url: `${BANK_API}?${params.toString()}`, method: "GET", timeout: 3000, onload: (res) => { try { const data = JSON.parse(res.responseText); if (data.code === 0 && data.data?.answer) { resolve(Array.isArray(data.data.answer) ? data.data.answer : [data.data.answer]); } else { resolve([]); } } catch (e) { resolve([]); } }, onerror: () => resolve([]), ontimeout: () => resolve([]) }); }); } // ===================== UI更新 ===================== function updateUI() { document.getElementById("status").textContent = state.running ? "运行中" : "未运行"; document.getElementById("current").textContent = `${state.currentIndex + 1}/${selectedCourses.length}`; const m = Math.floor(state.currentTime / 60).toString().padStart(2, "0"); const s = (state.currentTime % 60).toString().padStart(2, "0"); document.getElementById("time").textContent = `${m}:${s}/${CONFIG.watchMinutes}分钟`; document.getElementById("progress").style.width = `${Math.min((state.currentTime / (CONFIG.watchMinutes * 60)) * 100, 100)}%`; } // ===================== 事件绑定 ===================== function bindEvents() { document.getElementById("refreshBtn").onclick = refreshCourseList; document.getElementById("startBtn").onclick = start; document.getElementById("stopBtn").onclick = stop; } // ===================== 初始化 ===================== window.addEventListener("load", () => { createPanel(); bindEvents(); watchDomChange(); // 延迟3秒加载课程,等Vue渲染完成 setTimeout(() => { refreshCourseList(); }, 3000); }); })();