// ==UserScript==
// @name 🚀 超星学习通DeepSeek自动答题|▶️自动刷课|💯视频-章节测试|🏆一键操作|所有题目均可回答
// @namespace http://tampermonkey.net/
// @version 1.0.7
// @description 使用DeepSeek AI大模型答题,所有题目均可回答。超星学习通AI作业答题、全自动刷章节、章节测试自动完成。极致简洁,高效好用。
// @author Daniel
// @match *://*.chaoxing.com/*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_getResourceText
// @resource typrMd5Lib https://116611.xyz/typr-md5.js
// @resource fontTableData https://116611.xyz/table.json
// @license CC-BY-NC-ND-4.0
// @antifeature payment 脚本存在第三方答题接口付费功能
// @icon data:image/png;base64,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dpokU6dMscY8tmn0io2t2VN57QObvE3qPZUsNcxMhnun1GYhbORFlzUjorxV5LmzYGqPud4pMgGKSnGGQBapVC8wpjM6Wl20yFi7atWqNx33prvvvvu/rr76Ix/5yO5Llz788MN5nl9//fVENG3atDzPH3jggYMOOmiPPfZYuXLlE088MWXKlHq9/sILL9x///2nnnrqb37zm5kzZw4NDW3evPnAAw/03j/44IMnnHBCtVrt7e0FcPnlly9YsGBwcPCuu+5697vfLSI33XRTq9WaPn26qj700EOLFi067LDD1q5de999902aNGnSpEk7duy45557Tj/9dGbOsizP856enqeffvqRRx6ZOXPms88+u3jJklPe+tatI6PPrRpac/P/2u0b+/75w/NqZECZoTQxgL48Xjw1mq/or3jR0q9qeywXqFVr2k3XaRRZPX0DxL0zGWLYeV+r1QBMnz79rLPOOv/88y+//HIiqtVqRHTLLbcsX758+fLl4eWdTufaa69NkuTJJ59817velWVZeP6hhx665ZZb5s6de8IJJwBoNBrB4oaGhm6++eYsy4ImfvnLX37hhRfmzJnzhS98AcDNN988bdq0Qw89tPvVrrrqqmnTpj300EMnn3zywMBAeHLVqlW3335btVpLkqTdbo+Ojj711FNnn322MebyK644+OCDG6LP1PoO3z9pzslm+3x+P556/oV1A9OSvkn9Pba/r5Ibf9360RX9lVICKNpFczyXtBKm8Wl8a+cf5PR3QgvOzoV7ziMQas+YMQNArVYLLnn58uWPPfbYggULrrzyyizLZs+e/T//8z+nnXZalmWf/OQnly1bNjY2dsABB6xfv957H7KwM84447jjjvPeT506dXBw8O677161apW1dsmSJccdd1yr1brssstWrVrVarUOPfTQ9evX77777l/+8pdVdZ999vnNb35z9NFHDwwMXHLJJQsWLFi9evXChQsbjebo6CgRee/vuuuuQw45xBjzzW9+c+7cuYcddtiT28bGGJ/eNf3x3tO+vKTvsOZLH+jbcdLmpye9uHL4mTXtF9bORPH4jk6j4wzH3XLjQ03xpMwWxiA1rdG8PdKu9ld1oi/gDYQlIpVKxTmnqmmaDQ+PBD9dFMXLL7/8oQ99SFVfeeWV/fbbL0kSERkdHWt3Oj09Pe122zm37777NpvNnp6eVqsVvPXKlSv32WefYI+Dg4PMfNRRR731rW/96le/esopp0yaNOmwww5bsGDBJZdc8t73vldV161bt8cee0yZMiV48aFt22bPnq2qw8PDBx54YKPREJE8L4IjY+bPfvazu+222/3333/vvffefPPN3vsDB2oH9TpDhGTycKt92T0PpiLfOPOdL7z08v1PPTujGGg6vrLTM5L7emaJqTPWbo16SRMFWyXybK2VsQ3NtJ6wtW+Y/xJRURTBy46PjyeJJUJzfLRWq6nqpk2bRsfGBwcHiej0008//fTTw7u2bduaJlZVrbX/+Z//2b3a9u3bK5VKML2TTjrJORcOY8OGDeecc87UqVMvuuiib3zjG1/84hfPOuusmTNn7hgdzbKMiA455JDrrrsuXGR0dIcvCqiKyNe//vXuxcdGtg30zw/6fuCBB4rIvffee/7552dZ5pyz1sJaAVR0oF777gfPvva+B9aNN/c7YL/eKVMeeOjRfikGvZuUWQ+4wo1uGAcZz0aYWAjKrIktchpdN1buUH3dI6wyKPI8rD1vNZvbR0afWLv15nv+umjhbkT00GNPvNiqBart29/+9qJFi5csXbrH8uVf+tJX6wODqjo8PHLAAQcsXrx46dKly5cvX7NmzdSpUwG0Wi1mHhoa6uvrI6Jnn3/+t7/97cKFC2+99dYLL7zwySefDEIcGd4eMME111wTL75s2Xvec5ZWJ4Ws860nn7xo8eKlS5ctX7788hvuqQzMAPDUypVf/NKXmPncc8/dsWNHOPKY/qsyoZ3nGfScNx212/RBUQxOG5xUrz+zrXXijJ6e1Bh4s2m405ERtsawJ1hhJUZBRJltjXTM2h298/p3lpeWv2VivN1xEqJybdr0mXffffdh++29YLeFcPnPf/u/Y1OWb1y7au7uex588CEPPfLYlCmT99tjyX/+dejRV4aZua+v78QTT3z++ecXLVpU7+np6emx1gLo7e298847jzjiiEql8vhjj7741GNvPemktWvXPvHEE3Pnzj399NOJaOOG9bf+9bkPbdqyZMmSPfbYY8W++6VpesCK5f/7wvjTw55IjTHHH3+8senC3RbMGJzyvSeso8Q5l+f5NVf91/vPOWfBgt2SJHn88cf33mefwvmQRRmmRie/5HfXvf/NJ8zfZSZ8sWbV88q6+8wpb148/ZVRfWF9vnJ95cmi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
// ==/UserScript==
const systemConfig = {
buildTime: new Date().toISOString(),
environment: 'production'
};
class Logger {
constructor(prefix) {
this.prefix = prefix || 'System';
this.levels = ['DEBUG', 'INFO', 'WARN', 'ERROR'];
}
log(level, message) {
if (this.levels.includes(level)) {
const timestamp = new Date().toISOString();
}
}
debug(msg) { this.log('DEBUG', msg); }
info(msg) { this.log('INFO', msg); }
warn(msg) { this.log('WARN', msg); }
error(msg) { this.log('ERROR', msg); }
}
const logger = new Logger('CXHelper');
const browserCheck = {
isChrome: () => /Chrome/.test(navigator.userAgent),
isFirefox: () => /Firefox/.test(navigator.userAgent),
isEdge: () => /Edge/.test(navigator.userAgent),
isSafari: () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)
};
class PerformanceMonitor {
constructor() {
this.metrics = new Map();
this.startTimes = new Map();
}
start(name) {
this.startTimes.set(name, performance.now());
}
end(name) {
const startTime = this.startTimes.get(name);
if (startTime) {
const duration = performance.now() - startTime;
this.metrics.set(name, duration);
this.startTimes.delete(name);
return duration;
}
return 0;
}
getMetric(name) {
return this.metrics.get(name) || 0;
}
}
const perfMonitor = new PerformanceMonitor();
const utils = {
generateId: (length = 8) => {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
},
deepClone: (obj) => {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime());
if (obj instanceof Array) return obj.map(item => utils.deepClone(item));
if (typeof obj === 'object') {
const cloned = {};
Object.keys(obj).forEach(key => {
cloned[key] = utils.deepClone(obj[key]);
});
return cloned;
}
},
debounce: (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
},
throttle: (func, limit) => {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
};
class CacheManager {
constructor(maxSize = 100) {
this.cache = new Map();
this.maxSize = maxSize;
}
set(key, value, ttl = 300000) { // 默认5分钟过期
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
const item = {
value: value,
expiry: Date.now() + ttl
};
this.cache.set(key, item);
}
get(key) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expiry) {
this.cache.delete(key);
return null;
}
return item.value;
}
clear() {
this.cache.clear();
}
}
const cacheManager = new CacheManager();
logger.info('System initialization completed');
(function() {
'use strict';
(function(){
function _b64ToBytes(b64){ const bin = atob(b64); const out = new Uint8Array(bin.length); for(let i=0;i<bin.length;i++) out[i] = bin.charCodeAt(i); return out; }
function _bytesToStr(arr){ let s=''; for(let i=0;i<arr.length;i++) s += String.fromCharCode(arr[i]); return s; }
function _strToBytes(s){ const out = new Uint8Array(s.length); for(let i=0;i<s.length;i++) out[i] = s.charCodeAt(i); return out; }
function _xor(a,b){ const out=new Uint8Array(a.length); for(let i=0;i<a.length;i++) out[i] = a[i] ^ b[i % b.length]; return out; }
const __S = [100, 121, 96, 105, 102, 109, 113, 102, 115, 96, 116, 98, 109, 117, 96, 51, 49, 51, 54].map(c=>c-1);
const __SALT = String.fromCharCode.apply(null, __S);
const __ENC = "idiM9YBNCEBSu80fAcWJtglB3UgCOQSNSUCG2EFbmlWW7AyIJkSb/kgNWgCHsoEA";
function __getDSK(){
try {
const step1 = __ENC.split('').reverse().join('');
const xored = _b64ToBytes(step1);
const plainB64Bytes = _xor(xored, _strToBytes(__SALT));
const plainB64 = _bytesToStr(plainB64Bytes);
return atob(plainB64);
} catch (e) { return ''; }
}
window.__getDeepseekKey = __getDSK;
})();
const DEEPSEEK_API_KEY = (typeof window!=='undefined' && window.__getDeepseekKey) ? window.__getDeepseekKey() : '';
const DEEPSEEK_API_URL = 'https://api.deepseek.com/v1/chat/completions';
let isAnswering = false;
let isStudyingChapters = false;
let studyIntervalId = null;
const STUDY_PERSIST_KEY = 'cx_helper_study_on_v2';
const PANEL_REG_KEY = 'cx_helper_active_panel_v2';
const PANEL_INSTANCE_ID = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
const FRAME_DEPTH = (() => { let d = 0; try { let w = window; while (w !== w.top) { d++; w = w.parent; } } catch { d = 999; } return d; })();
let isActiveOwner = false;
let createdPanelEl = null;
const HEARTBEAT_INTERVAL_MS = 2000;
const STALE_MS = 7000;
let heartbeatTimerId = null;
let lastAutoSkipTs = 0;
let emptyChecksCount = 0;
let lastEmptySectionKey = '';
let recoveryTimerId = null;
const API_BASE = 'https://116611.xyz';
const MONEY_YUAN = '5.00';
const PAY_NAME = 'XHelper 解锁/赞助';
const DEFAULT_PAY = 'wxpay';
const LS_KEY_DEV_ID = 'cxhelper_device_id';
const LS_KEY_FREE = 'cxhelper_free_used';
const LS_KEY_LICENSED = 'cxhelper_licensed';
const POLL_MS_PAY = 3000;
const POLL_MAX_PAY = 100;
const getFreeLimit = (() => {
let cached = null;
return function() {
if (cached != null) return cached;
try {
const b64 = 'JDEw';
const decoded = atob(b64);
const n = parseInt(decoded.replace(/\D/g, ''), 10);
cached = Number.isFinite(n) ? n : 10;
} catch {
cached = 10;
}
return cached;
};
})();
function getDeviceIdPaid() {
try {
let id = localStorage.getItem(LS_KEY_DEV_ID);
if (!id) {
id = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
localStorage.setItem(LS_KEY_DEV_ID, id);
}
return id;
} catch { return 'dev_' + Math.random().toString(36).slice(2); }
}
const DEVICE_ID_PAID = getDeviceIdPaid();
function isLocallyLicensed() {
try { return localStorage.getItem(LS_KEY_LICENSED) === '1'; } catch { return false; }
}
function setLocallyLicensed() {
try { localStorage.setItem(LS_KEY_LICENSED, '1'); } catch {}
}
function getFreeUsedCount() {
try { return parseInt(localStorage.getItem(LS_KEY_FREE) || '0', 10) || 0; } catch { return 0; }
}
function incFreeUsedCount() {
try { const n = getFreeUsedCount() + 1; localStorage.setItem(LS_KEY_FREE, String(n)); return n; } catch { return 0; }
}
async function checkLicensePaid() {
if (isLocallyLicensed()) return true;
try {
const r = await fetch(`${API_BASE}/api/license/status?deviceId=${encodeURIComponent(DEVICE_ID_PAID)}`, { credentials: 'omit' });
const ct = (r.headers.get('content-type') || '').toLowerCase();
const data = ct.includes('application/json') ? await r.json() : await r.text();
const ok = !!(data && data.licensed);
if (ok) setLocallyLicensed();
try { updateTrialBadge(); } catch {}
return ok;
} catch { return false; }
}
async function startPaymentPaid(payType) {
const win = window.open('', '_blank');
try {
const resp = await fetch(`${API_BASE}/api/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: PAY_NAME,
money: MONEY_YUAN,
type: payType || DEFAULT_PAY,
param: DEVICE_ID_PAID
})
});
const html = await resp.text();
win.document.open();
win.document.write(html);
win.document.close();
return true;
} catch (e) {
if (win) win.close();
alert('发起支付失败:' + e.message);
return false;
}
}
async function pollUntilLicensedPaid(onProgress) {
for (let i = 0; i < POLL_MAX_PAY; i++) {
if (onProgress) { try { onProgress(i); } catch {} }
const ok = await checkLicensePaid();
if (ok) { setLocallyLicensed(); return true; }
await new Promise(r => setTimeout(r, POLL_MS_PAY));
}
return false;
}
function showPayModalPaid(messageText) {
return new Promise(resolve => {
const mask = document.createElement('div');
mask.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:999998;';
const box = document.createElement('div');
box.style.cssText = 'position:fixed;left:50%;top:120px;transform:translateX(-50%);width:420px;background:#fff;border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.2);overflow:hidden;z-index:999999;font-family:system-ui,Segoe UI,Arial;';
const msg = messageText || '试用已用完,打赏5元永久解锁哦';
box.innerHTML = (
'<div style="padding:14px 16px;border-bottom:1px solid #f0f0f0;font-weight:600;font-size:13px;">解锁全部功能(永久)</div>' +
'<div style="padding:16px;">' +
'<div style="margin-bottom:12px;font-size:12px;">' + msg + '</div>' +
'<div style="margin-bottom:12px;">' +
'<label style="margin-right:14px;cursor:pointer;font-size:12px;"><input type="radio" name="cx_pay" value="wxpay" checked> 微信</label>' +
'<label style="margin-right:14px;cursor:pointer;font-size:12px;"><input type="radio" name="cx_pay" value="alipay"> 支付宝</label>' +
'<div style="color:#888;font-size:12px;margin-top:6px;">若支付方式不可用请尝试其他支付方式</div>' +
'</div>' +
'<div id="cx_tip_paid" style="color:#555;font-size:12px;">点击"去支付"将打开收银台,完成后此处会自动检测。</div>' +
'</div>' +
'<div style="padding:12px 16px;border-top:1px solid #f0f0f0;text-align:right;">' +
'<button id="cx_cancel_paid" style="padding:8px 14px;border-radius:8px;border:1px solid #ddd;background:#fff;color:#333;margin-right:8px;cursor:pointer;font-size:13px;">取消</button>' +
'<button id="cx_go_pay" style="padding:8px 14px;border-radius:8px;border:none;background:#4f46e5;color:#fff;cursor:pointer;font-size:13px;">去支付</button>' +
'</div>'
);
document.body.appendChild(mask);
document.body.appendChild(box);
const tip = box.querySelector('#cx_tip_paid');
const btnPay = box.querySelector('#cx_go_pay');
const btnCancel = box.querySelector('#cx_cancel_paid');
function close() { try { box.remove(); mask.remove(); } catch {} }
btnCancel.onclick = () => { close(); resolve(false); };
btnPay.onclick = async () => {
btnPay.disabled = true;
btnPay.textContent = '打开收银台...';
const payType = (box.querySelector('input[name="cx_pay"]:checked') || {}).value || DEFAULT_PAY;
const ok = await startPaymentPaid(payType);
if (!ok) { btnPay.disabled = false; btnPay.textContent = '去支付'; return; }
btnPay.textContent = '检测支付中...';
if (tip) tip.innerHTML = '已打开收银台,请完成支付,完成后此处会自动解锁...<br><span style="color:#ff6b35;font-size:12px;margin-top:4px;display:block;">💡 若无法打开支付页面请尝试连接手机热点网络</span>';
const done = await pollUntilLicensedPaid();
if (done) {
if (tip) tip.textContent = '支付成功,正在解锁...';
setLocallyLicensed();
try { updateTrialBadge(); } catch {}
setTimeout(() => { close(); resolve(true); }, 500);
} else {
btnPay.disabled = false;
btnPay.textContent = '去支付';
if (tip) tip.textContent = '未检测到支付完成,可重试或稍后再次打开本面板。';
}
};
});
}
function showFeedbackModal() {
const mask = document.createElement('div');
mask.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:999998;';
const box = document.createElement('div');
box.style.cssText = 'position:fixed;left:50%;top:120px;transform:translateX(-50%);width:400px;background:#fff;border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.2);overflow:hidden;z-index:999999;font-family:system-ui,Segoe UI,Arial;';
box.innerHTML = (
'<div style="padding:16px 20px;border-bottom:1px solid #f0f0f0;font-weight:600;font-size:16px;color:#333;">意见反馈</div>' +
'<div style="padding:24px 20px;text-align:center;">' +
'<div style="margin-bottom:16px;font-size:14px;color:#555;line-height:1.6;">' +
'如果您在使用过程中遇到问题或有任何建议,欢迎通过以下方式联系我们:' +
'</div>' +
'<div style="background:#f8f9fa;border:1px solid #e9ecef;border-radius:8px;padding:16px;margin:16px 0;">' +
'<div style="font-size:16px;font-weight:600;color:#1677ff;margin-bottom:8px;">联系邮箱</div>' +
'<div style="font-size:18px;font-weight:bold;color:#333;cursor:pointer;" onclick="navigator.clipboard.writeText(\'[email protected]\')" title="点击复制">[email protected]</div>' +
'<div style="font-size:12px;color:#666;margin-top:4px;">点击邮箱地址即可复制</div>' +
'</div>' +
'<div style="font-size:13px;color:#888;margin-top:12px;line-height:1.5;">我们将会认真对待每一条反馈,并且尽快回复您的问题。您的建议是我们改进产品的重要动力!</div>' +
'</div>' +
'<div style="padding:12px 20px;border-top:1px solid #f0f0f0;text-align:right;">' +
'<button id="feedback-close" style="padding:8px 16px;border-radius:8px;border:none;background:#1677ff;color:#fff;cursor:pointer;font-size:14px;">关闭</button>' +
'</div>'
);
document.body.appendChild(mask);
document.body.appendChild(box);
const closeBtn = box.querySelector('#feedback-close');
function close() {
try {
box.remove();
mask.remove();
} catch {}
}
closeBtn.onclick = close;
mask.onclick = close;
// 添加复制成功的提示
const emailDiv = box.querySelector('[onclick*="clipboard"]');
if (emailDiv) {
emailDiv.addEventListener('click', function() {
const originalText = this.innerHTML;
this.innerHTML = '✅ 已复制到剪贴板';
this.style.color = '#52c41a';
setTimeout(() => {
this.innerHTML = originalText;
this.style.color = '#333';
}, 2000);
});
}
}
async function ensureAccessAllowed() {
if (await checkLicensePaid()) return true;
const used = getFreeUsedCount();
if (used < getFreeLimit()) { incFreeUsedCount(); try { updateTrialBadge(); } catch {} return true; }
const ok = await showPayModalPaid();
if (ok) { setLocallyLicensed(); try { updateTrialBadge(); } catch {} return true; }
throw new Error('试用已用完,请解锁后继续使用');
}
function getActivePanelRecord() {
try { const raw = localStorage.getItem(PANEL_REG_KEY); return raw ? JSON.parse(raw) : null; } catch { return null; }
}
function setActivePanelRecord(rec) {
try { localStorage.setItem(PANEL_REG_KEY, JSON.stringify(rec)); } catch {}
}
function clearActivePanelRecordIfOwner() {
try {
const cur = getActivePanelRecord();
if (cur && cur.id === PANEL_INSTANCE_ID) {
localStorage.removeItem(PANEL_REG_KEY);
}
} catch {}
}
function shouldWeOwn(current) {
const nowTs = Date.now();
if (!current) return { own: true, ts: nowTs };
if (!current.aliveTs || nowTs - current.aliveTs > STALE_MS) return { own: true, ts: nowTs };
try { if (current.url && current.url !== location.href) return { own: true, ts: nowTs }; } catch {}
if (FRAME_DEPTH > (current.depth || 0)) return { own: true, ts: nowTs };
if (FRAME_DEPTH === (current.depth || 0) && nowTs > (current.ts || 0)) return { own: true, ts: nowTs };
return { own: false, ts: nowTs };
}
function claimOwnership() {
const cur = getActivePanelRecord();
const decision = shouldWeOwn(cur);
if (decision.own) {
setActivePanelRecord({ id: PANEL_INSTANCE_ID, depth: FRAME_DEPTH, ts: decision.ts, aliveTs: Date.now(), url: location.href });
isActiveOwner = true;
} else {
isActiveOwner = false;
}
return isActiveOwner;
}
function startHeartbeat() {
if (heartbeatTimerId) return;
heartbeatTimerId = setInterval(() => {
if (!isActiveOwner) return;
const cur = getActivePanelRecord();
if (!cur || cur.id !== PANEL_INSTANCE_ID) { stopHeartbeat(); return; }
cur.aliveTs = Date.now();
try { cur.url = location.href; } catch {}
setActivePanelRecord(cur);
}, HEARTBEAT_INTERVAL_MS);
}
function stopHeartbeat() { if (heartbeatTimerId) { clearInterval(heartbeatTimerId); heartbeatTimerId = null; } }
const cleanupOwnership = () => {
stopHeartbeat();
clearActivePanelRecordIfOwner();
};
window.addEventListener('beforeunload', cleanupOwnership);
window.addEventListener('pagehide', cleanupOwnership);
function destroyPanelAndStop() {
try {
if (studyIntervalId) { clearInterval(studyIntervalId); studyIntervalId = null; }
isStudyingChapters = false;
isAnswering = false;
stopHeartbeat();
const panel = document.getElementById('answer-helper-panel');
if (panel && panel.parentNode) panel.parentNode.removeChild(panel);
createdPanelEl = null;
} catch {}
}
window.addEventListener('storage', (e) => {
if (e.key !== PANEL_REG_KEY) return;
const rec = getActivePanelRecord();
if (!rec) return;
if (rec.id === PANEL_INSTANCE_ID) {
if (!createdPanelEl) {
try { createdPanelEl = createPanel(); bindPanelEvents(); } catch {}
}
isActiveOwner = true;
startHeartbeat();
} else {
isActiveOwner = false;
destroyPanelAndStop();
}
});
GM_addStyle(`
#answer-helper-panel {
position: fixed;
top: 20px;
left: 20px;
width: 320px;
background: #ffffff;
border-radius: 12px;
padding: 0;
z-index: 9999;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
user-select: none;
}
#answer-helper-header {
cursor: move;
background: #f5f7fa;
border-radius: 12px 12px 0 0;
padding: 0 15px;
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 16px;
font-weight: 600;
color: #333;
}
#answer-helper-header .status-badge {
margin-left: 8px;
}
#answer-helper-header .collapse-btn {
width: 32px;
height: 32px;
border-radius: 8px;
background: #e0e0e0;
border: none;
font-size: 22px;
cursor: pointer;
color: #666;
margin-left: 10px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 1px 2px rgba(0,0,0,0.04);
transition: background 0.2s, color 0.2s;
}
#answer-helper-header .collapse-btn:hover {
background: #1677ff;
color: #fff;
}
.collapse-icon-bar {
display: block;
background: currentColor;
border-radius: 2px;
margin: 0 auto;
}
.collapse-icon-bar.horizontal {
width: 16px;
height: 3px;
}
.collapse-icon-bar.vertical {
width: 3px;
height: 16px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.collapse-btn-inner {
position: relative;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
#answer-helper-content {
padding: 15px;
}
#answer-helper-panel.collapsed #answer-helper-content {
display: none;
}
#answer-helper-panel.collapsed {
width: 180px;
min-width: 120px;
}
#no-task-toast {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 12px 24px;
border-radius: 8px;
font-size: 14px;
z-index: 10000;
animation: fadeInOut 3s ease-in-out forwards;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
@keyframes fadeInOut {
0% { opacity: 0; transform: translateY(-20px); }
10% { opacity: 1; transform: translateY(0); }
90% { opacity: 1; transform: translateY(0); }
100% { opacity: 0; transform: translateY(-20px); }
}
#answer-helper-panel h3 {
margin: 0 0 15px 0;
color: #333;
font-size: 16px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: space-between;
}
#answer-log {
height: 240px;
overflow-y: auto;
border: 1px solid #eef0f5;
border-radius: 8px;
padding: 12px;
margin: 10px 0;
font-size: 13px;
background: #f8f9fa;
}
#answer-log::-webkit-scrollbar {
width: 6px;
}
#answer-log::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
#answer-log::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.log-item {
margin-bottom: 8px;
padding: 8px;
border-radius: 6px;
background: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.success {
color: #00a854;
border-left: 3px solid #00a854;
}
.error {
color: #f5222d;
border-left: 3px solid #f5222d;
}
.debug {
color: #1890ff;
border-left: 3px solid #1890ff;
}
.info {
color: #666;
border-left: 3px solid #666;
}
.button-group {
display: flex;
gap: 8px;
}
.helper-button {
flex: 1;
padding: 8px 12px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.primary-button {
background: #1890ff;
color: white;
}
.primary-button:hover {
background: #40a9ff;
}
.danger-button {
background: #ff4d4f;
color: white;
}
.danger-button:hover {
background: #ff7875;
}
.secondary-button {
background: #f0f0f0;
color: #666;
}
.secondary-button:hover {
background: #d9d9d9;
}
.success-button {
background: #00a854;
color: #fff;
}
.success-button:hover {
background: #36c06a;
}
.status-badge {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: normal;
}
.status-running {
background: #e6f7ff;
color: #1890ff;
}
.status-stopped {
background: #fff1f0;
color: #ff4d4f;
}
.button-icon {
font-size: 14px;
line-height: 1;
}
#debug-page{ display:none !important; }
#answer-helper-panel .cx-trial-badge{
position: absolute;
left: 12px;
bottom: 8px;
color: #888;
font-size: 12px;
pointer-events: none;
}
#answer-helper-content { padding-bottom: 30px; }
`);
function createPanel() {
const panel = document.createElement('div');
panel.id = 'answer-helper-panel';
panel.innerHTML = `
<div id="answer-helper-header">
<span>学习通AI自动答题与刷课助手</span>
<div style="display: flex; align-items: center; gap: 8px;">
<button id="feedback-btn" class="helper-button secondary-button" style="padding: 2px 6px; font-size: 12px; margin: 0; min-width: auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 4px;">
<span class="button-icon" style="margin: 0; font-size: 14px;">💬</span>
</button>
<button class="collapse-btn" title="折叠/展开" style="padding: 2px 6px; font-size: 12px; margin: 0; min-width: auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 4px;">
<span class="collapse-btn-inner">
<span class="collapse-icon-bar horizontal"></span>
</span>
</button>
</div>
</div>
<div id="answer-helper-content">
<div id="answer-log"></div>
<div class="button-group">
<button id="start-answer" class="helper-button primary-button">
<span class="button-icon">▶</span>
开始答题
</button>
<button id="pause-answer" class="helper-button danger-button" style="display: none;">
<span class="button-icon">⏸</span>
暂停答题
</button>
</div>
<div class="button-group" style="margin-top: 8px;">
<button id="start-study" class="helper-button success-button">
<span class="button-icon">⏯</span>
开始刷章节
</button>
<button id="pause-study" class="helper-button danger-button" style="display: none;">
<span class="button-icon">■</span>
暂停刷章节
</button>
</div>
<div class="button-group" style="margin-top: 8px;">
<button id="buy-license" class="helper-button secondary-button">
<span class="button-icon">💳</span>
购买授权
</button>
</div>
<div class="button-group" style="margin-top: 8px;">
<button id="debug-page" class="helper-button secondary-button">
<span class="button-icon">🔍</span>
调试页面
</button>
</div>
</div>
<div id="cx_trial_badge" class="cx-trial-badge">检测中...</div>
`;
document.body.appendChild(panel);
let isDragging = false, offsetX = 0, offsetY = 0;
const header = panel.querySelector('#answer-helper-header');
header.addEventListener('mousedown', function(e) {
if (e.target.classList.contains('collapse-btn')) return;
isDragging = true;
const rect = panel.getBoundingClientRect();
offsetX = e.clientX - rect.left;
offsetY = e.clientY - rect.top;
document.body.style.userSelect = 'none';
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
panel.style.left = (e.clientX - offsetX) + 'px';
panel.style.top = (e.clientY - offsetY) + 'px';
panel.style.right = 'auto';
});
document.addEventListener('mouseup', function() {
isDragging = false;
document.body.style.userSelect = '';
});
const collapseBtn = panel.querySelector('.collapse-btn');
const collapseBtnInner = collapseBtn.querySelector('.collapse-btn-inner');
collapseBtn.addEventListener('click', function() {
panel.classList.toggle('collapsed');
collapseBtnInner.innerHTML = '';
if (panel.classList.contains('collapsed')) {
const h = document.createElement('span');
h.className = 'collapse-icon-bar horizontal';
const v = document.createElement('span');
v.className = 'collapse-icon-bar vertical';
collapseBtnInner.appendChild(h);
collapseBtnInner.appendChild(v);
} else {
const h = document.createElement('span');
h.className = 'collapse-icon-bar horizontal';
collapseBtnInner.appendChild(h);
}
});
return panel;
}
function bindPanelEvents() {
document.getElementById('start-answer')?.addEventListener('click', () => {
addLog('本助手仅供学习研究,请遵守课程与平台规则。', 'info');
addLog('开始自动答题...');
autoAnswer();
});
document.getElementById('pause-answer')?.addEventListener('click', () => {
isAnswering = false;
addLog('正在暂停自动答题...', 'info');
});
const startStudyBtn = document.getElementById('start-study');
const pauseStudyBtn = document.getElementById('pause-study');
if (startStudyBtn && pauseStudyBtn) {
startStudyBtn.addEventListener('click', () => {
addLog('本助手仅供学习研究,请遵守课程与平台规则。', 'info');
startStudyChapters();
});
pauseStudyBtn.addEventListener('click', () => { stopStudyChapters(); });
}
const buyBtn = document.getElementById('buy-license');
if (buyBtn) {
buyBtn.addEventListener('click', async () => {
try {
await showPayModalPaid('免费试用,打赏5元永久解锁哦');
} catch (e) {
addLog('打开支付弹窗失败: ' + (e && e.message ? e.message : e), 'error');
}
});
}
document.getElementById('debug-page')?.addEventListener('click', () => { debugPageStructure(); });
document.getElementById('feedback-btn')?.addEventListener('click', () => { showFeedbackModal(); });
setTimeout(updateTrialBadge, 0);
}
function safeClick(el) {
try {
if (!el) return false;
el.click();
el.dispatchEvent(new MouseEvent('click', { bubbles: true }));
return true;
} catch { return false; }
}
function forEachSameOriginFrame(callback) {
const visit = (win) => {
for (let i = 0; i < win.frames.length; i++) {
const f = win.frames[i];
try {
const doc = f.document || f.contentDocument;
if (doc && doc.location && doc.location.href.includes('.chaoxing.com')) {
callback(doc);
visit(f);
}
} catch { }
}
};
try { callback(document); } catch {}
try { visit(window); } catch {}
}
function forEachAllSameOriginDocs(callback) {
const seen = new Set();
const visit = (win) => {
if (!win || seen.has(win)) return;
seen.add(win);
try {
const doc = win.document || win.contentDocument;
if (doc) callback(doc);
} catch {}
try {
const len = win.frames ? win.frames.length : 0;
for (let i = 0; i < len; i++) {
try { visit(win.frames[i]); } catch {}
}
} catch {}
};
try { visit(window.top); } catch { visit(window); }
}
async function waitForQuestionsRenderAny(timeoutMs = 8000) {
const end = Date.now() + timeoutMs;
const selector = '.question, .questionLi, .subject_item, .examPaper_subject, .questionContainer, .q-item, .subject_node, [class*="question"], .ti-item, .exam-item';
while (Date.now() < end) {
let hit = null;
forEachAllSameOriginDocs((doc) => {
if (hit) return;
try {
const qs = doc.querySelectorAll(selector);
if (qs && qs.length > 0) hit = doc;
} catch {}
});
if (hit) return hit;
await new Promise(r => setTimeout(r, 300));
}
return null;
}
function gotoNextSection(contextDoc) {
const docsToTry = [];
if (contextDoc) docsToTry.push(contextDoc);
try { if (window.top && window.top.document) docsToTry.push(window.top.document); } catch {}
docsToTry.push(document);
const textNextRegex = /下一(节|章|单元|页|个)|继续|下一步|下一个|Next/i;
const nextBtnSelectors = [
'.next', '.vc-next', '.reader-next', 'a[title="下一页"]', '.btn-next', '#next',
'.prev_next .right a', '.switch-btn.next', '.icon-arrow-right', '.right-btn .next'
];
const currentNodeSelectors = ['.cur', '.curr', 'li.active', 'li.selected', '.posCatalog_active'];
try { if (isStudyingChapters) localStorage.setItem(STUDY_PERSIST_KEY, '1'); } catch {}
for (const doc of docsToTry) {
try {
for (const sel of nextBtnSelectors) {
const btn = doc.querySelector(sel);
if (btn && !btn.getAttribute('disabled') && !String(btn.className).includes('disabled')) {
if (safeClick(btn)) { addLog('检测到下一节按钮,已点击', 'success'); return true; }
}
}
for (const curSel of currentNodeSelectors) {
const cur = doc.querySelector(curSel);
if (cur && cur.nextElementSibling) {
const link = cur.nextElementSibling.querySelector('a');
if (link && safeClick(link)) { addLog('目录定位到下一小节', 'success'); return true; }
}
}
const links = Array.from(doc.querySelectorAll('a[href*="knowledgeId"], a[href*="chapterId"], a[href*="studentstudy"]'));
if (links.length > 1) {
const hrefNow = (location && location.href) || '';
const idx = links.findIndex(a => (a.href || '').includes('knowledgeId') && hrefNow.includes('knowledgeId') && a.href.split('knowledgeId')[1] === hrefNow.split('knowledgeId')[1]);
const next = idx >= 0 ? links[idx + 1] : null;
if (next && safeClick(next)) { addLog('通过目录链接顺序跳转下一小节', 'success'); return true; }
}
const clickable = Array.from(doc.querySelectorAll('a, button, .btn, .el-button, .next'));
for (const el of clickable) {
const txt = (el.textContent || '').trim();
if (textNextRegex.test(txt)) {
const excludeClasses = ['close', 'cancel', 'delete', 'remove', 'back', 'prev', 'disabled', 'popup', 'modal'];
const hasExcludeClass = excludeClasses.some(cls =>
el.className.toLowerCase().includes(cls) ||
el.id.toLowerCase().includes(cls)
);
const isVisible = el.offsetWidth > 0 && el.offsetHeight > 0 &&
window.getComputedStyle(el).display !== 'none' &&
window.getComputedStyle(el).visibility !== 'hidden';
const isValidNavigationElement = (
(el.tagName === 'A' && (el.href || el.onclick)) ||
(el.tagName === 'BUTTON' && el.onclick) ||
el.className.includes('btn') ||
el.className.includes('next')
) && !el.closest('.popup, .modal, .dialog, .alert');
const isNavigationText = /^(下一节|下一章|下一个|下一页|继续|Next)$/i.test(txt);
if (!hasExcludeClass && isVisible && isValidNavigationElement && isNavigationText) {
if (safeClick(el)) {
addLog(`通过文本匹配跳转: ${txt}`, 'success');
return true;
}
} else {
addLog(`跳过不合适的文本匹配元素: ${txt} (类名: ${el.className})`, 'debug');
}
}
}
} catch {}
}
addLog('未能自动跳转到下一小节', 'error');
return false;
}
function handleVideosInDocument(doc) {
try {
const videos = doc.querySelectorAll('video, .video-js video');
if (videos.length === 0) return false;
let any = false;
videos.forEach(v => {
try {
v.muted = true;
if (!Number.isNaN(v.playbackRate)) v.playbackRate = 1.0;
const p = v.play(); if (p && typeof p.catch === 'function') p.catch(() => {});
v.loop = false;
if (!v.dataset.autonextBind) {
v.dataset.autonextBind = '1';
v.addEventListener('ended', () => {
if (v.dataset.disableAutoNext === '1' || !isStudyingChapters) return;
addLog('视频播放结束,进行完成度检测', 'success');
setTimeout(() => ensureSectionCompletedAndAdvance(doc), 300);
}, { passive: true });
let nearingFired = false;
const onTimeUpdate = () => {
if (v.dataset.disableAutoNext === '1' || !isStudyingChapters) return;
try {
const d = v.duration || 0;
const t = v.currentTime || 0;
if (d > 0 && (d - t) <= 1.0 && !nearingFired) {
nearingFired = true;
addLog('检测到视频即将结束,进行完成度检测', 'debug');
setTimeout(() => ensureSectionCompletedAndAdvance(doc), 800);
}
} catch {}
};
v.addEventListener('timeupdate', onTimeUpdate, { passive: true });
}
any = true;
} catch {}
});
const popBtns = doc.querySelectorAll('.ans-job-icon, .popBtn, .dialog-footer .btn, .ans-modal .btn, .vjs-big-play-button');
popBtns.forEach(b => safeClick(b));
return any;
} catch { return false; }
}
function handlePPTInDocument(doc) {
try {
const nextSelectors = ['.next', '.vc-next', '.reader-next', 'a[title="下一页"]', '.btn-next', '#next'];
for (const sel of nextSelectors) {
const btn = doc.querySelector(sel);
if (btn && !btn.className.includes('disabled') && !btn.getAttribute('disabled')) {
if (safeClick(btn)) { addLog('PPT自动下一页', 'debug'); return true; }
}
}
const container = doc.scrollingElement || doc.body;
if (container) container.scrollTop = container.scrollHeight;
return false;
} catch { return false; }
}
function findChapterQuizTab(doc) {
try {
const byTitle = doc.querySelector('li[title*="章节测验"], li[title*="测验"], a[title*="章节测验"], a[title*="测验"]');
if (byTitle) return byTitle;
const byOnClick = Array.from(doc.querySelectorAll('li[onclick], a[onclick], button[onclick]')).find(el => {
const oc = (el.getAttribute('onclick') || '').toString();
return oc.includes('changeDisplayContent') && (oc.includes('(2,2') || oc.includes(',2)'));
});
if (byOnClick) return byOnClick;
const candidates = Array.from(doc.querySelectorAll('li, a, button, [role="tab"], [role="option"]'));
const textEl = candidates.find(el => /章节测验|测验/.test(((el.textContent || el.getAttribute('title') || '') + '').trim()));
if (textEl) return textEl;
} catch {}
return null;
}
async function waitForQuestionsRender(doc, timeoutMs = 6000) {
const end = Date.now() + timeoutMs;
while (Date.now() < end) {
try {
const qs = doc.querySelectorAll('.question, .questionLi, .subject_item, .examPaper_subject, .questionContainer, .q-item, .subject_node, [class*="question"], .ti-item, .exam-item');
if (qs.length > 0) return true;
} catch {}
await new Promise(r => setTimeout(r, 300));
}
return false;
}
let TYPR_MD5_LIB, FONT_TABLE_DATA;
try {
TYPR_MD5_LIB = GM_getResourceText('typrMd5Lib');
FONT_TABLE_DATA = GM_getResourceText('fontTableData');
if (TYPR_MD5_LIB) {
window.TYPR_MD5_LIB = TYPR_MD5_LIB;
}
if (FONT_TABLE_DATA) {
window.FONT_TABLE_DATA = FONT_TABLE_DATA;
}
} catch (e) {
console.error('加载外部资源失败:', e);
TYPR_MD5_LIB = '';
FONT_TABLE_DATA = '{}';
}
function injectConsoleDecryptCode(doc, timeoutMs = 3000) {
return new Promise((resolve) => {
try {
const consoleCode = `
if (!window.Typr || !window.md5) {
${TYPR_MD5_LIB || window.TYPR_MD5_LIB || ''}
}
if (!window.chaoXingFontTable) {
window.chaoXingFontTable = ${FONT_TABLE_DATA || window.FONT_TABLE_DATA || '{}'};
}
const decryptChaoXingFont = async () => {
const { Typr, md5, chaoXingFontTable: table } = window;
const base64ToUint8Array = (base64) => {
const data = atob(base64);
const buffer = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
buffer[i] = data.charCodeAt(i);
}
return buffer;
};
const styleElements = [...document.querySelectorAll('style')];
const cxStyle = styleElements.find(el =>
el.textContent.includes('font-cxsecret')
);
if (!cxStyle) {
return;
}
const fontData = cxStyle.textContent.match(/base64,([\\w\\W]+?)'/)[1];
const parsedFont = Typr.parse(base64ToUint8Array(fontData))[0];
const charMap = {};
for (let charCode = 19968; charCode < 40870; charCode++) {
const glyph = Typr.U.codeToGlyph(parsedFont, charCode);
if (!glyph) continue;
const path = Typr.U.glyphToPath(parsedFont, glyph);
const pathHash = md5(JSON.stringify(path)).slice(24);
charMap[String.fromCharCode(charCode)] =
String.fromCharCode(table[pathHash]);
}
document.querySelectorAll('.font-cxsecret').forEach(element => {
let htmlContent = element.innerHTML;
Object.entries(charMap).forEach(([encryptedChar, decryptedChar]) => {
const regex = new RegExp(encryptedChar, 'g');
htmlContent = htmlContent.replace(regex, decryptedChar);
});
element.innerHTML = htmlContent;
element.classList.remove('font-cxsecret');
});
};
decryptChaoXingFont().catch(console.error);
`;
const beforeCnt = (() => { try { return doc.querySelectorAll('.font-cxsecret').length; } catch { return -1; } })();
let script = doc.createElement('script');
script.type = 'text/javascript';
let blobUrl = '';
try {
const blob = new Blob([consoleCode], { type: 'text/javascript' });
blobUrl = (doc.defaultView || window).URL.createObjectURL(blob);
script.src = blobUrl;
} catch {
script.textContent = consoleCode;
}
(doc.head || doc.documentElement).appendChild(script);
script.onload = () => { try { if (blobUrl) (doc.defaultView || window).URL.revokeObjectURL(blobUrl); } catch {} };
const start = Date.now();
const timer = setInterval(() => {
try {
const cnt = doc.querySelectorAll('.font-cxsecret').length;
if (cnt === 0 || (beforeCnt >= 0 && cnt < beforeCnt)) { clearInterval(timer); resolve(); return; }
} catch {}
if (Date.now() - start > timeoutMs) { clearInterval(timer); resolve(); }
}, 200);
} catch { resolve(); }
});
}
async function tryEnterQuizAndAnswer(contextDoc) {
try {
if (!isStudyingChapters) return false;
let targetDoc = null;
let tabEl = null;
forEachAllSameOriginDocs((doc) => {
if (tabEl) return;
const el = findChapterQuizTab(doc);
if (el) { tabEl = el; targetDoc = doc; }
});
if (!tabEl || !targetDoc) return false;
addLog('检测到章节测验入口,正在进入...', 'info');
await new Promise((r) => {
let pending = 0; let done = false;
forEachAllSameOriginDocs((doc) => {
pending++; injectConsoleDecryptCode(doc).finally(() => { if (--pending === 0 && !done) { done = true; r(); } });
});
if (pending === 0) r();
});
try { tabEl.scrollIntoView({ block: 'center', behavior: 'smooth' }); } catch {}
const clicked = safeClick(tabEl);
const oc = (tabEl.getAttribute('onclick') || '').toString();
const m = oc.match(/changeDisplayContent\(([^)]*)\)/);
if (!clicked && m && m[1]) {
try {
const ownerWin = (tabEl.ownerDocument && tabEl.ownerDocument.defaultView) || null;
const topWin = (function(){ try { return window.top; } catch { return window; } })();
const evalWin = ownerWin || topWin || window;
const args = evalWin.eval('[' + m[1] + ']');
const fn = (ownerWin && ownerWin.changeDisplayContent) || (topWin && topWin.changeDisplayContent) || window.changeDisplayContent;
if (typeof fn === 'function') {
fn.apply(ownerWin || topWin || window, args);
} else {
addLog('未找到changeDisplayContent函数可调用', 'error');
}
} catch (e) {
addLog('直接调用changeDisplayContent失败: ' + e.message, 'error');
}
}
const qDoc = await waitForQuestionsRenderAny(10000);
if (!isStudyingChapters) return false;
if (!qDoc) {
addLog('进入章节测验后未检测到题目,自动跳转下一节', 'info');
try { gotoNextSection(targetDoc || document); } catch {}
return true;
}
await injectConsoleDecryptCode(qDoc);
if (!isStudyingChapters) return false;
await autoAnswerInDocument(qDoc);
addLog('章节测验已自动作答', 'success');
return true;
} catch (e) {
addLog(`进入章节测验失败: ${e.message}`, 'error');
return false;
}
}
function hasActionableStudyContent(doc) {
try {
if (doc.querySelector('video, .video-js video')) return true;
const docSelectors = [
'.ans-attach-ct', '.reader', '.ppt', '.ppt-play', '.vjs-control', '.vjs-big-play-button',
'.catalog', '.course_section', '.posCatalog', '.posCatalog_active', '.catalogTree'
];
if (docSelectors.some(sel => !!doc.querySelector(sel))) return true;
const nextSelectors = ['.next', '.vc-next', '.reader-next', 'a[title="下一页"]', '.btn-next', '#next'];
if (nextSelectors.some(sel => !!doc.querySelector(sel))) return true;
if (doc.querySelector('.question, .questionLi, .subject_item, .examPaper_subject, .questionContainer, .q-item, .subject_node, [class*="question"], .ti-item, .exam-item')) return true;
if (doc.querySelector('input[type="radio"], input[type="checkbox"], textarea, select')) return true;
if (doc.querySelector('[id^="answerEditor"], iframe[id^="ueditor_"], div[contenteditable="true"]')) return true;
const iframes = Array.from(doc.querySelectorAll('iframe'));
if (iframes.some(f => {
const src = (f.getAttribute('src') || '').toLowerCase();
return src.includes('mooc-ans') || src.includes('document') || src.includes('ppt') || src.includes('video') || src.includes('knowledgeid');
})) return true;
if (doc.querySelector('.cur, .curr, li.active, li.selected, .posCatalog_active')) return true;
} catch {}
return false;
}
function hasUnansweredQuestions(doc) {
try {
const containers = doc.querySelectorAll('.question, .questionLi, .subject_item, .examPaper_subject, .questionContainer, .q-item, .subject_node, [class*="question"], .ti-item, .exam-item');
for (const q of containers) {
try { if (!isQuestionAnswered(q)) return true; } catch {}
}
const radios = Array.from(doc.querySelectorAll('input[type="radio"]'));
if (radios.length > 0) {
const groups = new Map();
radios.forEach(r => {
const k = r.name || `__radio_${Math.random()}`;
if (!groups.has(k)) groups.set(k, []);
groups.get(k).push(r);
});
for (const [, list] of groups) {
if (!list.some(r => r.checked)) return true;
}
}
const texts = Array.from(doc.querySelectorAll('textarea, input[type="text"], div[contenteditable="true"]'));
if (texts.length > 0) {
if (texts.some(el => {
if (el.tagName && el.tagName.toLowerCase() === 'div') return ((el.innerText || el.textContent || '').trim().length === 0);
return ((el.value || '').trim().length === 0);
})) return true;
}
} catch {}
return false;
}
function tryAutoSkipEmptySection() {
if (!isStudyingChapters) return false;
const now = Date.now();
if (now - lastAutoSkipTs < 4000) return false;
const href = (location && location.href) || '';
const key = href.split('?')[0] + (href.includes('knowledgeId') ? ('?k=' + href.split('knowledgeId')[1]) : '');
if (key !== lastEmptySectionKey) { lastEmptySectionKey = key; emptyChecksCount = 0; }
let found = false;
forEachSameOriginFrame((doc) => {
if (found) return;
if (hasActionableStudyContent(doc)) { found = true; return; }
if (hasUnansweredQuestions(doc)) { found = true; return; }
});
if (!found) {
emptyChecksCount += 1;
addLog(`小节判空第${emptyChecksCount}次`, 'debug');
if (emptyChecksCount >= 2) {
lastAutoSkipTs = now;
emptyChecksCount = 0;
addLog('检测到空白小节(已二次确认),自动跳转下一小节', 'info');
gotoNextSection(document);
return true;
}
} else {
emptyChecksCount = 0;
}
return false;
}
async function autoAnswerInDocument(rootDoc) {
try {
if (!isStudyingChapters) return false;
if (isQuizPageDoc(rootDoc)) {
if (!isStudyingChapters) return false;
const ok = await autoAnswerQuizInDocument(rootDoc);
if (ok) return true;
}
const possibleSelectors = ['.question', '.questionLi', '.subject_item', '.examPaper_subject', '.questionContainer', '.q-item', '.subject_node', '[class*="question"]', '[class*="subject"]', '.ti-item', '.exam-item'];
let questions = [];
for (let selector of possibleSelectors) {
questions = rootDoc.querySelectorAll(selector);
if (questions.length > 0) break;
}
if (questions.length === 0) return false;
addLog(`章节内发现 ${questions.length} 个题目,自动作答...`, 'info');
for (let q of questions) {
if (!isStudyingChapters) { addLog('已暂停刷章节,停止小测作答', 'info'); return false; }
const info = getQuestionInfo(q);
if (!info || !info.question) continue;
const ans = await getAnswer(info);
if (ans) {
fillAnswer(ans, q, info.type);
await new Promise(r => setTimeout(r, 800));
}
}
return true;
} catch (e) { addLog(`章节答题出错: ${e.message}`, 'error'); return false; }
}
function isStudyPage() { return /mycourse\/studentstudy|mooc2-ans|knowledgeId|chapterId/.test(location.href); }
function hasStudyContentDeep() {
let found = false;
const tryDoc = (doc) => {
try {
if (doc.querySelector('video, .video-js, .ans-attach-ct, .reader, .ppt, .ppt-play, .catalog, .vjs-play-control')) { found = true; return; }
if (doc.querySelector('.question, .questionLi, .subject_item, .examPaper_subject, .questionContainer, .q-item, .subject_node, [class*="question"], .ti-item, .exam-item')) { found = true; return; }
} catch {}
};
forEachSameOriginFrame(tryDoc);
return found;
}
function updateStudyButtons(running) {
const startBtn = document.getElementById('start-study');
const pauseBtn = document.getElementById('pause-study');
if (!startBtn || !pauseBtn) return;
if (running) { startBtn.style.display = 'none'; pauseBtn.style.display = 'flex'; }
else { startBtn.style.display = 'flex'; pauseBtn.style.display = 'none'; }
}
function startStudyChapters() {
if (isStudyingChapters) { addLog('刷章节已在运行', 'info'); return; }
isStudyingChapters = true;
try { localStorage.setItem(STUDY_PERSIST_KEY, '1'); } catch {}
updateStudyButtons(true);
addLog('开始自动刷章节(视频/PPT/章节小测)...', 'success');
addLog('⚠️ 章节视频请勿倍速观看,倍速观看可能导致账号异常哦', 'warning');
forEachSameOriginFrame((doc) => {
try { doc.querySelectorAll('video, .video-js video').forEach(v => { delete v.dataset.disableAutoNext; }); } catch {}
handleVideosInDocument(doc);
handlePPTInDocument(doc);
autoAnswerInDocument(doc);
});
tryAutoSkipEmptySection();
studyIntervalId = setInterval(() => {
if (!isStudyingChapters) return;
forEachSameOriginFrame((doc) => {
handleVideosInDocument(doc);
handlePPTInDocument(doc);
});
tryAutoSkipEmptySection();
}, 3000);
}
function stopStudyChapters() {
if (!isStudyingChapters) return;
isStudyingChapters = false;
if (studyIntervalId) { clearInterval(studyIntervalId); studyIntervalId = null; }
try { localStorage.removeItem(STUDY_PERSIST_KEY); } catch {}
forEachSameOriginFrame((doc) => {
try {
doc.querySelectorAll('video, .video-js video').forEach(v => {
v.dataset.disableAutoNext = '1';
try { v.pause(); } catch {}
});
} catch {}
});
updateStudyButtons(false);
addLog('已暂停刷章节', 'info');
}
const LOG_SHOW_DEBUG = false;
const LOG_MAX_ITEMS = 120;
function addLog(message, type = 'info') {
try {
if (type === 'debug' && !LOG_SHOW_DEBUG) return;
const logContainer = document.getElementById('answer-log');
if (!logContainer) return;
const text = String(message || '')
.replace(/\s+/g, ' ')
.slice(0, 140);
const logItem = document.createElement('div');
logItem.className = `log-item ${type}`;
logItem.textContent = `${new Date().toLocaleTimeString()} - ${text}`;
logContainer.appendChild(logItem);
const items = logContainer.querySelectorAll('.log-item');
if (items.length > LOG_MAX_ITEMS) {
const removeCount = items.length - LOG_MAX_ITEMS;
for (let i = 0; i < removeCount; i++) {
const n = logContainer.firstElementChild;
if (n) logContainer.removeChild(n);
}
}
logContainer.scrollTop = logContainer.scrollHeight;
} catch {}
}
async function updateTrialBadge() {
try {
const el = document.getElementById('cx_trial_badge');
if (!el) return;
const licensed = await checkLicensePaid();
const buyBtn = document.getElementById('buy-license');
if (buyBtn) {
const group = buyBtn.closest('.button-group');
if (licensed) {
if (group) group.style.display = 'none';
else buyBtn.style.display = 'none';
} else {
if (group) group.style.display = 'flex';
else buyBtn.style.display = 'flex';
}
}
if (licensed) {
el.textContent = '永久激活,感谢赞助';
return;
}
const used = getFreeUsedCount();
const remain = Math.max(0, getFreeLimit() - used);
el.textContent = `试用剩余:${remain}/${getFreeLimit()}`;
} catch {}
}
function getQuestionInfo(questionElement) {
try {
addLog('题目元素HTML结构:' + questionElement.outerHTML.substring(0, 200) + '...', 'debug');
const questionId = questionElement.id || '';
addLog(`题目ID: ${questionId}`, 'debug');
const possibleTypeSelectors = [
'.type_title',
'.mark_name',
'.questionType',
'div[class*="type"]',
'div[class*="Type"]',
'.subject_type',
'.q-type',
'div[class*="questionType"]',
'.stem_type'
];
const possibleQuestionSelectors = [
'.subject_describe',
'.mark_name',
'.questionContent',
'.title',
'div[class*="title"]',
'.subject_stem',
'.q-body',
'.question-content',
'.stem-content',
'.stem_txt'
];
let typeText = '';
for (let selector of possibleTypeSelectors) {
const element = questionElement.querySelector(selector);
if (element) {
typeText = element.textContent.trim();
addLog(`找到题目类型: ${typeText},使用选择器: ${selector}`, 'debug');
break;
}
}
let type = '';
if (typeText.includes('单选题')) type = 'single';
else if (typeText.includes('多选题')) type = 'multiple';
else if (typeText.includes('判断题')) type = 'judge';
else if (typeText.includes('填空题')) type = 'blank';
else if (typeText.includes('简答题')) type = 'short';
else if (typeText.includes('名词解释')) type = 'term';
else if (typeText.includes('论述题')) type = 'essay';
else if (typeText.includes('计算题')) type = 'calculation';
else if (typeText.includes('完形填空')) type = 'cloze';
else if (typeText.includes('写作题')) type = 'writing';
else if (typeText.includes('连线题')) type = 'matching';
else if (typeText.includes('分录题')) type = 'accounting';
let questionText = '';
for (let selector of possibleQuestionSelectors) {
const element = questionElement.querySelector(selector);
if (element) {
questionText = element.textContent.trim();
addLog(`找到题目内容: ${questionText.substring(0, 30)}...,使用选择器: ${selector}`, 'debug');
break;
}
}
const optionSelectors = [
'.stem_answer > div',
'.stem_answer div[class*="option"]',
'div.stem_answer > div',
`#${questionId} > div.stem_answer > div`,
'.answer_p',
'.subject_node',
'.answer_options',
'.options div'
];
let options = [];
let foundSelector = '';
for (let selector of optionSelectors) {
const elements = questionElement.querySelectorAll(selector);
if (elements.length > 0) {
options = Array.from(elements).map((option, index) => {
const text = option.textContent.trim();
const letter = String.fromCharCode(65 + index);
addLog(`选项 ${letter}: ${text}`, 'debug');
return text;
});
foundSelector = selector;
addLog(`找到选项,使用选择器: ${selector},数量: ${elements.length}`, 'debug');
break;
}
}
if (options.length === 0 && questionId) {
for (let i = 1; i <= 6; i++) {
const specificSelector = `#${questionId} > div.stem_answer > div:nth-child(${i})`;
const element = document.querySelector(specificSelector);
if (element) {
options.push(element.textContent.trim());
addLog(`使用nth-child选择器找到选项 ${i}: ${element.textContent.trim()}`, 'debug');
}
}
}
if (!type || !questionText) {
addLog('未能完全识别题目信息', 'error');
}
return {
type,
question: questionText,
options,
foundSelector,
questionId
};
} catch (error) {
addLog(`解析题目失败: ${error.message}`, 'error');
return null;
}
}
function getModelParams(questionType) {
const preciseTypes = ['single', 'multiple', 'blank', 'cloze', 'judge', 'term'];
if (preciseTypes.includes(questionType)) {
return {
temperature: 0.1,
max_tokens: 100,
top_p: 0.1,
frequency_penalty: 0.1,
presence_penalty: 0.1
};
} else {
return {
temperature: 0.5,
max_tokens: 500,
top_p: 0.8,
frequency_penalty: 0.3,
presence_penalty: 0.3
};
}
}
async function getAnswer(questionInfo) {
try {
await ensureAccessAllowed();
} catch (e) {
addLog(String(e && e.message ? e.message : e), 'error');
return null;
}
const prompt = generatePrompt(questionInfo);
addLog(`发送到DeepSeek的提示词:\n${prompt}`, 'debug');
try {
const modelParams = getModelParams(questionInfo.type);
addLog(`使用模型参数: ${JSON.stringify(modelParams)}`, 'debug');
const response = await fetch(DEEPSEEK_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${DEEPSEEK_API_KEY}`
},
body: JSON.stringify({
model: "deepseek-chat",
messages: [{
role: "user",
content: prompt
}],
...modelParams
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (!data.choices || !data.choices[0] || !data.choices[0].message) {
throw new Error('Invalid API response format');
}
const answer = data.choices[0].message.content.trim();
return answer;
} catch (error) {
addLog(`API调用失败: ${error.message}`, 'error');
return null;
}
}
function generatePrompt(questionInfo) {
let prompt = `直接给出答案不要解释 \n题目:${questionInfo.question}\n`;
if (questionInfo.type === 'single' || questionInfo.type === 'multiple' || questionInfo.type === 'judge') {
if (questionInfo.options && questionInfo.options.length > 0) {
prompt += '选项:\n';
questionInfo.options.forEach((option, index) => {
const letter = String.fromCharCode(65 + index);
const cleanOption = option.replace(/^[A-Z][\s.、.。]+|^\d+[\s.、.。]+/, '').trim();
prompt += `${letter}. ${cleanOption}\n`;
});
if (questionInfo.type === 'single') {
prompt += '\n请直接回答选项字母(A/B/C/D/...)';
} else if (questionInfo.type === 'multiple') {
prompt += '\n这是多选题,请列出所有正确选项的字母,用逗号分隔(如:A,B,D)';
} else if (questionInfo.type === 'judge') {
prompt += '\n这是判断题,请回答A表示正确,B表示错误';
}
}
} else if (questionInfo.type === 'blank') {
prompt += '\n这是填空题,请按顺序给出每个空的答案,用逗号分隔';
}
return prompt;
}
function fillAnswer(answer, questionElement, type) {
try {
addLog(`开始填写答案: ${type}类型`, 'debug');
addLog('题目元素类名: ' + questionElement.className, 'debug');
let filled = false;
const questionId = questionElement.id;
addLog(`处理题目ID: ${questionId}`, 'debug');
switch (type) {
case 'blank':
case 'cloze': {
const answers = answer.split(/[,,;;、]\s*/).map(a => a.trim()).filter(a => a);
addLog(`解析到的答案数量: ${answers.length}`, 'debug');
answers.forEach((ans, idx) => addLog(`第${idx + 1}个答案: ${ans}`, 'debug'));
const editorElements = questionElement.querySelectorAll('[id^="answerEditor"]');
if (editorElements.length > 0) {
addLog(`找到UEditor元素数量: ${editorElements.length}`, 'debug');
editorElements.forEach((editorElement, index) => {
const editorId = editorElement.id;
addLog(`处理第${index + 1}个编辑器: ${editorId}`, 'debug');
if (index < answers.length) {
const currentAnswer = answers[index];
try {
if (typeof UE !== 'undefined' && UE.getEditor) {
const editor = UE.getEditor(editorId);
if (editor) {
if (editor.ready) {
editor.ready(() => {
editor.setContent(currentAnswer);
addLog(`通过UEditor API设置第${index + 1}个空的内容: ${currentAnswer}`, 'debug');
if (typeof editor.fireEvent === 'function') {
editor.fireEvent('contentChange');
}
});
filled = true;
}
}
}
if (!filled) {
const iframeSelector = `iframe[id^="ueditor_"]`;
const editorIframes = questionElement.querySelectorAll(iframeSelector);
const editorIframe = editorIframes[index];
if (editorIframe) {
try {
const iframeDoc = editorIframe.contentDocument || editorIframe.contentWindow.document;
const editorBody = iframeDoc.body;
if (editorBody) {
editorBody.innerHTML = currentAnswer;
editorBody.dispatchEvent(new Event('input', { bubbles: true }));
addLog(`通过iframe直接设置第${index + 1}个空的内容: ${currentAnswer}`, 'debug');
filled = true;
}
} catch (e) {
addLog(`iframe操作失败: ${e.message}`, 'error');
}
}
}
const textarea = document.getElementById(editorId);
if (textarea) {
textarea.value = currentAnswer;
textarea.dispatchEvent(new Event('change', { bubbles: true }));
textarea.dispatchEvent(new Event('input', { bubbles: true }));
addLog(`设置第${index + 1}个空的textarea值: ${currentAnswer}`, 'debug');
}
} catch (e) {
addLog(`处理第${index + 1}个空时出错: ${e.message}`, 'error');
}
} else {
addLog(`警告:第${index + 1}个空没有对应的答案`, 'error');
}
});
}
if (!filled) {
const blankInputs = [
...questionElement.querySelectorAll('input[type="text"]'),
...questionElement.querySelectorAll('.blank'),
...questionElement.querySelectorAll('.fill-blank'),
...questionElement.querySelectorAll('[class*="blank"]'),
...questionElement.querySelectorAll('[class*="fill"]'),
...questionElement.querySelectorAll('textarea')
];
if (blankInputs.length > 0) {
addLog(`找到 ${blankInputs.length} 个普通输入框`, 'debug');
blankInputs.forEach((input, index) => {
if (index < answers.length) {
try {
input.value = answers[index];
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
addLog(`填写第${index + 1}个空: ${answers[index]}`, 'debug');
filled = true;
} catch (e) {
addLog(`填写第${index + 1}个空失败: ${e.message}`, 'error');
}
} else {
addLog(`警告:第${index + 1}个输入框没有对应的答案`, 'error');
}
});
}
}
break;
}
case 'short':
case 'term':
case 'essay':
case 'writing':
case 'calculation':
case 'matching':
case 'accounting': {
const textInputs = [
...questionElement.querySelectorAll('textarea'),
...questionElement.querySelectorAll('.answer-area'),
...questionElement.querySelectorAll('.writing-area'),
...questionElement.querySelectorAll('[class*="answer"]'),
...questionElement.querySelectorAll('[class*="text-area"]'),
...questionElement.querySelectorAll('div[contenteditable="true"]')
];
if (textInputs.length > 0) {
textInputs.forEach(input => {
try {
if (input.tagName.toLowerCase() === 'textarea' || input.tagName.toLowerCase() === 'input') {
input.value = answer;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
}
else if (input.getAttribute('contenteditable') === 'true') {
input.innerHTML = answer;
input.dispatchEvent(new Event('input', { bubbles: true }));
}
addLog(`填写答案到${input.tagName.toLowerCase()}`, 'debug');
filled = true;
} catch (e) {
addLog(`填写答案失败: ${e.message}`, 'error');
}
});
}
const editors = [
...questionElement.querySelectorAll('.editor'),
...questionElement.querySelectorAll('[class*="editor"]'),
...questionElement.querySelectorAll('iframe')
];
editors.forEach(editor => {
try {
if (editor.tagName.toLowerCase() === 'iframe') {
const iframeDoc = editor.contentDocument || editor.contentWindow.document;
const editorBody = iframeDoc.body;
if (editorBody) {
editorBody.innerHTML = answer;
editorBody.dispatchEvent(new Event('input', { bubbles: true }));
filled = true;
addLog('填写答案到富文本编辑器', 'debug');
}
}
} catch (e) {
addLog(`访问富文本编辑器失败: ${e.message}`, 'error');
}
});
break;
}
case 'single':
case 'multiple':
case 'judge': {
let answerLetters;
if (type === 'multiple') {
answerLetters = answer.toUpperCase().split(/[,,、\s]+/).map(l => l.trim());
} else {
answerLetters = [answer.toUpperCase().trim()];
}
addLog(`识别到的选项字母: ${answerLetters.join(', ')}`, 'debug');
for (const letter of answerLetters) {
if (!/^[A-Z]$/.test(letter)) {
addLog(`跳过无效的选项字母: ${letter}`, 'error');
continue;
}
const index = letter.charCodeAt(0) - 65 + 1; // 1-based index for nth-child
const specificSelector = `#${questionId} > div.stem_answer > div:nth-child(${index})`;
const optionElement = document.querySelector(specificSelector);
if (optionElement) {
try {
optionElement.click();
addLog(`点击选项元素: ${specificSelector}`, 'debug');
const input = optionElement.querySelector('input');
if (input) {
input.click();
input.checked = true;
input.dispatchEvent(new Event('change', { bubbles: true }));
addLog(`点击选项input元素`, 'debug');
}
const label = optionElement.querySelector('label');
if (label) {
label.click();
addLog(`点击选项label元素`, 'debug');
}
filled = true;
} catch (e) {
addLog(`点击选项 ${letter} 失败: ${e.message}`, 'error');
}
} else {
addLog(`未找到选项元素: ${specificSelector}`, 'error');
}
}
break;
}
default:
break;
}
if (filled) {
addLog(`答案填写成功`, 'success');
} else {
addLog(`答案可能未成功填写,请检查`, 'error');
}
try {
const submitButtons = [
...questionElement.querySelectorAll('button[type="submit"]'),
...questionElement.querySelectorAll('input[type="submit"]'),
...questionElement.querySelectorAll('.submit-btn'),
...questionElement.querySelectorAll('.save-btn'),
...questionElement.querySelectorAll('[class*="submit"]'),
...questionElement.querySelectorAll('[class*="save"]')
];
if (submitButtons.length > 0) {
submitButtons[0].click();
addLog('触发了提交按钮', 'debug');
}
} catch (e) {
addLog(`触发提交按钮失败: ${e.message}`, 'debug');
}
} catch (error) {
addLog(`答案填写失败: ${error.message}`, 'error');
}
}
function debugPageStructure() {
addLog('开始调试页面结构...', 'debug');
addLog('页面URL: ' + window.location.href, 'debug');
addLog('页面标题: ' + document.title, 'debug');
const possibleContainers = [
'.question',
'.questionLi',
'.subject_item',
'.examPaper_subject',
'.questionContainer',
'.q-item',
'.subject_node',
'[class*="question"]',
'[class*="subject"]'
];
for (let selector of possibleContainers) {
const elements = document.querySelectorAll(selector);
addLog(`使用选择器 ${selector} 找到 ${elements.length} 个元素`, 'debug');
if (elements.length > 0) {
addLog(`第一个元素HTML结构:${elements[0].outerHTML.substring(0, 200)}...`, 'debug');
}
}
const allElements = document.querySelectorAll('*');
const relevantElements = Array.from(allElements).filter(el => {
const className = el.className || '';
const id = el.id || '';
return (className + id).toLowerCase().includes('question') ||
(className + id).toLowerCase().includes('answer') ||
(className + id).toLowerCase().includes('option') ||
(className + id).toLowerCase().includes('subject');
});
addLog(`找到 ${relevantElements.length} 个可能相关的元素`, 'debug');
relevantElements.forEach(el => {
addLog(`发现元素: ${el.tagName.toLowerCase()}.${el.className}#${el.id}`, 'debug');
addLog(`元素HTML: ${el.outerHTML.substring(0, 100)}...`, 'debug');
});
const inputs = document.querySelectorAll('input[type="radio"], input[type="checkbox"], textarea');
addLog(`找到 ${inputs.length} 个输入元素`, 'debug');
inputs.forEach(input => {
addLog(`输入元素: type=${input.type}, name=${input.name}, class=${input.className}`, 'debug');
});
}
function updateStatus(running) {
const startButton = document.getElementById('start-answer');
const pauseButton = document.getElementById('pause-answer');
if (running) {
startButton.style.display = 'none';
pauseButton.style.display = 'flex';
} else {
startButton.style.display = 'flex';
pauseButton.style.display = 'none';
}
}
function hasQuestions() {
const possibleSelectors = [
'.question',
'.questionLi',
'.subject_item',
'.examPaper_subject',
'.questionContainer',
'.q-item',
'.subject_node',
'[class*="question"]',
'[class*="subject"]',
'.ti-item',
'.exam-item'
];
for (let selector of possibleSelectors) {
const questions = document.querySelectorAll(selector);
if (questions.length > 0) {
return true;
}
}
const allElements = document.querySelectorAll('*');
const possibleQuestions = Array.from(allElements).filter(el => {
const className = el.className || '';
const id = el.id || '';
const text = el.textContent || '';
return (className + id + text).toLowerCase().includes('题目') ||
(className + id).toLowerCase().includes('question') ||
(className + id).toLowerCase().includes('subject') ||
/^\d+[\.。]/.test(text.trim());
});
return possibleQuestions.length > 0;
}
function showNoTaskToast() {
const toast = document.createElement('div');
toast.id = 'no-task-toast';
toast.textContent = '该页面无任务';
document.body.appendChild(toast);
setTimeout(() => {
if (toast && toast.parentNode) {
toast.parentNode.removeChild(toast);
}
}, 3000);
}
let advanceInProgress = false;
function isQuestionAnswered(q) {
try {
const choiceInputs = q.querySelectorAll('input[type="radio"], input[type="checkbox"]');
if (choiceInputs.length > 0) {
return Array.from(choiceInputs).some(i => i.checked);
}
const textInputs = q.querySelectorAll('input[type="text"], textarea');
if (textInputs.length > 0) {
if (Array.from(textInputs).some(t => (t.value || '').trim().length > 0)) return true;
}
const editableDivs = q.querySelectorAll('[contenteditable="true"]');
if (editableDivs.length > 0) {
if (Array.from(editableDivs).some(d => (d.innerText || d.textContent || '').trim().length > 0)) return true;
}
const ueTextareas = q.querySelectorAll('[id^="answerEditor"]');
for (const ta of ueTextareas) {
const id = ta.id;
try {
if (typeof UE !== 'undefined' && UE.getEditor) {
const ed = UE.getEditor(id);
if (ed && ed.getContentTxt && ed.getContentTxt().trim().length > 0) return true;
}
} catch {}
if ((ta.value || '').trim().length > 0) return true;
}
const ifr = q.querySelector('iframe[id^="ueditor_"]');
if (ifr) {
try {
const doc = ifr.contentDocument || ifr.contentWindow.document;
const txt = (doc && doc.body && (doc.body.innerText || doc.body.textContent)) || '';
if (txt.trim().length > 0) return true;
} catch {}
}
} catch {}
return false;
}
function isSectionDone(contextDoc) {
const doc = contextDoc || document;
try {
const videos = doc.querySelectorAll('video, .video-js video');
for (const v of videos) {
try {
const d = v.duration || 0;
const t = v.currentTime || 0;
if (!(v.ended || (d > 0 && t / d >= 0.985))) {
return false;
}
} catch { return false; }
}
const questions = doc.querySelectorAll('.question, .questionLi, .subject_item, .examPaper_subject, .questionContainer, .q-item, .subject_node, [class*="question"], .ti-item, .exam-item');
for (const q of questions) {
if (!isQuestionAnswered(q)) {
return false;
}
}
return true;
} catch { return false; }
}
async function ensureSectionCompletedAndAdvance(contextDoc) {
if (!isStudyingChapters) { addLog('刷章节已暂停,跳过跳转检测', 'info'); return; }
if (advanceInProgress) { addLog('跳转检测进行中,忽略重复触发', 'debug'); return; }
advanceInProgress = true;
try {
const doc = contextDoc || document;
await autoAnswerInDocument(doc);
await tryEnterQuizAndAnswer(doc);
let tries = 3;
while (tries-- > 0) {
if (!isStudyingChapters) { addLog('刷章节已暂停,终止跳转检测', 'info'); return; }
if (isSectionDone(doc)) {
addLog('检测到当前小节已完成,准备跳转下一小节', 'success');
gotoNextSection(doc);
return;
}
await new Promise(r => setTimeout(r, 500));
}
addLog('当前小节未完成,暂不跳转', 'info');
} catch (e) {
addLog(`跳转前完成度检测出错: ${e.message}`, 'error');
} finally {
advanceInProgress = false;
}
}
async function autoAnswer() {
if (isAnswering) {
addLog('自动答题已经在运行中...', 'info');
return;
}
isAnswering = true;
updateStatus(true);
addLog('开始查找题目...', 'debug');
try {
addLog('当前页面URL: ' + window.location.href, 'debug');
addLog('当前页面标题: ' + document.title, 'debug');
const possibleSelectors = [
'.question',
'.questionLi',
'.subject_item',
'.examPaper_subject',
'.questionContainer',
'.q-item',
'.subject_node',
'[class*="question"]',
'[class*="subject"]',
'.ti-item',
'.exam-item'
];
let questions = [];
let foundSelector = '';
for (let selector of possibleSelectors) {
questions = document.querySelectorAll(selector);
if (questions.length > 0) {
foundSelector = selector;
addLog(`使用选择器 ${selector} 找到 ${questions.length} 个题目`, 'debug');
break;
}
}
if (questions.length === 0) {
addLog('使用常规选择器未找到题目,尝试查找可能的题目容器...', 'debug');
const allElements = document.querySelectorAll('*');
const possibleQuestions = Array.from(allElements).filter(el => {
const className = el.className || '';
const id = el.id || '';
const text = el.textContent || '';
return (className + id + text).toLowerCase().includes('题目') ||
(className + id).toLowerCase().includes('question') ||
(className + id).toLowerCase().includes('subject') ||
/^\d+[\.。]/.test(text.trim()); // 匹配数字开头的内容
});
if (possibleQuestions.length > 0) {
questions = possibleQuestions;
addLog(`通过内容分析找到 ${questions.length} 个可能的题目`, 'debug');
}
}
if (questions.length === 0) {
addLog('未找到任何题目,请确保页面已完全加载', 'error');
addLog('页面主要内容:' + document.body.innerHTML.substring(0, 500) + '...', 'debug');
return;
}
addLog(`共找到 ${questions.length} 个题目`, 'info');
Array.from(questions).forEach((q, idx) => {
addLog(`题目 ${idx + 1} 类名: ${q.className}, ID: ${q.id}`, 'debug');
});
for (let question of questions) {
if (!isAnswering) {
addLog('自动答题已暂停', 'info');
break;
}
const questionInfo = getQuestionInfo(question);
if (!questionInfo) {
addLog('题目信息获取失败,跳过当前题目', 'error');
continue;
}
addLog(`正在处理题目: ${questionInfo.question.substring(0, 30)}...`);
addLog(`题目类型: ${questionInfo.type}`, 'debug');
addLog(`选项数量: ${questionInfo.options.length}`, 'debug');
const answer = await getAnswer(questionInfo);
if (answer) {
addLog(`获取到答案: ${answer}`);
fillAnswer(answer, question, questionInfo.type);
}
if (isAnswering) {
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
} catch (error) {
addLog(`自动答题过程出错: ${error.message}`, 'error');
} finally {
isAnswering = false;
updateStatus(false);
addLog('答题过程结束', 'success');
}
}
function init() {
let persistedStudy = false;
try { persistedStudy = localStorage.getItem(STUDY_PERSIST_KEY) === '1'; } catch {}
const pageTitle = document.title || '';
const currentUrl = location.href || '';
if (pageTitle.includes('课程') || pageTitle === '课程' || pageTitle.includes('课表') || pageTitle === '课表') {
addLog(`检测到${pageTitle.includes('课表') ? '课表' : '课程'}页面,不展现脚本面板`, 'info');
return;
}
const isCourseDetailPage = () => {
if (currentUrl.includes('/mooc2-ans/mycourse/stu') ||
currentUrl.includes('/mycourse/studentcourse') ||
currentUrl.includes('course/') && !currentUrl.includes('knowledge')) {
const hasNavigationMenu = document.querySelector('.nav-content ul, .stuNavigationList ul');
const hasModuleLinks = document.querySelectorAll('a[title="章节"], a[title="作业"], a[title="考试"], a[title="资料"]').length >= 3;
const hasCourseInfo = document.querySelector('.classDl, .sideCon, .nav_side');
const hasCourseId = document.querySelector('#courseid, input[name="courseid"]');
if ((hasNavigationMenu || hasModuleLinks) && hasCourseInfo && hasCourseId) {
return true;
}
}
return false;
};
if (isCourseDetailPage()) {
addLog('检测到课程详情页面,不展现脚本面板', 'info');
return;
}
const isChapterListPage = () => {
const hasChapterList = document.querySelector('.fanyaChapter, .chapter_body, .xs_table');
const hasChapterItems = document.querySelectorAll('.chapter_unit, .chapter_item').length > 0;
const hasChapterStructure = document.querySelector('.chapter_th, .chapter_td');
const hasProgressInfo = document.querySelector('.catalog_points_yi, .chapter_head');
const hasSearchBox = document.querySelector('#searchChapterListByName, .dataSearch');
const hasTypicalStructure = hasChapterList && hasChapterStructure && hasProgressInfo;
const hasChapterTitles = document.querySelectorAll('.catalog_name, .newCatalog_name').length > 2;
const urlIndicatesChapterList = currentUrl.includes('/mycourse/studentcourse') ||
currentUrl.includes('/studentstudy') && !currentUrl.includes('chapterId=');
const hasNoLearningContent = !document.querySelector('video, .video-js, iframe[src*="chaoxing"], .questionLi, .TiMu');
return hasTypicalStructure && hasChapterItems && hasChapterTitles && urlIndicatesChapterList && hasNoLearningContent;
};
if (isChapterListPage()) {
addLog('检测到章节列表页面,不展现脚本面板', 'info');
return;
}
if (!persistedStudy && !hasQuestions() && !hasStudyContentDeep() && !isStudyPage()) {
showNoTaskToast();
return;
}
if (!claimOwnership()) {
if (persistedStudy && !recoveryTimerId) {
recoveryTimerId = setInterval(() => {
if (claimOwnership()) {
clearInterval(recoveryTimerId); recoveryTimerId = null;
createdPanelEl = createPanel();
bindPanelEvents();
startHeartbeat();
if (!isStudyingChapters) startStudyChapters();
}
}, 1000);
}
return;
}
createdPanelEl = createPanel();
bindPanelEvents();
startHeartbeat();
if (persistedStudy) {
startStudyChapters();
setTimeout(() => tryAutoSkipEmptySection(), 600);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
function isQuizPageDoc(doc) {
try {
if (doc.getElementById('form1') && doc.querySelector('#RightCon .newTestTitle')) return true;
if (doc.querySelector('.newTestCon form#form1') && doc.querySelector('.ans-cc')) return true;
} catch {}
return false;
}
function collectQuizQuestions(doc) {
const questions = [];
try {
const typeInputs = doc.querySelectorAll('input[id^="answertype"]');
typeInputs.forEach((inp) => {
try {
const id = inp.id.replace('answertype', '');
const qid = id.trim();
const block = doc.querySelector(`.singleQuesId[data="${qid}"]`) || inp.closest('.TiMu') || doc;
const typeVal = (inp.value || '').trim();
let type = '';
if (typeVal === '0') type = 'single';
else if (typeVal === '1') type = 'multiple';
else if (typeVal === '3') type = 'judge';
else if (typeVal === '2') type = 'blank';
else if (typeVal === '4') type = 'short';
else {
const hasTextInput = block.querySelector('input[type="text"], textarea, [contenteditable="true"], [id^="answerEditor"], iframe[id^="ueditor_"]');
type = hasTextInput ? 'short' : 'text';
}
const opts = [];
const lis = block.querySelectorAll(`ul.Zy_ulTop li[onclick][qid="${qid}"]`);
lis.forEach((li, idx) => {
const span = li.querySelector('.num_option, .num_option_dx');
const letter = span?.getAttribute('data') || String.fromCharCode(65 + idx);
const txt = (li.querySelector('a.after')?.textContent || '').trim();
opts.push(`${letter}. ${txt}`);
});
let qtext = '';
const label = block.querySelector('.Zy_TItle .fontLabel');
if (label) qtext = label.textContent.replace(/\s+/g, ' ').trim();
questions.push({ qid, type, question: qtext, options: opts });
} catch {}
});
} catch {}
return questions;
}
function fillQuizAnswer(doc, qid, type, answer) {
try {
const block = doc.querySelector(`.singleQuesId[data="${qid}"]`) || doc;
if (!block) return false;
if (type === 'single' || type === 'multiple' || type === 'judge') {
let letters = [];
if (type === 'multiple') {
letters = (answer || '').toUpperCase().split(/[,,、\s]+/).filter(Boolean);
} else if (type === 'judge') {
const val = String(answer || '').trim().toLowerCase();
if (/^a$|对|true|正确/.test(val)) letters = ['A'];
else if (/^b$|错|false|错误/.test(val)) letters = ['B'];
else if (/^t$/.test(val)) letters = ['A'];
else if (/^f$/.test(val)) letters = ['B'];
else letters = [(val.match(/[ab]/i) || ['A'])[0].toUpperCase()];
} else {
const m = String(answer || '').toUpperCase().match(/[A-Z]/g);
letters = m ? m : [];
}
const ul = block.querySelector('ul.Zy_ulTop');
if (!ul) return false;
letters.forEach((L) => {
let target = null;
if (type === 'judge') {
const dataVal = (L === 'A') ? 'true' : 'false';
target = ul.querySelector(`li .num_option[data='${dataVal}'], li .num_option_dx[data='${dataVal}']`)
|| ul.querySelector(`li .num_option[data='${L}'], li .num_option_dx[data='${L}']`);
} else {
target = ul.querySelector(`li .num_option[data='${L}'], li .num_option_dx[data='${L}']`);
}
if (target) {
const li = target.closest('li');
safeClick(li);
}
});
const hidden = doc.getElementById(`answer${qid}`);
if (hidden) {
const want = (type === 'judge')
? (letters[0] === 'A' ? 'true' : 'false')
: letters.join('');
if (!hidden.value || (type !== 'multiple' && hidden.value.toLowerCase() !== want)) {
hidden.value = want;
const spans = ul.querySelectorAll(`.choice${qid}`);
spans.forEach(s => s.classList.remove('check_answer', 'check_answer_dx'));
letters.forEach((L) => {
let sel = null;
if (type === 'judge') {
const dv = (L === 'A') ? 'true' : 'false';
sel = ul.querySelector(`.choice${qid}[data='${dv}']`) || ul.querySelector(`.choice${qid}[data='${L}']`);
} else {
sel = ul.querySelector(`.choice${qid}[data='${L}']`);
}
if (sel) {
const isMulti = !!ul.querySelector('.num_option_dx');
sel.classList.add(isMulti ? 'check_answer_dx' : 'check_answer');
const li = sel.closest('li');
if (li) {
li.setAttribute('aria-checked', 'true');
li.setAttribute('aria-pressed', 'true');
}
}
});
}
}
return true;
}
else if (type === 'blank') {
// 多空填空:按分隔符拆分并逐个填入
const answers = String(answer || '').split(/[,,;;、]\s*/).map(s => s.trim()).filter(Boolean);
const ueAreas = block.querySelectorAll('[id^="answerEditor"]');
ueAreas.forEach((ta, i) => {
const val = answers[i] || '';
if (!val) return;
try {
if (typeof UE !== 'undefined' && UE.getEditor) {
const ed = UE.getEditor(ta.id);
if (ed) {
ed.ready(() => {
ed.setContent(val);
if (typeof ed.fireEvent === 'function') ed.fireEvent('contentChange');
});
}
} else {
ta.value = val;
ta.dispatchEvent(new Event('input', { bubbles: true }));
ta.dispatchEvent(new Event('change', { bubbles: true }));
}
} catch {}
});
const ifrs = block.querySelectorAll('iframe[id^="ueditor_"]');
ifrs.forEach((ifr, i) => {
const val = answers[i] || '';
if (!val) return;
try {
const d = ifr.contentDocument || ifr.contentWindow?.document;
const body = d && d.body;
if (body) {
body.innerHTML = val;
body.dispatchEvent(new Event('input', { bubbles: true }));
}
} catch {}
});
const inputs = [
...block.querySelectorAll('input[type="text"]'),
...block.querySelectorAll('textarea'),
...block.querySelectorAll('[contenteditable="true"]')
];
inputs.forEach((el, i) => {
const val = answers[i] || '';
if (!val) return;
try {
const tag = (el.tagName || '').toLowerCase();
if (tag === 'input' || tag === 'textarea') {
el.value = val;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
} else if (el.getAttribute('contenteditable') === 'true') {
el.innerHTML = val;
el.dispatchEvent(new Event('input', { bubbles: true }));
}
} catch {}
});
const hidden = doc.getElementById(`answer${qid}`);
if (hidden) hidden.value = answers.join(' ');
return true;
}
else if (type === 'text' || type === 'short' || type === 'essay' || type === 'writing') {
// 简答题:整体写入,不做分割
const val = String(answer || '').trim();
if (!val) return false;
const ueAreas = block.querySelectorAll('[id^="answerEditor"]');
ueAreas.forEach((ta) => {
try {
if (typeof UE !== 'undefined' && UE.getEditor) {
const ed = UE.getEditor(ta.id);
if (ed) {
ed.ready(() => {
ed.setContent(val);
if (typeof ed.fireEvent === 'function') ed.fireEvent('contentChange');
});
}
} else {
ta.value = val;
ta.dispatchEvent(new Event('input', { bubbles: true }));
ta.dispatchEvent(new Event('change', { bubbles: true }));
}
} catch {}
});
const ifrs = block.querySelectorAll('iframe[id^="ueditor_"]');
ifrs.forEach((ifr) => {
try {
const d = ifr.contentDocument || ifr.contentWindow?.document;
const body = d && d.body;
if (body) {
body.innerHTML = val;
body.dispatchEvent(new Event('input', { bubbles: true }));
}
} catch {}
});
const inputs = [
...block.querySelectorAll('textarea'),
...block.querySelectorAll('input[type="text"]'),
...block.querySelectorAll('[contenteditable="true"]')
];
inputs.forEach((el) => {
try {
const tag = (el.tagName || '').toLowerCase();
if (tag === 'input' || tag === 'textarea') {
el.value = val;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
} else if (el.getAttribute('contenteditable') === 'true') {
el.innerHTML = val;
el.dispatchEvent(new Event('input', { bubbles: true }));
}
} catch {}
});
const hidden = doc.getElementById(`answer${qid}`);
if (hidden) hidden.value = val;
return true;
}
return false;
} catch { return false; }
}
function findAndClickQuizSubmitButton(doc) {
try {
const targetWindow = doc.defaultView || window;
const chaoxingSubmitMethods = [
() => {
if (typeof targetWindow.btnBlueSubmit === 'function') {
targetWindow.btnBlueSubmit();
addLog('使用 btnBlueSubmit() 方法提交', 'success');
return true;
}
return false;
},
() => {
if (typeof targetWindow.submitCheckTimes === 'function') {
targetWindow.submitCheckTimes();
addLog('使用 submitCheckTimes() 方法提交', 'success');
return true;
}
return false;
},
() => {
if (typeof targetWindow.submitWork === 'function') {
targetWindow.submitWork();
addLog('使用 submitWork() 方法提交', 'success');
return true;
}
return false;
},
() => {
const forms = doc.querySelectorAll('form');
for (const form of forms) {
const formAction = form.action || '';
if (formAction.includes('work') || formAction.includes('quiz') || formAction.includes('submit')) {
try {
form.submit();
addLog('使用表单 submit() 方法提交', 'success');
return true;
} catch (e) {
addLog(`表单提交失败: ${e.message}`, 'error');
}
}
}
return false;
}
];
for (const method of chaoxingSubmitMethods) {
try {
if (method()) return true;
} catch (e) {
addLog(`提交方法执行失败: ${e.message}`, 'error');
}
}
const submitSelectors = [
'input[type="submit"][value*="提交"]',
'button[type="submit"]',
'input[value="提交答案"]',
'input[value="提交"]',
'button[onclick*="submit"]',
'button[onclick*="btnBlueSubmit"]',
'button[onclick*="submitCheckTimes"]',
'.submit-btn',
'.btn-submit',
'#submit',
'.submit',
'input[id*="submit"]',
'button[id*="submit"]',
'a[onclick*="submit"]',
'input[onclick*="tijiao"]',
'button[onclick*="tijiao"]'
];
for (const selector of submitSelectors) {
const submitBtn = doc.querySelector(selector);
if (submitBtn && !submitBtn.disabled && !submitBtn.classList.contains('disabled')) {
try {
submitBtn.scrollIntoView({ block: 'center', behavior: 'smooth' });
const onclick = submitBtn.getAttribute('onclick');
if (onclick) {
try {
const func = new targetWindow.Function(onclick);
func.call(submitBtn);
addLog(`通过onclick执行提交: ${onclick}`, 'success');
return true;
} catch (e) {
addLog(`onclick执行失败: ${e.message}`, 'error');
}
}
if (safeClick(submitBtn)) {
addLog(`成功点击提交按钮: ${selector}`, 'success');
return true;
}
} catch (e) {
addLog(`点击提交按钮失败: ${e.message}`, 'error');
}
}
}
const clickableElements = Array.from(doc.querySelectorAll('input, button, a, span, div'));
for (const el of clickableElements) {
const text = (el.textContent || el.value || '').trim();
if (/^(提交|提交答案|完成|确认提交)$/.test(text)) {
try {
el.scrollIntoView({ block: 'center', behavior: 'smooth' });
const onclick = el.getAttribute('onclick');
if (onclick) {
try {
const func = new targetWindow.Function(onclick);
func.call(el);
addLog(`通过文本匹配和onclick执行提交: ${text}`, 'success');
return true;
} catch (e) {
addLog(`文本匹配onclick执行失败: ${e.message}`, 'error');
}
}
if (safeClick(el)) {
addLog(`通过文本匹配点击提交按钮: ${text}`, 'success');
return true;
}
} catch (e) {
addLog(`通过文本匹配点击提交按钮失败: ${e.message}`, 'error');
}
}
}
addLog('未找到章节测验提交按钮', 'error');
return false;
} catch (e) {
addLog(`查找提交按钮时出错: ${e.message}`, 'error');
return false;
}
}
function validateAndFixSubmitParams(doc) {
try {
const targetWindow = doc.defaultView || window;
if (typeof targetWindow.workRelationId === 'undefined') {
const workIdInputs = doc.querySelectorAll('input[name*="workRelationId"], input[id*="workRelationId"]');
if (workIdInputs.length > 0) {
targetWindow.workRelationId = workIdInputs[0].value;
addLog(`设置workRelationId: ${targetWindow.workRelationId}`, 'debug');
}
}
if (typeof targetWindow.courseId === 'undefined') {
const courseIdInputs = doc.querySelectorAll('input[name*="courseId"], input[id*="courseId"]');
if (courseIdInputs.length > 0) {
targetWindow.courseId = courseIdInputs[0].value;
addLog(`设置courseId: ${targetWindow.courseId}`, 'debug');
}
}
if (typeof targetWindow.classId === 'undefined') {
const classIdInputs = doc.querySelectorAll('input[name*="classId"], input[id*="classId"]');
if (classIdInputs.length > 0) {
targetWindow.classId = classIdInputs[0].value;
addLog(`设置classId: ${targetWindow.classId}`, 'debug');
}
}
const questions = doc.querySelectorAll('[class*="TiMu"], [class*="timu"]');
questions.forEach((q, index) => {
const qid = q.getAttribute('id') || `question_${index}`;
let answerInput = doc.querySelector(`input[name="answer${qid}"], input[id="answer${qid}"]`);
if (!answerInput) {
answerInput = doc.createElement('input');
answerInput.type = 'hidden';
answerInput.name = `answer${qid}`;
answerInput.id = `answer${qid}`;
q.appendChild(answerInput);
addLog(`为题目${qid}创建答案input`, 'debug');
}
});
addLog('提交参数验证完成', 'debug');
return true;
} catch (e) {
addLog(`提交参数验证失败: ${e.message}`, 'error');
return false;
}
}
async function handleSubmitConfirmDialog(doc, timeoutMs = 3000) {
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
try {
const confirmDialogSelectors = [
'.popDiv', '.modal', '.dialog', '.alert',
'.layui-layer', '.confirm-dialog', '.submit-confirm',
'[class*="confirm"]', '[class*="dialog"]', '[class*="modal"]'
];
for (const selector of confirmDialogSelectors) {
const dialog = doc.querySelector(selector);
if (dialog && dialog.style.display !== 'none' &&
(dialog.textContent.includes('确认提交') ||
dialog.textContent.includes('提交') ||
dialog.textContent.includes('确定'))) {
addLog('检测到提交确认弹窗', 'info');
const confirmButtonSelectors = [
'button[onclick*="submit"]', 'button[value*="提交"]',
'button[value*="确定"]', 'button[value*="确认"]',
'input[type="button"][value*="提交"]',
'input[type="button"][value*="确定"]',
'input[type="button"][value*="确认"]',
'.confirm-btn', '.submit-btn', '.ok-btn',
'button:contains("提交")', 'button:contains("确定")',
'button:contains("确认")', 'a[onclick*="submit"]'
];
for (const btnSelector of confirmButtonSelectors) {
const confirmBtn = dialog.querySelector(btnSelector) ||
doc.querySelector(`${selector} ${btnSelector}`);
if (confirmBtn && !confirmBtn.disabled) {
try {
const onclick = confirmBtn.getAttribute('onclick');
if (onclick) {
const targetWindow = doc.defaultView || window;
const func = new targetWindow.Function(onclick);
func.call(confirmBtn);
addLog(`通过onclick执行确认提交: ${onclick}`, 'success');
return true;
}
if (safeClick(confirmBtn)) {
addLog(`点击确认提交按钮: ${btnSelector}`, 'success');
return true;
}
} catch (e) {
addLog(`点击确认按钮失败: ${e.message}`, 'error');
}
}
}
const allButtons = dialog.querySelectorAll('button, input[type="button"], a');
for (const btn of allButtons) {
const text = (btn.textContent || btn.value || '').trim();
if (/^(提交|确定|确认|OK)$/.test(text)) {
try {
if (safeClick(btn)) {
addLog(`通过文本匹配点击确认按钮: ${text}`, 'success');
return true;
}
} catch (e) {
addLog(`文本匹配点击确认按钮失败: ${e.message}`, 'error');
}
}
}
}
}
} catch (e) {
}
await new Promise(r => setTimeout(r, 200));
}
return false;
}
async function waitForQuizSubmitCompletion(doc, timeoutMs = 5000) {
const startTime = Date.now();
const originalUrl = doc.location.href;
while (Date.now() - startTime < timeoutMs) {
try {
const successIndicators = [
'.success', '.alert-success', '.msg-success',
'[class*="success"]', '[class*="complete"]',
'*[text()*="提交成功"]', '*[text()*="完成"]'
];
for (const selector of successIndicators) {
const indicator = doc.querySelector(selector);
if (indicator && indicator.textContent.includes('成功')) {
addLog('检测到提交成功提示', 'success');
return true;
}
}
if (doc.location.href !== originalUrl) {
addLog('检测到页面跳转,提交可能已完成', 'info');
return true;
}
const nextStepSelectors = [
'button[onclick*="next"]', 'a[onclick*="next"]',
'input[value*="下一"]', 'button[value*="下一"]',
'.next-btn', '.btn-next', '#next'
];
for (const selector of nextStepSelectors) {
if (doc.querySelector(selector)) {
addLog('检测到下一步按钮,提交可能已完成', 'info');
return true;
}
}
} catch (e) {
}
await new Promise(r => setTimeout(r, 200));
}
addLog('等待提交完成超时', 'error');
return false;
}
async function autoAnswerQuizInDocument(doc) {
try {
if (!isStudyingChapters) return false;
if (!isQuizPageDoc(doc)) return false;
await injectConsoleDecryptCode(doc);
const qs = collectQuizQuestions(doc);
if (!qs || qs.length === 0) return false;
addLog(`检测到章节测验,共 ${qs.length} 题,开始作答...`, 'info');
for (const q of qs) {
if (!isStudyingChapters) { addLog('已暂停刷章节,停止测验作答', 'info'); return false; }
const promptInfo = { type: q.type, question: q.question || `题目 ${q.qid}`, options: q.options || [] };
const ans = await getAnswer(promptInfo);
if (ans) {
fillQuizAnswer(doc, q.qid, q.type, ans);
}
await new Promise(r => setTimeout(r, 500));
}
addLog('章节测验答题完成,准备提交...', 'success');
await new Promise(r => setTimeout(r, 1000));
addLog('验证提交参数...', 'info');
validateAndFixSubmitParams(doc);
let submitSuccess = false;
const targetWindow = doc.defaultView || window;
try {
const originalAlert = targetWindow.alert;
targetWindow.alert = function(msg) {
addLog(`阻止弹窗: ${msg}`, 'debug');
if (msg && msg.includes('code-1')) {
addLog('检测到code-1错误,尝试其他提交方式', 'info');
return;
}
return originalAlert.call(this, msg);
};
if (typeof targetWindow.btnBlueSubmit === 'function') {
addLog('使用学习通标准提交流程', 'info');
targetWindow.btnBlueSubmit();
await new Promise(r => setTimeout(r, 1000));
if (typeof targetWindow.submitCheckTimes === 'function') {
targetWindow.submitCheckTimes();
addLog('执行submitCheckTimes完成', 'success');
}
if (typeof targetWindow.noSubmit === 'function') {
addLog('检测到noSubmit函数,跳过自动提交以避免错误', 'info');
}
submitSuccess = true;
addLog('学习通标准提交流程执行完成', 'success');
} else if (typeof targetWindow.submitWork === 'function') {
addLog('使用submitWork提交', 'info');
targetWindow.submitWork();
submitSuccess = true;
} else {
submitSuccess = findAndClickQuizSubmitButton(doc);
}
// 恢复原始alert targetWindow.alert = originalAlert;
} catch (e) {
addLog(`提交流程执行失败: ${e.message}`, 'error');
submitSuccess = findAndClickQuizSubmitButton(doc);
}
if (submitSuccess) {
addLog('已执行提交操作,等待确认弹窗...', 'info');
await new Promise(r => setTimeout(r, 500));
const confirmHandled = await handleSubmitConfirmDialog(doc, 3000);
if (confirmHandled) {
addLog('已处理提交确认弹窗', 'success');
} else {
addLog('未检测到确认弹窗或处理失败', 'info');
}
const submitCompleted = await waitForQuizSubmitCompletion(doc, 8000);
if (submitCompleted) {
addLog('章节测验提交完成,准备跳转下一节...', 'success');
await new Promise(r => setTimeout(r, 2000));
if (isStudyingChapters) {
const jumpSuccess = gotoNextSection(doc);
if (jumpSuccess) {
addLog('已自动跳转到下一节', 'success');
} else {
addLog('自动跳转失败,请手动切换到下一节', 'error');
}
}
} else {
addLog('等待提交完成超时,但将继续尝试跳转', 'info');
await new Promise(r => setTimeout(r, 1500));
if (isStudyingChapters) gotoNextSection(doc);
}
} else {
addLog('未找到提交按钮,跳过提交直接尝试跳转', 'info');
await new Promise(r => setTimeout(r, 1000));
if (isStudyingChapters) gotoNextSection(doc);
}
return true;
} catch (e) {
addLog(`章节测验自动作答失败: ${e.message}`, 'error');
return false;
}
}
})();