// ==UserScript== // @name 超星学习通自动答题(章节) // @namespace http://tampermonkey.net/ // @version 1.0.0 // @description 学习通章节答题 // @author dmhnb6 (Modified by AI) // @match *://*.chaoxing.com/* // @match *://*.edu.cn/* // @grant GM_xmlhttpRequest // @connect api.deepseek.com // @original-author dmhnb6 // @original-license MIT // @original-script https://scriptcat.org/zh-CN/script-show-page/6071 // ==/UserScript== (function() { 'use strict'; // ======== 用户配置区 ======== const API_KEY = 'API'; const DELAY = 1000; // 适中的延迟,保证稳定 // =========================== let isPaused = false; let isRunning = false; let currentIdx = 0; let uiCreated = false; const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); let panel, progressBar, progressText, statusLabel, startBtn, pauseBtn; function createUI() { if (uiCreated) return; uiCreated = true; panel = document.createElement('div'); panel.style = "position:fixed;top:20px;right:20px;z-index:2147483647;width:320px;background:#fff;padding:15px;border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,0.4);font-family:sans-serif;border:2px solid #8e44ad;"; panel.innerHTML = `
🎯 答题助手 已就绪
等待开始...
`; 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 ? '已暂停' : '运行中'; }; } async function getAIResponse(question, options, type) { // 【核心恢复】:恢复 V5 原汁原味的高效 Prompt let sys = "你是一个专业的大学考试答题专家。请先在心里一步步分析题目,然后**必须**将最终答案放在英文方括号内,格式如:[A] 或 [ABC] 或 [正确]。除了方括号内的答案,不要输出多余的解释。"; // 只有遇到填空题时,才追加填空题的格式要求 if (type.includes("填空")) { 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 ? '选项:\n' + options : ''}` }], temperature: 0.1 }), onload: (res) => { try { let content = JSON.parse(res.responseText).choices[0].message.content.trim(); let match = content.match(/\[(.*?)\]/); if (match) { resolve(match[1]); } else { resolve(content); } } catch { resolve(null); } }, onerror: () => resolve(null) }); }); } async function startSolve() { let sheetItems = document.querySelectorAll('.questionLi, .TiMu'); const total = sheetItems.length; if (total === 0) { alert("未找到题目!"); isRunning = false; startBtn.style.display = 'inline-block'; pauseBtn.style.display = 'none'; return; } for (; currentIdx < total; currentIdx++) { while (isPaused) { await sleep(300); } const percent = Math.floor(((currentIdx + 1) / total) * 100); progressBar.style.width = `${percent}%`; progressText.innerText = `${currentIdx + 1} / ${total} (${percent}%)`; const q = sheetItems[currentIdx]; q.scrollIntoView({ behavior: 'smooth', block: 'center' }); await sleep(300); const titleEl = q.querySelector('h3.mark_name, div.mark_name, .Zy_TItle .clearfix'); let typeText = titleEl ? titleEl.innerText : ""; let type = typeText.includes('多选') ? "多选题" : typeText.includes('单选') ? "单选题" : typeText.includes('判断') ? "判断题" : typeText.includes('填空') ? "填空题" : "未知"; const questionText = typeText.replace(/【.*?】/, '').replace(/\s+/g, ' ').trim(); statusLabel.innerText = `答题中: 第 ${currentIdx + 1} 题...`; if (type.includes("填空") || type.includes("简答")) { const response = await getAIResponse(questionText, null, type); if (response) { const answers = type.includes("填空") ? response.split('###') : [response]; let fillIndex = 0; // 【核心保留】:保留 V6 的强力富文本注入代码 if (window.unsafeWindow && window.unsafeWindow.UE && window.unsafeWindow.UE.instants) { for (let key in window.unsafeWindow.UE.instants) { let ue = window.unsafeWindow.UE.instants[key]; if (q.contains(ue.container) && fillIndex < answers.length) { let ansText = answers[fillIndex] ? answers[fillIndex].trim() : ""; try { ue.ready(() => { ue.setContent(ansText); }); } catch(e) {} fillIndex++; } } } if (fillIndex === 0) { const textareas = q.querySelectorAll('textarea'); for(let i=0; i opt.innerText.trim()).join('\n'); const result = await getAIResponse(questionText, opts, type); if (result) { const resUpper = result.toUpperCase(); optionElements.forEach(opt => { const letterEl = opt.querySelector('[class*="num_option"], i.fl'); const letter = letterEl ? letterEl.innerText.trim().toUpperCase() : opt.innerText.trim().charAt(0).toUpperCase(); let shouldClick = false; if (letter && resUpper.includes(letter)) shouldClick = true; else if ((resUpper.includes("正确") || resUpper === "A" || resUpper === "√" || resUpper === "对") && (opt.innerText.includes("正确") || opt.innerText.includes("√") || opt.innerText.includes("对"))) shouldClick = true; else if ((resUpper.includes("错误") || resUpper === "B" || resUpper === "×" || resUpper === "错") && (opt.innerText.includes("错误") || opt.innerText.includes("×") || opt.innerText.includes("错"))) shouldClick = true; if (shouldClick) { const isChecked = opt.getAttribute('aria-checked') === 'true' || opt.querySelector('input:checked'); if (!isChecked) { const clickTarget = opt.querySelector('label, input') || opt; clickTarget.click(); } } }); } } statusLabel.innerText = `第 ${currentIdx + 1} 题完成...`; await sleep(DELAY + Math.random() * 300); } isRunning = false; statusLabel.innerText = "全部作答完成"; pauseBtn.style.display = 'none'; startBtn.style.display = 'inline-block'; startBtn.innerText = '重新开始'; alert("作答完毕!"); } setInterval(() => { if (!uiCreated && document.querySelectorAll('.questionLi, .TiMu').length > 0) { createUI(); } }, 1000); })();