// ==UserScript== // @name 超星学习通自动答题 - 终极适配版 // @namespace http://tampermonkey.net/ // @version 1.9.2 // @description DeepSeek搜题 + 自动翻页 + 进度监控 + 全题型适配 + 暂停功能 // @author dmhnb6 // @match *://mooc1.chaoxing.com/mooc-ans/mooc2/work/dowork* // @grant GM_xmlhttpRequest // @connect api.deepseek.com // ==/UserScript== (function() { 'use strict'; // ======== 用户配置区 ======== const API_KEY = '您的_DEEPSEEK_API_KEY'; const DELAY = 100; // 每题基础间隔(毫秒) // =========================== let isPaused = false; let isRunning = false; let currentIdx = 0; // 全局进度变量:支持暂停后继续和重新开始 const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // UI 组件变量 let progressBar, progressText, statusLabel, startBtn, pauseBtn; // 创建 UI 控制面板 function createUI() { const panel = document.createElement('div'); panel.style = "position:fixed;top:10px;left:50%;transform:translateX(-50%);z-index:10000;width:420px;background:#fff;padding:15px;border-radius:10px;box-shadow:0 4px 15px rgba(0,0,0,0.3);font-family:sans-serif;border:1px solid #ddd;"; panel.innerHTML = `
学习通答题助手 v1.9.2 待命
准备就绪
`; document.body.appendChild(panel); progressBar = document.getElementById('auto-progress-bar'); progressText = document.getElementById('auto-progress-text'); statusLabel = document.getElementById('auto-status-label'); startBtn = document.getElementById('auto-start-btn'); pauseBtn = document.getElementById('auto-pause-btn'); // 开始/重新开始按钮点击事件 startBtn.onclick = () => { if (!isRunning) { currentIdx = 0; // 重新开始时将索引归零 isRunning = true; isPaused = false; startBtn.style.display = 'none'; pauseBtn.style.display = 'inline-block'; pauseBtn.innerText = '暂停'; pauseBtn.style.background = '#e74c3c'; startSolve(); } }; // 暂停/恢复按钮点击事件 pauseBtn.onclick = () => { isPaused = !isPaused; pauseBtn.innerText = isPaused ? '恢复' : '暂停'; pauseBtn.style.background = isPaused ? '#f1c40f' : '#e74c3c'; statusLabel.innerText = isPaused ? '已暂停' : '运行中'; }; } // 调用 DeepSeek API async function getAIResponse(question, options, type) { let sys = "你是一个助手。"; if (type === "单选题" || type === "判断题") sys = "只回答案字母或'正确'/'错误',不解释。"; else if (type === "多选题") sys = "只回答正确字母组合,如ABC,不解释。"; else if (type === "填空题") sys = "多空答案用###分隔,不解释。"; else if (type === "简答题") sys = "提供精炼答案内容。"; return new Promise((resolve) => { GM_xmlhttpRequest({ method: "POST", url: "https://api.deepseek.com/chat/completions", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${API_KEY}` }, data: JSON.stringify({ model: "deepseek-chat", messages: [{ role: "system", content: sys }, { role: "user", content: `题型:${type}\n题目:${question}\n${options ? '选项:' + options : ''}` }], temperature: 0.1 }), onload: (res) => { try { resolve(JSON.parse(res.responseText).choices[0].message.content.trim()); } catch { resolve(null); } }, onerror: () => resolve(null) }); }); } async function startSolve() { const sheetItems = document.querySelectorAll('.topicNumber_list li'); const total = sheetItems.length; // 使用外部作用域的 currentIdx 实现断点续答 for (; currentIdx < total; currentIdx++) { // 暂停检查点 while (isPaused) { await sleep(300); } // 更新进度 UI const percent = Math.floor(((currentIdx + 1) / total) * 100); progressBar.style.width = `${percent}%`; progressText.innerText = `${currentIdx + 1} / ${total} (${percent}%)`; const item = sheetItems[currentIdx]; statusLabel.innerText = `跳转至第 ${currentIdx + 1} 题...`; item.click(); await sleep(200); const qId = item.getAttribute('data'); const q = document.querySelector(`.questionLi[data="${qId}"]`) || document.querySelector('.questionLi'); if (q) { const type = q.getAttribute('typeName') || "单选题"; const titleEl = q.querySelector('h3.mark_name'); const questionText = titleEl ? titleEl.innerText.replace(/\s+/g, ' ').trim() : ""; statusLabel.innerText = `正在搜题: 第 ${currentIdx + 1} 题...`; if (type === "填空题" || type === "简答题") { const response = await getAIResponse(questionText, null, type); if (response) { const answers = type === "填空题" ? response.split('###') : [response]; const editors = q.querySelectorAll('textarea[id^="answer"]'); for (let idx = 0; idx < editors.length; idx++) { const editorId = editors[idx].id; if (window.unsafeWindow && window.unsafeWindow.UE) { try { const ue = window.unsafeWindow.UE.getEditor(editorId); ue.ready(() => { ue.setContent(answers[idx] || answers[0]); if (window.unsafeWindow.loadEditorAnswerd) window.unsafeWindow.loadEditorAnswerd(qId, type === "填空题" ? 2 : 4); }); } catch(e) {} } } } } else { const optionElements = q.querySelectorAll('.answerBg'); let opts = Array.from(optionElements).map(opt => opt.innerText.trim()).join(' | '); const result = await getAIResponse(questionText, opts, type); if (result) { const resUpper = result.toUpperCase(); optionElements.forEach(opt => { const letter = opt.querySelector('[class*="num_option"]')?.innerText.trim().toUpperCase(); if (letter && resUpper.includes(letter)) { if (opt.getAttribute('aria-checked') !== 'true') opt.click(); } else if ((resUpper.includes("正确") || resUpper === "A") && opt.innerText.includes("正确")) { opt.click(); } else if ((resUpper.includes("错误") || resUpper === "B") && opt.innerText.includes("错误")) { opt.click(); } }); } } } statusLabel.innerText = `第 ${currentIdx + 1} 题已完成,休息中...`; await sleep(DELAY + Math.random() * 200); } // 运行结束后的重置逻辑 isRunning = false; statusLabel.innerText = "全部作答完成"; pauseBtn.style.display = 'none'; startBtn.style.display = 'inline-block'; startBtn.innerText = '重新开始'; alert("作答完毕,请人工检查后提交。\n(多次运行可提高正确率)"); } window.addEventListener('load', () => setTimeout(createUI, 2000)); })();