// ==UserScript==
// @name 超星学习通刷课专属 <<< 助你解放双手
// @namespace cx-helper-xqqx
// @version 1.3.0
// @description 超星学习通智能刷课助手:静音+强制播放+自动下一节+AI答题+视频监控。支持拖拽缩放面板,位置记忆,Alt+P快捷键。集成DeepSeek API智能答题,检测视频异常自动提示。
// @author xqqx
// @match *://mooc1-2.chaoxing.com/mooc-ans/*
// @match *://mooc1.chaoxing.com/mooc-ans/*
// @run-at document-end
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @icon data:image/jpeg;base64,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
// @license MIT
// ==/UserScript==
(function () {
'use strict';
if (window.top !== window) return;
if (window.__PH_INIT__) return;
window.__PH_INIT__ = true;
// 清理遗留元素,避免重复组件造成冲突
['ph-panel','ph-fab','ph-video-tip'].forEach(id => {
const e = document.getElementById(id); if (e) try { e.remove(); } catch {}
});
const Store = (() => {
const hasGM = typeof GM_getValue === 'function' && typeof GM_setValue === 'function';
const mem = new Map();
function get(k, d) { try { return hasGM ? GM_getValue(k, d) : (mem.has(k) ? mem.get(k) : d); } catch { return d; } }
function set(k, v) { try { hasGM ? GM_setValue(k, v) : mem.set(k, v); } catch {} }
return { get, set };
})();
const K = {
rate: 'ph_rate', mute: 'ph_mute', playOn: 'ph_play_on', nextOn: 'ph_next_on',
apiKey: 'ph_api_key', answerOn: 'ph_answer_on',
};
const S = {
visible: 'ph_visible', pos: 'ph_pos', tab: 'ph_tab', size: 'ph_size',
};
// 默认值
if (Store.get(K.rate, null) == null) Store.set(K.rate, '1.5');
if (Store.get(K.mute, null) == null) Store.set(K.mute, true);
if (Store.get(K.playOn, null) == null) Store.set(K.playOn, true);
if (Store.get(K.nextOn, null) == null) Store.set(K.nextOn, true);
if (Store.get(S.visible, null) == null) Store.set(S.visible, true);
if (Store.get(S.tab, null) == null) Store.set(S.tab, 'home');
if (Store.get(S.size, null) == null) Store.set(S.size, {width: 420, height: 450});
if (Store.get(K.apiKey, null) == null) Store.set(K.apiKey, '');
if (Store.get(K.answerOn, null) == null) Store.set(K.answerOn, false);
const Log = {
info: (...a) => console.log('[PH]', ...a),
warn: (...a) => console.warn('[PH]', ...a),
};
const Dom = {
$(sel, root = document) { return root.querySelector(sel); },
$$(sel, root = document) { return Array.from(root.querySelectorAll(sel)); },
mainDoc() {
const f = document.getElementById('iframe');
if (!f) return document;
try { return f.contentDocument || (f.contentWindow && f.contentWindow.document) || document; } catch { return document; }
},
collectDocs(rootDoc) {
const seen = new Set(), out = [];
(function dfs(doc) {
if (!doc || seen.has(doc)) return;
seen.add(doc); out.push(doc);
const ifrs = doc.getElementsByTagName('iframe');
for (let i = 0; i < ifrs.length; i++) {
try {
const d = ifrs[i].contentDocument || (ifrs[i].contentWindow && ifrs[i].contentWindow.document);
if (d) dfs(d);
} catch {}
}
})(rootDoc);
return out;
},
curChapterId() {
const el = document.getElementById('chapterIdid');
return el ? el.value : null;
},
};
// 视频错误检测与提示
const VideoMonitor = (() => {
let errorCount = 0;
const MAX_ERRORS = 3;
function showSwitchTip() {
if (document.getElementById('ph-video-tip')) return;
const tip = document.createElement('div');
tip.id = 'ph-video-tip';
tip.style.cssText = [
'position:fixed','top:50%','left:50%','transform:translate(-50%,-50%)',
'z-index:2147483648','background:#ff4444','color:#fff','padding:20px',
'border-radius:10px','box-shadow:0 8px 20px rgba(0,0,0,.3)','text-align:center'
].join(';');
tip.innerHTML = `
⚠️ 视频播放异常
检测到视频格式不支持或网络问题,建议切换线路:
公网1 → 公网2 → 本校
`;
document.body.appendChild(tip);
Dom.$('#ph-tip-close').addEventListener('click', () => {
tip.remove();
errorCount = 0; // 重置计数
});
// 10秒后自动关闭
setTimeout(() => { if (tip.parentNode) tip.remove(); }, 10000);
}
function monitorVideos() {
const docs = Dom.collectDocs(Dom.mainDoc());
for (const d of docs) {
try {
d.querySelectorAll('video').forEach(v => {
if (v.dataset.phMonitored) return;
v.dataset.phMonitored = 'true';
v.addEventListener('error', () => {
errorCount++;
Log.warn(`视频错误 ${errorCount}/${MAX_ERRORS}:`, v.error);
if (errorCount >= MAX_ERRORS) showSwitchTip();
});
v.addEventListener('loadstart', () => errorCount = 0); // 成功加载时重置
});
} catch {}
}
}
return { start: () => setInterval(monitorVideos, 2000) };
})();
const Playback = (() => {
let t = null;
function allVideos() {
const docs = Dom.collectDocs(Dom.mainDoc()), out = [];
for (const d of docs) {
try { out.push(...d.getElementsByTagName('video')); } catch {}
}
return out;
}
function tick() {
const rate = parseFloat(Store.get(K.rate, '1.5'));
const mute = !!Store.get(K.mute, true);
const vids = allVideos();
for (const v of vids) {
try {
if (v.paused) v.play().catch(() => {});
try { v.playbackRate = rate; } catch {}
try { v.muted = mute; } catch {}
} catch {}
}
}
return {
start() { this.stop(); t = setInterval(tick, 1000); Log.info('播放引擎已启动'); },
stop() { if (t) clearInterval(t); t = null; Log.info('播放引擎已停止'); },
poke() { try { tick(); } catch {} },
};
})();
const Progress = (() => {
let t = null, lastChapter = null, obs = null;
function currentH4() {
const id = Dom.curChapterId();
if (id) {
const byId = document.getElementById('cur' + id);
if (byId) return byId;
}
return document.querySelector('#content1 .ncells h4.currents');
}
function finishedByCatalog() {
const h4 = currentH4();
if (!h4) return null;
const hiddenCnt = h4.querySelector('input.jobUnfinishCount');
if (hiddenCnt && hiddenCnt.value != null) {
const n = parseInt(hiddenCnt.value, 10);
if (!isNaN(n)) return n <= 0;
}
const spanCnt = h4.querySelector('span.jobCount');
if (spanCnt) {
const m = parseInt((spanCnt.textContent || '').trim() || '0', 10);
if (!isNaN(m)) return m <= 0;
}
if (h4.querySelector('.roundpointStudent.blue')) return true;
return null;
}
function allVideosEnded() {
const docs = Dom.collectDocs(Dom.mainDoc());
let any = false;
for (const d of docs) {
try {
const arr = d.getElementsByTagName('video');
if (arr.length) any = true;
for (const v of arr) {
try {
if (!(v.ended || (v.duration > 0 && v.currentTime >= v.duration - 0.5))) return false;
} catch { return false; }
}
} catch { return false; }
}
return any ? true : false;
}
function goNext() {
const btn = document.getElementById('right1');
if (btn && !/\bgray\b/.test(btn.className || '')) {
btn.click();
Log.info('已点击"下一节"按钮');
return true;
}
Log.warn('未找到"下一节"入口');
return false;
}
function hasQuestions() {
const docs = Dom.collectDocs(Dom.mainDoc());
const sels = ['.questionLi', '.examPaper_subject', '.TiMu', '.question-box', '.question'];
for (const d of docs) {
for (const sel of sels) {
if (d.querySelector(sel)) return true;
}
}
return false;
}
function shouldSkipQuestions() {
const apiKey = Store.get(K.apiKey, '');
const answerOn = Store.get(K.answerOn, false);
// 如果没有API或答题功能关闭,则跳过题目章节
return !apiKey || !answerOn;
}
function tick() {
const ch = Dom.curChapterId();
if (lastChapter && ch && lastChapter !== ch) {
Log.info('检测到章节变化:', lastChapter, '->', ch);
setTimeout(() => Playback.poke(), 2500);
}
if (ch) lastChapter = ch;
const fin = finishedByCatalog();
const hasQs = hasQuestions();
const shouldSkip = shouldSkipQuestions();
if (fin === true) {
setTimeout(() => goNext(), 600);
} else if (fin === false) {
Playback.poke();
} else if (hasQs && shouldSkip) {
// 有题目但需要跳过:等视频播放完再跳过
if (allVideosEnded()) {
Log.info('检测到题目章节,无API配置,跳过...');
setTimeout(() => goNext(), 600);
} else {
Playback.poke(); // 继续播放视频
}
} else if (allVideosEnded()) {
setTimeout(() => goNext(), 600);
}
}
return {
start() { this.stop(); lastChapter = Dom.curChapterId(); t = setInterval(tick, 3000); Log.info('进度引擎已启动'); },
stop() { if (t) clearInterval(t); t = null; Log.info('进度引擎已停止'); }
};
})();
const Panel = (() => {
let wrap = null, fab = null;
let dragging = false, startX = 0, startY = 0, startLeft = 0, startTop = 0;
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
// 安全事件绑定函数,避免绑定到不存在的元素
function safeBind(selector, event, handler, root = document) {
try {
const el = root.querySelector(selector);
if (!el) {
console.warn('[PH] safeBind: missing', selector);
return null;
}
el.addEventListener(event, handler);
return el;
} catch (err) {
console.warn('[PH] safeBind error', selector, err);
return null;
}
}
function ensureFab() {
fab = document.getElementById('ph-fab');
if (fab) return fab;
fab = document.createElement('div');
fab.id = 'ph-fab';
fab.textContent = 'CX';
fab.title = '点击显示面板(Alt+P)';
Object.assign(fab.style, {
position: 'fixed',
right: '16px',
bottom: '16px',
zIndex: 2147483647,
width: '44px',
height: '44px',
borderRadius: '50%',
background: '#0f1320',
color: '#fff',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
boxShadow: '0 6px 16px rgba(0,0,0,.25)',
userSelect: 'none',
fontWeight: 600,
fontSize: '14px',
pointerEvents: 'auto'
});
fab.addEventListener('click', () => {
open();
});
document.body.appendChild(fab);
// 根据存储状态决定初始显示(保证互斥)
const vis = !!Store.get(S.visible, true);
fab.style.display = vis ? 'none' : 'flex';
return fab;
}
function switchTab(tab) {
const tabs = ['home','database','answer','search','settings'];
tabs.forEach(t => {
const page = document.getElementById('ph-page-' + t);
const btn = document.querySelector(`.ph-tab[data-tab="${t}"]`);
if (page) page.style.display = (t === tab ? 'block' : 'none');
if (btn) btn.classList.toggle('active', t === tab);
});
Store.set(S.tab, tab);
}
function extractQuestions() {
const docs = Dom.collectDocs(Dom.mainDoc());
const items = [];
const sels = [
'.questionLi', '.examPaper_subject', '.subject_type', '.TiMu',
'.questionLi .clearfix', '.ZyTop', '.question-box', '.question',
'.subject_content', 'li.topic-item'
];
for (const d of docs) {
for (const sel of sels) {
d.querySelectorAll(sel).forEach((node, index) => {
// 保留原始HTML结构,然后转换为格式化文本
let html = node.innerHTML || '';
let text = node.innerText || '';
// 保留换行和段落结构
text = text.replace(/\n\s*\n/g, '\n'); // 合并多个空行
text = text.replace(/^\s+|\s+$/g, ''); // 去除首尾空白
// 格式化选项(A、B、C、D)
text = text.replace(/([ABCD])[\.、]\s*/g, '\n$1. '); // 选项换行
text = text.replace(/\s*([ABCD])\s*[\.、]\s*/g, '\n$1. '); // 处理选项格式
// 清理题号但保留结构
text = text.replace(/^(\d+[\.\)]\s*)/, '【题目】 ');
if (text && text.length > 10) {
items.push(`=== 题目 ${items.length + 1} ===\n${text}\n`);
}
});
}
}
const area = document.getElementById('ph-answer-area');
if (area) {
if (items.length > 0) {
area.value = items.join('\n' + '-'.repeat(60) + '\n\n');
} else {
area.value = '未识别到题面,请确保在章节测试/作业页面。';
}
}
displayQuestions(items);
}
// API验证和答题相关函数
async function validateAPI(apiKey) {
if (!apiKey || apiKey.trim() === '') return false;
try {
const response = await fetch('https://api.deepseek.com/v1/models', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
return response.ok;
} catch (error) {
Log.warn('API验证失败:', error);
return false;
}
}
function updateAPIStatus(status, message) {
const statusEl = document.getElementById('ph-api-status');
const toggleBtn = document.getElementById('ph-answer-toggle');
const autoBtn = document.getElementById('ph-auto-answer');
if (statusEl) statusEl.textContent = message;
if (toggleBtn) {
toggleBtn.style.background = status ? '#0f1320' : '#ccc';
toggleBtn.style.color = status ? '#fff' : '#000';
}
if (autoBtn) autoBtn.disabled = !status;
}
function displayQuestions(questions) {
const window = document.getElementById('ph-question-window');
if (!window) return;
if (questions.length === 0) {
window.innerHTML = '未找到题目
';
return;
}
// 清理题目格式,避免重复显示
const cleanQuestions = questions.map(q => {
// 移除已有的格式标记
let cleaned = q.replace(/^=== 题目 \d+ ===\n?/g, '');
cleaned = cleaned.replace(/^【题目】\s*/g, '');
return cleaned.trim();
});
window.innerHTML = cleanQuestions.map((q, i) =>
``
).join('');
}
async function autoAnswer(questions) {
const apiKey = Store.get(K.apiKey, '');
if (!apiKey) {
alert('请先配置API密钥');
return;
}
Log.info('开始自动答题,题目数量:', questions.length);
for (let i = 0; i < questions.length; i++) {
const question = questions[i];
try {
// 调用DeepSeek API获取答案
const answer = await callDeepSeekAPI(apiKey, question);
if (answer) {
// 尝试填入答案到页面
fillAnswer(question, answer, i);
Log.info(`题目${i+1}答题完成:`, answer);
}
} catch (error) {
Log.warn(`题目${i+1}答题失败:`, error);
}
// 添加延迟避免API限制
if (i < questions.length - 1) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}
async function callDeepSeekAPI(apiKey, question) {
try {
const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [{
role: 'user',
content: `请回答以下题目,只返回答案选项(如A、B、C、D)或简短答案,不要解释:\n\n${question}`
}],
max_tokens: 100,
temperature: 0.1
})
});
const data = await response.json();
return data.choices?.[0]?.message?.content?.trim();
} catch (error) {
Log.warn('API调用失败:', error);
return null;
}
}
function fillAnswer(question, answer, index) {
const docs = Dom.collectDocs(Dom.mainDoc());
// 改进的题目匹配策略
for (const doc of docs) {
try {
// 找到所有题目容器
const questionContainers = doc.querySelectorAll('.questionLi, .examPaper_subject, .TiMu, .question-box, .question');
if (questionContainers[index]) {
const container = questionContainers[index];
// 根据答案类型选择不同的填入策略
if (/^[A-D]$/i.test(answer.trim())) {
// 选择题答案
const options = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
for (const option of options) {
const label = option.closest('label')?.textContent || option.parentElement?.textContent || '';
if (label.includes(answer.toUpperCase()) || label.startsWith(answer.toUpperCase())) {
option.click();
Log.info(`题目${index+1}选择答案: ${answer}`);
return true;
}
}
} else {
// 文本答案
const textInputs = container.querySelectorAll('input[type="text"], textarea');
if (textInputs.length > 0) {
textInputs[0].value = answer.trim();
textInputs[0].dispatchEvent(new Event('input', { bubbles: true }));
textInputs[0].dispatchEvent(new Event('change', { bubbles: true }));
Log.info(`题目${index+1}填入答案: ${answer}`);
return true;
}
}
}
} catch (error) {
Log.warn(`题目${index+1}填答失败:`, error);
}
}
Log.warn(`题目${index+1}未找到合适的输入元素`);
return false;
}
function mount() {
if (document.getElementById('ph-panel')) { wrap = document.getElementById('ph-panel'); ensureFab(); return; }
// 防御性清理:再次删除可能残留的旧元素
['ph-panel','ph-fab'].forEach(id => {
const ex = document.getElementById(id);
if (ex) try { ex.remove(); } catch {}
});
wrap = document.createElement('div');
wrap.id = 'ph-panel';
wrap.style.cssText = [
'position:fixed','z-index:2147483647',
'background:#fff','color:#000','padding:12px 15px',
'border-radius:12px','font-size:13px','box-shadow:0 8px 20px rgba(0,0,0,.28)',
'width:420px','min-height:450px','user-select:none',
'right:20px','bottom:20px'
].join(';');
// 设置相对定位以便拖拽手柄正确定位
wrap.style.overflow = 'visible';
wrap.innerHTML = `
超星学习通刷课助手
v1.2.4 - 助你解放双手,高效学习
✨ 核心功能
- 强制播放:自动播放视频,支持倍速调节
- 自动下一节:完成后自动跳转下一章节
- 智能答题:集成DeepSeek AI自动答题
- 视频监控:检测播放异常并提示切换线路
🛠️ 使用说明
- 面板可拖动、缩放,位置自动记忆
- Alt+P 或右下角"CX"可显示/隐藏面板
- 设置页面可调节倍速、静音等参数
- 答题页面需配置API密钥才能使用AI功能
⚠️ 使用提醒
本脚本仅供学习交流使用,请遵守学校相关规定,合理使用辅助工具。
点击搜索按钮开始查找答案
题库搜题免费使用,AI搜题需配置DeepSeek API
`;
document.body.appendChild(wrap);
ensureFab();
// 初始化API相关控件
const apiKey = Store.get(K.apiKey, '');
const answerOn = !!Store.get(K.answerOn, false);
if (Dom.$('#ph-api-key')) Dom.$('#ph-api-key').value = apiKey;
if (Dom.$('#ph-answer-toggle')) {
Dom.$('#ph-answer-toggle').textContent = answerOn ? '停止答题' : '开始答题';
Dom.$('#ph-answer-toggle').style.background = answerOn ? '#ff4444' : (apiKey ? '#0f1320' : '#ccc');
Dom.$('#ph-answer-toggle').style.color = answerOn ? '#fff' : (apiKey ? '#fff' : '#000');
}
// 更新API状态显示
updateAPIStatus(!!apiKey, apiKey ? 'API已配置' : '未配置API');
// 大小调整功能 - 确保DOM元素已存在
const resizeHandle = Dom.$('#ph-resize');
if (resizeHandle) {
resizeHandle.addEventListener('mousedown', (e) => {
let resizing = true;
const startWidth = wrap.offsetWidth;
const startHeight = wrap.offsetHeight;
const startX = e.clientX;
const startY = e.clientY;
function onResize(e) {
if (!resizing) return;
const newWidth = Math.max(300, startWidth + (e.clientX - startX));
const newHeight = Math.max(200, startHeight + (e.clientY - startY));
wrap.style.width = newWidth + 'px';
wrap.style.height = newHeight + 'px';
}
function onResizeEnd() {
if (!resizing) return;
resizing = false;
document.removeEventListener('mousemove', onResize);
document.removeEventListener('mouseup', onResizeEnd);
Store.set(S.size, {width: wrap.offsetWidth, height: wrap.offsetHeight});
}
document.addEventListener('mousemove', onResize);
document.addEventListener('mouseup', onResizeEnd);
e.preventDefault();
e.stopPropagation();
});
}
// 安全事件绑定
safeBind('#ph-min', 'click', () => hide());
safeBind('#ph-close', 'click', () => hide());
safeBind('#ph-rate', 'change', (e) => {
Store.set(K.rate, e.target.value);
Playback.poke();
setStatus();
});
safeBind('#ph-mute', 'change', (e) => {
Store.set(K.mute, e.target.checked);
Playback.poke();
setStatus();
});
safeBind('#ph-play-toggle', 'click', () => {
const on = !Store.get(K.playOn, true);
Store.set(K.playOn, on);
const btn = document.getElementById('ph-play-toggle');
if (btn) btn.textContent = on ? '关闭' : '开启';
if (on) Playback.start(); else Playback.stop();
setStatus();
});
safeBind('#ph-next-toggle', 'click', () => {
const on = !Store.get(K.nextOn, true);
Store.set(K.nextOn, on);
const btn = document.getElementById('ph-next-toggle');
if (btn) btn.textContent = on ? '关闭' : '开启';
if (on) Progress.start(); else Progress.stop();
setStatus();
});
safeBind('#ph-extract', 'click', extractQuestions);
// 定期检查是否需要自动答题
setInterval(checkAndAutoAnswer, 3000);
// API相关事件处理
safeBind('#ph-api-save', 'click', async () => {
const apiKey = document.getElementById('ph-api-key').value.trim();
if (!apiKey) {
updateAPIStatus(false, '请输入API密钥');
return;
}
updateAPIStatus(false, '验证中...');
const isValid = await validateAPI(apiKey);
if (isValid) {
Store.set(K.apiKey, apiKey);
updateAPIStatus(true, 'API有效');
} else {
updateAPIStatus(false, 'API无效');
}
});
safeBind('#ph-answer-toggle', 'click', () => {
const apiKey = Store.get(K.apiKey, '');
if (!apiKey) {
updateAPIStatus(false, '请先配置API');
return;
}
const on = !Store.get(K.answerOn, false);
Store.set(K.answerOn, on);
const btn = document.getElementById('ph-answer-toggle');
if (btn) {
btn.textContent = on ? '停止答题' : '开始答题';
btn.style.background = on ? '#ff4444' : '#0f1320';
}
});
safeBind('#ph-auto-answer', 'click', () => {
const docs = Dom.collectDocs(Dom.mainDoc());
const items = [];
const sels = ['.questionLi', '.examPaper_subject', '.TiMu', '.question-box', '.question'];
for (const d of docs) {
for (const sel of sels) {
d.querySelectorAll(sel).forEach(node => {
const text = (node.innerText || '').replace(/\s+/g, ' ').trim();
if (text && text.length > 6) items.push(text);
});
}
}
displayQuestions(items);
if (items.length > 0) autoAnswer(items);
});
safeBind('#ph-copy', 'click', () => {
const t = document.getElementById('ph-answer-area');
if (t) { t.select(); document.execCommand('copy'); }
});
// 搜题模式切换和功能实现
let searchMode = 'database'; // 'database' 或 'ai'
safeBind('#ph-search-mode-db', 'click', () => {
searchMode = 'database';
document.getElementById('ph-search-mode-db').className = 'ph-btn primary';
document.getElementById('ph-search-mode-ai').className = 'ph-btn';
document.getElementById('ph-search-mode-desc').textContent = '题库搜题:直接给出标准答案';
});
safeBind('#ph-search-mode-ai', 'click', () => {
searchMode = 'ai';
document.getElementById('ph-search-mode-db').className = 'ph-btn';
document.getElementById('ph-search-mode-ai').className = 'ph-btn primary';
document.getElementById('ph-search-mode-desc').textContent = 'AI搜题:提供答案解析和推理过程';
});
// 题库答题页面功能
safeBind('#ph-db-answer-toggle', 'click', () => {
const on = !Store.get('ph_db_answer_on', false);
Store.set('ph_db_answer_on', on);
const btn = document.getElementById('ph-db-answer-toggle');
if (btn) {
btn.textContent = on ? '停止题库答题' : '开始题库答题';
btn.style.background = on ? '#dc3545' : '#28a745';
}
if (on) {
// 开始自动检测和答题
startDatabaseAnswering();
} else {
// 停止自动答题
stopDatabaseAnswering();
}
});
safeBind('#ph-db-extract', 'click', () => {
const docs = Dom.collectDocs(Dom.mainDoc());
const items = [];
const sels = [
'.questionLi', '.examPaper_subject', '.subject_type', '.TiMu',
'.questionLi .clearfix', '.ZyTop', '.question-box', '.question',
'.subject_content', 'li.topic-item'
];
for (const d of docs) {
for (const sel of sels) {
d.querySelectorAll(sel).forEach((node, index) => {
let html = node.innerHTML || '';
let text = node.innerText || '';
text = text.replace(/\n\s*\n/g, '\n');
text = text.replace(/^\s+|\s+$/g, '');
text = text.replace(/([ABCD])[\.、]\s*/g, '\n$1. ');
text = text.replace(/\s*([ABCD])\s*[\.、]\s*/g, '\n$1. ');
text = text.replace(/^(\d+[\.\)]\s*)/, '【题目】 ');
if (text && text.length > 10) {
items.push(`=== 题目 ${items.length + 1} ===\n${text}\n`);
}
});
}
}
const area = document.getElementById('ph-db-answer-area');
const window = document.getElementById('ph-db-question-window');
if (area) {
if (items.length > 0) {
area.value = items.join('\n' + '-'.repeat(60) + '\n\n');
} else {
area.value = '未识别到题面,请确保在章节测试/作业页面。';
}
}
// 显示在题目窗口
if (window) {
if (items.length === 0) {
window.innerHTML = '未找到题目
';
return;
}
const cleanQuestions = items.map(q => {
let cleaned = q.replace(/^=== 题目 \d+ ===\n?/g, '');
cleaned = cleaned.replace(/^【题目】\s*/g, '');
return cleaned.trim();
});
window.innerHTML = cleanQuestions.map((q, i) =>
``
).join('');
}
});
safeBind('#ph-db-copy', 'click', () => {
const t = document.getElementById('ph-db-answer-area');
if (t) { t.select(); document.execCommand('copy'); }
});
// 题库自动答题逻辑
let dbAnsweringInterval = null;
function startDatabaseAnswering() {
if (dbAnsweringInterval) return;
dbAnsweringInterval = setInterval(async () => {
const docs = Dom.collectDocs(Dom.mainDoc());
const items = [];
const sels = ['.questionLi', '.examPaper_subject', '.TiMu', '.question-box', '.question'];
for (const d of docs) {
for (const sel of sels) {
d.querySelectorAll(sel).forEach(node => {
const text = (node.innerText || '').replace(/\s+/g, ' ').trim();
if (text && text.length > 6) items.push(text);
});
}
}
if (items.length > 0) {
Log.info('检测到题目,开始题库答题');
for (let i = 0; i < items.length; i++) {
try {
const answer = await searchFromDatabase(items[i]);
if (answer) {
fillAnswer(items[i], answer, i);
Log.info(`题目${i+1}答题完成:`, answer);
}
} catch (error) {
Log.warn(`题目${i+1}答题失败:`, error);
}
if (i < items.length - 1) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}
}, 5000); // 每5秒检测一次
}
function stopDatabaseAnswering() {
if (dbAnsweringInterval) {
clearInterval(dbAnsweringInterval);
dbAnsweringInterval = null;
}
}
// 题库搜题函数
async function searchFromDatabase(question) {
try {
const response = await fetch(`https://api.pearktrue.cn/api/question/?question=${encodeURIComponent(question)}`);
const data = await response.json();
if (data.code === 200 && data.data) {
return `【题库答案】\n题目:${data.data.question}\n答案:${data.data.answer}`;
} else {
return '题库中未找到该题目';
}
} catch (error) {
throw new Error('题库API请求失败');
}
}
// AI搜题函数
async function searchFromAI(apiKey, question) {
try {
const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [
{
role: 'system',
content: '你是一个专业的题目解答助手。请按照以下格式回答:\n1. 首先给出明确的答案(如选择题直接给A/B/C/D,判断题给对/错)\n2. 然后简要说明理由(控制在100字以内)\n3. 回答要简洁明了,避免冗长的解释'
},
{
role: 'user',
content: `请回答以下题目:\n\n${question}`
}
],
max_tokens: 200,
temperature: 0.1
})
});
const data = await response.json();
if (data.choices && data.choices[0]) {
const content = data.choices[0].message.content;
return `【AI解析】\n${content}`;
} else {
throw new Error('AI响应格式错误');
}
} catch (error) {
throw new Error('AI API请求失败');
}
}
safeBind('#ph-search-btn', 'click', async () => {
const question = document.getElementById('ph-search-q').value.trim();
const resultDiv = document.getElementById('ph-search-result');
if (!question) {
resultDiv.textContent = '请输入题目内容';
return;
}
resultDiv.textContent = '搜索中...';
try {
let result;
if (searchMode === 'database') {
result = await searchFromDatabase(question);
} else {
const apiKey = Store.get(K.apiKey, '');
if (!apiKey) {
resultDiv.textContent = 'AI搜题需要先配置DeepSeek API密钥';
return;
}
result = await searchFromAI(apiKey, question);
}
resultDiv.textContent = result || '未找到相关答案';
} catch (error) {
resultDiv.textContent = `搜索失败: ${error.message}`;
}
});
// 清空搜索结果按钮
safeBind('#ph-search-clear', 'click', () => {
document.getElementById('ph-search-q').value = '';
document.getElementById('ph-search-result').textContent = '点击搜索按钮开始查找答案';
});
document.querySelectorAll('.ph-tab').forEach(btn => {
btn.addEventListener('click', () => switchTab(btn.dataset.tab));
});
// 拖拽:使用 pointerdown/pointermove/pointerup
const header = Dom.$('#ph-header');
if (header) {
header.addEventListener('pointerdown', function (e) {
// 仅左键(pointerType 仍然通过 button 判断)
if (e.button !== 0) return;
// 如果点击的是可交互控件,则不触发拖拽(保留按钮、输入的点击)
if (e.target.closest('button, input, select, textarea, .ph-tab')) return;
// 记录初始坐标
dragging = true;
const rect = wrap.getBoundingClientRect();
startX = e.clientX; startY = e.clientY;
startLeft = rect.left; startTop = rect.top;
// 切换为 left/top 定位以避免与 right/bottom 冲突
wrap.style.right = 'auto';
wrap.style.bottom = 'auto';
wrap.style.left = rect.left + 'px';
wrap.style.top = rect.top + 'px';
// 禁用文本选择体验
document.body.style.userSelect = 'none';
// 捕获指针,保证 move/up 正确分发
try { header.setPointerCapture(e.pointerId); } catch (err) {}
function onPointerMove(ev) {
if (!dragging) return;
const dx = ev.clientX - startX, dy = ev.clientY - startY;
const left = clamp(startLeft + dx, 0, window.innerWidth - wrap.offsetWidth);
const top = clamp(startTop + dy, 0, window.innerHeight - wrap.offsetHeight);
wrap.style.left = left + 'px';
wrap.style.top = top + 'px';
}
function onPointerUp(ev) {
if (!dragging) return;
dragging = false;
// 恢复可选中
document.body.style.userSelect = '';
try { header.releasePointerCapture(e.pointerId); } catch (err) {}
document.removeEventListener('pointermove', onPointerMove);
document.removeEventListener('pointerup', onPointerUp);
// 保存位置
const r = wrap.getBoundingClientRect();
Store.set(S.pos, { left: Math.round(r.left), top: Math.round(r.top) });
}
document.addEventListener('pointermove', onPointerMove);
document.addEventListener('pointerup', onPointerUp);
e.preventDefault();
});
}
// 应用保存的位置和大小
const pos = Store.get(S.pos, null);
const size = Store.get(S.size, null);
if (pos && Number.isFinite(pos.left) && Number.isFinite(pos.top)) {
wrap.style.right = 'auto';
wrap.style.bottom = 'auto';
Object.assign(wrap.style, { left: pos.left + 'px', top: pos.top + 'px' });
}
// 如果没有保存的位置,保持CSS中设置的right和bottom
if (size && Number.isFinite(size.width) && Number.isFinite(size.height)) {
wrap.style.width = size.width + 'px';
wrap.style.height = size.height + 'px';
}
// 初始化控件
Dom.$('#ph-rate').value = String(Store.get(K.rate, '1.5'));
Dom.$('#ph-mute').checked = !!Store.get(K.mute, true);
const playOn = !!Store.get(K.playOn, true);
const nextOn = !!Store.get(K.nextOn, true);
Dom.$('#ph-play-toggle').textContent = playOn ? '关闭' : '开启';
Dom.$('#ph-next-toggle').textContent = nextOn ? '关闭' : '开启';
if (Store.get(S.visible, true)) open(); else hide();
switchTab(Store.get(S.tab, 'home'));
setStatus();
// 强制同步显示状态,确保面板与FAB互斥
ensureFab(); // 确保fab存在
const visible = !!Store.get(S.visible, true);
if (visible) {
if (wrap) wrap.style.display = 'block';
if (fab) fab.style.display = 'none';
} else {
if (wrap) wrap.style.display = 'none';
if (fab) fab.style.display = 'flex';
}
}
function setStatus() {
const s = Dom.$('#ph-status');
if (!s) return;
const r = Store.get(K.rate, '1.5');
const m = !!Store.get(K.mute, true);
const p = !!Store.get(K.playOn, true);
const n = !!Store.get(K.nextOn, true);
s.textContent = `状态:${p?'强制播放开':'强制播放关'} / ${n?'自动下一节开':'自动下一节关'} / 倍速 ${r}x / ${m?'静音':'出声'}`;
}
function open() {
if (!wrap) mount();
wrap.style.display = 'block';
if (fab) fab.style.display = 'none'; // 隐藏悬浮球
Store.set(S.visible, true);
}
function hide() {
if (!wrap) return;
wrap.style.display = 'none';
if (fab) fab.style.display = 'flex'; // 显示悬浮球
Store.set(S.visible, false);
}
function toggle() {
if (!wrap || wrap.style.display === 'none') open(); else hide();
}
return { mount, setStatus, open, hide, toggle };
})();
// 扩展菜单与快捷键
if (typeof GM_registerMenuCommand === 'function') {
GM_registerMenuCommand('显示/隐藏面板 (Alt+P)', () => Panel.toggle());
}
document.addEventListener('keydown', (e) => {
if (e.altKey && String(e.key).toLowerCase() === 'p') {
Panel.toggle();
e.preventDefault();
}
});
// 启动
function boot() {
Panel.mount();
VideoMonitor.start(); // 启动视频监控
if (Store.get(K.playOn, true)) Playback.start(); else Playback.stop();
if (Store.get(K.nextOn, true)) Progress.start(); else Progress.stop();
setTimeout(() => Playback.poke(), 1200);
window.PHPanel = Panel;
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
else boot();
})();