// ==UserScript== // @name 国开助手 // @namespace https://eduai.lovie.me/ // @version 0.5.8 // @description 国开课程视频试跑 + 当前试卷自动作答;核心答案走服务器,脚本本身不含题库。 // @icon data:image/png;base64,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 // @author 国开助手 // @match *://*.ouchn.cn/* // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_notification // @grant GM_setClipboard // @connect eduai.lovie.me // @connect menhu.pt.ouchn.cn // @run-at document-idle // ==/UserScript== (function () { 'use strict'; // ======== 运营配置(发之前只改这里)======== const CFG = { QQ_GROUP: '3930058219', QQ_LINK: '', HOMEPAGE: 'https://eduai.lovie.me/s/', SERVER_BASE: 'https://eduai.lovie.me', VIDEO_RATE: 4, CHUNK: 120, PANEL_KEY: 'gk_trial_panel_open', AUTH_KEY: 'gk_trial_auth_v3' }; // ======== 通用小工具 ======== const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); function gmGet(k, d) { try { if (typeof GM_getValue === 'function') { const v = GM_getValue(k, null); return v === null ? d : v; } const v = localStorage.getItem(k); return v === null ? d : JSON.parse(v); } catch (e) { return d; } } function gmSet(k, v) { try { if (typeof GM_setValue === 'function') GM_setValue(k, v); else localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} } function gmXhr(opts) { if (typeof GM_xmlhttpRequest === 'function') { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: opts.method || 'GET', url: opts.url, headers: opts.headers || {}, data: opts.data, timeout: opts.timeout || 30000, onload: resolve, onerror: reject, ontimeout: () => reject(new Error('请求超时')) }); }); } return fetch(opts.url, { method: opts.method || 'GET', headers: opts.headers, body: opts.data }) .then(async (r) => ({ status: r.status, responseText: await r.text() })); } function deviceId() { let d = gmGet('gk_trial_device', ''); if (!d) { const hex = '0123456789ABCDEF'; for (let i = 0; i < 8; i++) d += hex[Math.floor(Math.random() * 16)]; gmSet('gk_trial_device', d); } return d; } // ======== 页面识别 ======== function guessActivityId() { try { let m = location.href.match(/learning-activity(?:\/full-screen)?#\/(\d{6,})/i); if (m) return m[1]; m = location.href.match(/[#/](?:learning-activity|activity|activities)[\/=](\d{6,})/i); if (m) return m[1]; m = location.href.match(/(?:learning-activity|activity|activities)[\/=](\d{6,})/i); if (m) return m[1]; const b = document.body; if (b && b.dataset && b.dataset.activityId) return b.dataset.activityId; const el = document.querySelector('[data-activity-id]'); if (el) return el.getAttribute('data-activity-id') || ''; const es = performance.getEntriesByType('resource').map((e) => e.name); for (const u of es) { let mm = u.match(/\/api\/activities\/(\d{6,})/); if (mm) return mm[1]; mm = u.match(/activities-read\/(\d{6,})/); if (mm) return mm[1]; } } catch (e) {} return ''; } function pickVideo() { const vs = Array.from(document.querySelectorAll('video')); return vs.find((v) => isFinite(v.duration) && v.duration > 0) || vs[0] || null; } function guessStudent() { try { const hay = location.href + ' ' + location.hash; let m = hay.match(/(?:student_?id|studentId|user_?no|userNumber|username)[=:_-]?(\d{6,20})/i); if (m) return m[1]; m = ((document.body && document.body.innerText) || '').match(/(?:学号|学号[::])\s*(\d{6,20})/); if (m) return m[1]; for (let i = 0; i < localStorage.length; i++) { const k = localStorage.key(i) || ''; if (!/user|student|account|学号/i.test(k)) continue; const v = localStorage.getItem(k) || ''; const mm = v.match(/\d{8,20}/); if (mm) return mm[0]; } } catch (e) {} return ''; } function guessCourse() { try { const h = document.querySelector('h1, .course-title, .course-name'); const s = ((h && h.innerText) || document.title || '').trim(); return s.replace(/\s+/g, ' ').slice(0, 40); } catch (e) { return ''; } } function guessExamId() { try { const hay = location.pathname + location.search + location.hash; if (!/exam/i.test(hay)) return ''; const m = location.pathname.match(/\/exam\/(\d{5,})/i); if (m) return m[1]; const hm = location.hash.match(/\/exam\/(\d{5,})/i); if (hm) return hm[1]; const qs = new URLSearchParams(location.search); for (const k of ['exam_id', 'examId', 'exam']) { const v = qs.get(k) || ''; if (/^\d{5,}$/.test(v)) return v; } const b = document.body; if (b && b.dataset && b.dataset.examId) return b.dataset.examId; const el = document.querySelector('[data-exam-id]'); if (el) return el.getAttribute('data-exam-id') || ''; for (const sc of Array.from(document.scripts || [])) { const t = sc.textContent || ''; const mm = t.match(/"exam_id"\s*:\s*"?(\d{5,})/); if (mm) return mm[1]; } } catch (e) {} return ''; } // 学号不让客户手填:先看页面,再从学校门户取(浏览器里本来就有登录态) const studentCache = { no: String(gmGet('gk_student', '') || ''), at: 0 }; let resolvingStudent = null; async function fetchPortalStudent() { try { const r = await gmXhr({ method: 'POST', url: 'https://menhu.pt.ouchn.cn/ouchnapp/wap/user/get-info', headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/x-www-form-urlencoded' }, data: '', timeout: 6000 }); const j = JSON.parse((r && r.responseText) || '{}'); const d = (j && j.d) || {}; const role = d.role || {}; const no = String(role.number || d.uid || '').trim(); if (/^\d{6,20}$/.test(no)) return no; } catch (e) {} return ''; } function resolveStudent(force) { if (!force && studentCache.no && Date.now() - studentCache.at < 120000) { return Promise.resolve(studentCache.no); } if (resolvingStudent) return resolvingStudent; resolvingStudent = (async () => { let no = guessStudent(); const portal = await fetchPortalStudent(); // 门户当前登录账号最权威:换号后不会拿旧学号去扣额度 if (portal) no = portal; resolvingStudent = null; if (no) { studentCache.no = no; studentCache.at = Date.now(); gmSet('gk_student', no); } return no; })(); return resolvingStudent; } const maskStudent = (no) => no ? (no.slice(0, 3) + '****' + no.slice(-4)) : ''; // ======== 授权 / 额度 ======== let AUTH = gmGet(CFG.AUTH_KEY, {}) || {}; let USAGE = null; const now = () => Date.now(); const token = () => AUTH.token || AUTH.trialToken || ''; const trialActive = () => !AUTH.token && AUTH.trialToken && (AUTH.trialEnd || 0) > now(); const isAuthed = () => !!AUTH.token || trialActive(); let expiredLogged = false; function saveAuth() { gmSet(CFG.AUTH_KEY, AUTH); } function trialLeftText() { if (AUTH.token) return '已登录:' + (AUTH.user || '用户'); if (trialActive()) { const s = Math.max(0, Math.floor((AUTH.trialEnd - now()) / 1000)); const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), ss = s % 60; return '体验剩余 ' + String(h).padStart(2, '0') + ':' + String(m).padStart(2, '0') + ':' + String(ss).padStart(2, '0'); } if (AUTH.trialUsed) return '体验已结束,注册后继续'; return '未登录:点下面「注册 / 登录」或「免费体验 120 分钟」'; } function quotaText() { if (!USAGE) return isAuthed() ? '正在读取额度…' : '登录/体验后显示额度'; if (USAGE.kind === 'trial') { return '体验已用学号 ' + (USAGE.used || 0) + '/' + (USAGE.limit || 3) + ';到期后注册,每天免费 1 个学号'; } return '今日学号 ' + ((USAGE.today || []).length) + ' 个(免费名额' + (USAGE.free_used ? '已用' : '可用') + ')· 点数 ' + (USAGE.credits || 0) + ' · 明天还有 1 个免费(只认学号)'; } function renderQuota() { el('#quota').textContent = quotaText(); authline.textContent = trialLeftText(); const cta = el('#authCta'); if (cta) cta.style.display = isAuthed() ? 'none' : 'block'; } async function api(path, body) { const r = await gmXhr({ method: 'POST', url: CFG.SERVER_BASE + path, headers: { 'Content-Type': 'application/json' }, data: JSON.stringify(body) }); let j = {}; try { j = JSON.parse(r.responseText || '{}'); } catch (e) {} j._status = r.status; return j; } async function loadUsage() { if (!isAuthed()) { USAGE = null; renderQuota(); return; } try { const j = await api('/dati/api/usage', { token: token(), device: deviceId() }); if (j.ok) { USAGE = j; if (j.kind === 'trial' && j.left) AUTH.trialEnd = now() + j.left * 1000; } else if (j._status === 401) { AUTH = {}; saveAuth(); USAGE = null; } } catch (e) {} renderQuota(); } async function startTrial() { authMsg.textContent = '正在开通体验…'; try { const j = await api('/dati/api/trial/start', { device: deviceId() }); if (!j.ok) { authMsg.textContent = j.error || '体验开通失败'; if (j._status === 429) authForm.style.display = 'block'; return; } AUTH.trialToken = j.token; AUTH.trialEnd = (j.end || 0) * 1000; AUTH.trialUsed = true; saveAuth(); log('体验已开始:120 分钟(最多 3 个学号)'); closeGate(true); loadUsage(); } catch (e) { authMsg.textContent = '体验开通失败:' + e.message; } } // ======== 面板 ======== const host = document.createElement('div'); host.id = 'gk-trial-host'; (document.body || document.documentElement).appendChild(host); const root = host.attachShadow({ mode: 'open' }); root.innerHTML = `
国开助手
国开助手 v0.5.8
关闭

当前页面

未登录:点下面「注册 / 登录」或「免费体验 120 分钟」
还没有开通:先免费体验 120 分钟,或注册一个账号
检测中…

额度

登录/体验后显示额度(学号自动识别)

题目查询(答案走服务器)

答案题型(不选则自动)

点数

注册后每天免费 1 个学号;第 2 个起 1 点 = 1 个学号/天。购买点数请展开下方「服务咨询」。
服务咨询
服务咨询QQ 正式版 检查更新
支付暂未开放;购买点数或正式版请通过服务咨询QQ联系。

开始使用

先选一种方式:免费体验 120 分钟(全功能,最多 3 个学号,不注册),或 注册(每天免费 1 个学号,更多按点数)。

体验结束或学号用完,可继续注册;正式版可在面板底部查看服务咨询。
以后再说
`; const el = (s) => root.querySelector(s); const panel = el('#panel'), fab = el('#fab'); const aidInput = el('#aid'), qInput = el('#q'), qtypeInput = el('#qtype'); const ansBox = el('#ans'), logBox = el('#log'); const btnTest = el('#testvideo'), btnScan = el('#scan'), btnAsk = el('#ask'); const btnExam = el('#autoexam'); function examBtnIdleText() { return el('#autosubmit').checked ? '自动答题并交卷' : '自动答题(只暂存)'; } el('#autosubmit').addEventListener('change', () => { if (!state.examRunning) btnExam.textContent = examBtnIdleText(); }); const gate = el('#gate'), authForm = el('#authForm'), authMsg = el('#authMsg'); const authline = el('#authline'); el('#qq').textContent = CFG.QQ_GROUP; el('#home').href = CFG.HOMEPAGE; function log(msg) { const t = new Date().toTimeString().slice(0, 8); logBox.textContent += `[${t}] ${msg}\n`; logBox.scrollTop = logBox.scrollHeight; } async function copyText(text, label) { try { if (typeof GM_setClipboard === 'function') GM_setClipboard(text, 'text'); else await navigator.clipboard.writeText(text); log((label || '内容') + '已复制'); return true; } catch (e) { log('复制失败,请手动选择'); return false; } } function setOpen(open) { panel.classList.toggle('open', open); gmSet(CFG.PANEL_KEY, open ? 1 : 0); } fab.addEventListener('click', () => setOpen(!panel.classList.contains('open'))); el('#close').addEventListener('click', () => setOpen(false)); el('#copyqq').addEventListener('click', () => copyText(CFG.QQ_GROUP, '服务咨询QQ')); el('#copyinfo').addEventListener('click', () => { const txt = [ (el('#pageinfo').textContent || '').trim(), '网址:' + location.href, '版本:' + (el('.hd span') ? el('.hd span').textContent : ''), '账号:' + trialLeftText() ].join('\n'); copyText(txt, '页面信息'); }); el('#copyans').addEventListener('click', () => { let t = (ansBox.textContent || '').trim(); if (!t || t === '请求服务器…') { log('还没有答案可复制'); return; } t = t.replace(/\n来源:[\s\S]*$/, '').trim(); copyText(t, '答案'); }); el('#copylog').addEventListener('click', () => { const t = (logBox.textContent || '').trim(); if (!t) { log('日志为空'); return; } copyText(t, '日志'); }); el('#clearlog').addEventListener('click', () => { logBox.textContent = ''; log('日志已清空'); }); function updateAuthline() { authline.textContent = trialLeftText(); if (!isAuthed() && AUTH.trialUsed && !expiredLogged) { expiredLogged = true; log('体验已结束:注册后继续(明天还有 1 个免费学号)'); renderQuota(); } if (trialActive()) expiredLogged = false; } setInterval(updateAuthline, 1000); let gateResolve = null; function openGate() { gate.classList.add('open'); if (gateResolve) gateResolve(false); return new Promise((r) => { gateResolve = r; }); } function closeGate(ok) { gate.classList.remove('open'); if (gateResolve) { gateResolve(ok); gateResolve = null; } } async function ensureAuth() { if (isAuthed()) return true; return openGate(); } el('#startTrial').addEventListener('click', () => { startTrial(); }); el('#showAuth').addEventListener('click', () => { authForm.style.display = 'block'; authMsg.textContent = ''; }); el('#gateLater').addEventListener('click', () => closeGate(false)); el('#ctaTrial').addEventListener('click', () => { openGate(); startTrial(); }); el('#ctaAuth').addEventListener('click', () => { openGate(); authForm.style.display = 'block'; authMsg.textContent = ''; }); el('#doLogin').addEventListener('click', async () => { const u = el('#u').value.trim(), p = el('#p').value; if (!u || !p) { authMsg.textContent = '用户名和密码都要填'; return; } authMsg.textContent = '登录中…'; try { const j = await api('/dati/api/auth/login', { username: u, password: p, device: deviceId() }); if (!j.ok) throw new Error(j.error || ('HTTP ' + j._status)); AUTH.token = j.token; AUTH.user = j.name || u; AUTH.expires = j.expires || ''; saveAuth(); log('登录成功:' + AUTH.user); closeGate(true); loadUsage(); } catch (e) { authMsg.textContent = '登录失败:' + e.message; } }); el('#doReg').addEventListener('click', async () => { const u = el('#u').value.trim(), p = el('#p').value; if (!u || !p) { authMsg.textContent = '用户名和密码都要填'; return; } authMsg.textContent = '注册中…'; try { // 注册来源由服务器记录,客户只填账号密码 const r1 = await api('/dati/api/auth/register', { username: u, password: p, device: deviceId(), channel: 'script' }); if (!r1.ok) throw new Error(r1.error || ('HTTP ' + r1._status)); if (r1.pending) { authMsg.textContent = '注册已提交,等待开通;详情请查看面板底部「服务咨询」。'; return; } const j = await api('/dati/api/auth/login', { username: u, password: p, device: deviceId() }); if (!j.ok) throw new Error('注册成功但登录失败:' + (j.error || '')); AUTH.token = j.token; AUTH.user = j.name || u; AUTH.expires = j.expires || ''; saveAuth(); log('注册并登录成功:' + AUTH.user); closeGate(true); loadUsage(); } catch (e) { authMsg.textContent = '注册失败:' + e.message; } }); async function bindStudent(quiet) { if (!isAuthed()) return false; // 不让客户手动绑定:从页面/学校门户自动识别当前登录学号 const sno = await resolveStudent(true); if (!sno) { if (!quiet) log('没识别到学号:请确认已在国开登录;识别不到可咨询服务咨询QQ'); return false; } try { const j = await api('/dati/api/student/bind', { token: token(), device: deviceId(), student_no: sno }); if (!j.ok) { log(j.error || '学号绑定失败'); if (j.today) { USAGE = { kind: 'user', today: j.today, credits: j.credits || 0, free_used: true, tomorrow_free: 1 }; renderQuota(); } return false; } studentCache.no = sno; gmSet('gk_student', sno); log('学号已识别:' + maskStudent(sno)); await loadUsage(); return true; } catch (e) { log('学号绑定失败:' + e.message); return false; } } const state = { running: false, examRunning: false }; function refreshPageInfo() { const aid = aidInput.value.trim() || guessActivityId(); const v = pickVideo(); const dur = v && isFinite(v.duration) && v.duration > 0 ? Math.round(v.duration) : 0; let pname = location.pathname; try { pname = decodeURIComponent(pname); } catch (e) {} let s = '页面:' + pname; s += '\n活动ID:' + (aid || '未识别(可手填)'); const eid = guessExamId(); if (eid) s += '\n试卷ID:' + eid; s += '\n视频:' + (v ? (dur ? dur + ' 秒' : '已找到,时长未加载') : '未找到'); s += '\n学号:' + (studentCache.no ? maskStudent(studentCache.no) + '(自动识别)' : '识别中…'); if (!aidInput.value && aid) aidInput.value = aid; el('#pageinfo').textContent = s; } btnScan.addEventListener('click', () => { log('重新识别…'); refreshPageInfo(); }); // ======== 自动答题(当前试卷)======== const EXAM_AB = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const COMPOUND_TYPES = ['matching', 'cloze', 'analysis', 'compound', 'group', 'material']; function stripHtml(html) { try { const d = document.createElement('div'); d.innerHTML = html || ''; return (d.textContent || '').replace(/\s+/g, ' ').trim(); } catch (e) { return String(html || '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim(); } } function normText(s) { return String(s || '').toLowerCase().replace(/[^0-9a-z\u4e00-\u9fff]+/g, ''); } function optLabel(o) { return stripHtml((o && o.content) || '').replace(/^[A-Da-d]\s*[.、))::]\s*/, ''); } function isSingleType(t) { return ['single_selection', 'true_or_false', 'true_false', 'single_choice', 'judge', '单选', '判断'].includes(String(t || '')); } function isSubjectiveType(t) { return ['fill_in_blank', 'short_answer', 'analysis', 'essay', '填空', '简答', '论述', '名词解释'].includes(String(t || '')); } function mapAnswer(opts, answer, single) { if (!opts || !opts.length || !answer) return []; const sorted = opts.slice().sort((a, b) => (a.sort || 0) - (b.sort || 0)); const a0 = String(answer).trim(); if (!a0) return []; const segs = a0.split(/\/&\/|\|/).map((s) => s.trim()).filter(Boolean); if (segs.length > 1) { const out = []; for (const s of segs) { for (const id of mapAnswer(sorted, s, false)) if (!out.includes(id)) out.push(id); } return single ? out.slice(0, 1) : out; } // 纯字母:A / AB / A,B / A、C if (/^[A-Za-z](?:[\s,,、/&;.]*[A-Za-z])*$/.test(a0)) { const letters = (a0.toUpperCase().match(/[A-Z]/g) || []); const sep = /[,,、/&;.]/.test(a0); if (!(single && letters.length > 1 && !sep) && letters.every((L) => EXAM_AB.indexOf(L) < sorted.length)) { const ids = letters.map((L) => sorted[EXAM_AB.indexOf(L)].id).filter(Boolean); return single ? ids.slice(0, 1) : ids; } } // 判断题:对/错/正确/错误/√/× if (sorted.length === 2) { const t = a0.replace(/\s+/g, ''); const wrong = /错误|错|不对|×|✗|false/i.test(t); const right = !wrong && /正确|对|是|√|✓|true/i.test(t); if (wrong || right) { for (const o of sorted) { const c = optLabel(o); if (wrong ? /错误|错|否|×|✗|false/i.test(c) : /正确|对|是|√|✓|true/i.test(c)) { return [o.id]; } } } } // 文本:先精确,再互相包含 const raw = stripHtml(a0); const clean = raw.replace(/^[A-Da-d]\s*[.、))::]\s*/, ''); const na = normText(clean); if (na) { for (const o of sorted) if (normText(optLabel(o)) === na) return [o.id]; if (na.length >= 2) { for (const o of sorted) { const no = normText(optLabel(o)); if (no && (no.includes(na) || na.includes(no))) return [o.id]; } } } return []; } async function imgKey(html) { try { if (!html || String(html).toLowerCase().indexOf(']*>/gi; let m; while ((m = re.exec(html))) { const sm = /src\s*=\s*["']([^"']+)["']/i.exec(m[0]); if (sm) srcs.push(sm[1]); } if (!srcs.length) return ''; srcs.sort(); const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(srcs.join('|'))); const hex = Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, '0')).join(''); return 'img:' + hex.slice(0, 16); } catch (e) { return ''; } } function leavesOf(subject, pool) { const ty = String((subject && subject.type) || ''); const subs = (subject && subject.sub_subjects) || []; const cur = ((subject && subject.options) || []).length ? subject.options : (pool || []); if (COMPOUND_TYPES.includes(ty) && subs.length) { let out = []; for (const c of subs) out = out.concat(leavesOf(c, cur)); return out; } return [{ s: subject, opts: cur }]; } async function lmsJson(path, opts) { const o = Object.assign({ credentials: 'include' }, opts || {}); o.headers = Object.assign({ 'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest' }, o.headers || {}); const ctl = new AbortController(); const timer = setTimeout(() => ctl.abort(), 30000); o.signal = ctl.signal; let r; try { r = await fetch(path, o); } catch (e) { throw new Error(e && e.name === 'AbortError' ? '平台请求超时' : (e.message || '平台请求失败')); } finally { clearTimeout(timer); } const text = await r.text(); let j = {}; if (text) { try { j = JSON.parse(text); } catch (e) { throw new Error('平台返回非 JSON(可能被拦截)'); } } if (!r.ok) throw new Error('平台 HTTP ' + r.status + ((j && (j.message || j.error)) ? ':' + (j.message || j.error) : '')); return j || {}; } const lmsGet = (path) => lmsJson(path); const lmsPost = (path, body) => lmsJson(path, { method: 'POST', headers: { 'Content-Type': 'application/json;charset=UTF-8' }, body: JSON.stringify(body || {}) }); async function askOne(qtext, qtype, options) { const j = await api('/dati/api/answer', { token: token(), device: deviceId(), course: guessCourse(), question: qtext, qtype: qtype, options: options || [] }); if (!j.ok) throw new Error(j.error || ('答案服务 HTTP ' + j._status)); return j; } function fillParts(answer, subject) { let parts = String(answer || '').split(/\/&\/|[;;\n]/).map((s) => s.trim()).filter(Boolean); let n = parseInt(subject.answer_number, 10); if (!n) n = ((subject.description || '').match(/__blank__/g) || []).length || parts.length || 1; while (parts.length < n) parts.push(''); return parts.slice(0, n); } async function autoExam() { if (state.examRunning) { log('正在答题中,请稍候…'); return; } const examId = guessExamId() || (/^\d{5,}$/.test(aidInput.value.trim()) ? aidInput.value.trim() : ''); if (!examId) { log('没识别到试卷ID:请从考试页面点进来,或在输入框手填'); return; } if (!(await ensureAuth())) return; if (!(await bindStudent(false))) return; const doSubmit = !!el('#autosubmit').checked; state.examRunning = true; btnExam.disabled = true; btnExam.textContent = '答题中…'; try { log('自动答题:试卷 ' + examId); try { const old = await lmsGet('/api/exams/' + examId + '/submissions'); const arr = (old && old.submissions) || []; if (arr.length) { const best = Math.max(...arr.map((x) => parseFloat(x.score || 0))); log('这份卷已交过 ' + arr.length + ' 次(最好 ' + best + ' 分),不重复交卷'); return; } } catch (e) { log('历史提交读取失败(继续取卷):' + e.message); } let qual = {}; try { qual = await lmsGet('/api/exam/' + examId + '/check-exam-qualification?no-intercept=true&check_status=start'); } catch (e) { log('资格检查失败(继续取卷):' + e.message); } if (qual && qual.is_closed) { log('考试已截止:' + (qual.message || '')); return; } try { await lmsPost('/api/course/activities-read/exam/' + examId, {}); } catch (e) {} let dist; try { dist = await lmsGet('/api/exams/' + examId + '/distribute'); } catch (e) { log('取卷失败:' + e.message + ';请先在页面点「开始答题」,再点本按钮'); return; } const data = (dist && dist.subjects) ? dist : ((dist && dist.data) || {}); const trees = data.subjects || []; if (!trees.length) { log('平台未下发题目:先在页面点「开始答题」,或稍后再试'); return; } const inst = data.exam_paper_instance_id || dist.exam_paper_instance_id; if (!inst) { log('没拿到 exam_paper_instance_id,停止'); return; } let leaves = []; for (const t of trees) leaves = leaves.concat(leavesOf(t, null)); leaves = leaves.filter((x) => String((x.s && x.s.type) || '') !== 'text'); const total = leaves.length; log('取到 ' + total + ' 道题,开始作答…'); const payload = []; let hit = 0, skipped = 0, aiUsed = 0; for (let i = 0; i < leaves.length; i++) { const s = leaves[i].s || {}; const opts = (leaves[i].opts || []).slice().sort((a, b) => (a.sort || 0) - (b.sort || 0)); const ty = String(s.type || ''); const html = s.description || ''; let qtext = stripHtml(html); if (qtext.length < 4) { const k = await imgKey(html); if (k) qtext = k; } btnExam.textContent = '答题中 ' + (i + 1) + '/' + total; if (!qtext) { skipped++; continue; } if (opts.length) { try { const j = await askOne(qtext, ty, opts.map((o) => stripHtml(o.content || '').slice(0, 200)).slice(0, 20)); if (j.source === 'ai') aiUsed++; const ids = mapAnswer(opts, j.answer, isSingleType(ty)); if (ids.length) { payload.push({ subject_id: s.id, subject_updated_at: s.last_updated_at, answer_option_ids: ids }); hit++; const picked = opts.filter((o) => ids.includes(o.id)).map((o) => optLabel(o).slice(0, 12)).join('、'); log('[' + (i + 1) + '/' + total + '] 选择题 → ' + (picked || ('选项 ' + ids.join(','))) + '(' + (j.source === 'bank' ? '题库' : 'AI') + ')'); } else { skipped++; log('[' + (i + 1) + '/' + total + '] 选择题未匹配:' + qtext.slice(0, 28)); } } catch (e) { skipped++; log('[' + (i + 1) + '/' + total + '] 取答失败:' + e.message); } } else if (isSubjectiveType(ty)) { try { const j = await askOne(qtext, ty, []); if (j.answer) { if (ty === 'fill_in_blank') { const parts = fillParts(j.answer, s); payload.push({ subject_id: s.id, subject_updated_at: s.last_updated_at, answers: parts.map((content, idx) => ({ sort: idx, content: content })) }); } else { payload.push({ subject_id: s.id, subject_updated_at: s.last_updated_at, answer: j.answer, attachments: [] }); } if (j.source === 'ai') aiUsed++; hit++; log('[' + (i + 1) + '/' + total + '] ' + ty + ' 已作答(' + (j.source === 'bank' ? '题库' : 'AI') + ')'); } else { skipped++; log('[' + (i + 1) + '/' + total + '] ' + ty + ' 没有答案,留人工'); } } catch (e) { skipped++; log('[' + (i + 1) + '/' + total + '] ' + ty + ' 取答失败:' + e.message); } } else { skipped++; log('[' + (i + 1) + '/' + total + '] ' + (ty || '未知题型') + ' 留人工'); } await sleep(120); } const kept = payload.filter((x) => { const n = parseInt(x.subject_id, 10); return Number.isFinite(n) && n >= 1; }); if (kept.length !== payload.length) { log((payload.length - kept.length) + ' 个作答节点 subject_id 无效(<1),已剔除'); } payload.length = 0; payload.push.apply(payload, kept); log('作答结束:命中 ' + hit + '/' + total + ',跳过 ' + skipped + (aiUsed ? (',AI ' + aiUsed + ' 次') : '')); if (!payload.length) { log('没有可提交的作答,未交卷'); return; } const st = await lmsPost('/api/exams/' + examId + '/submissions/storage', { exam_paper_instance_id: inst, exam_submission_id: null, subjects: payload }); const sid = (st && (st.exam_submission_id || st.id || st.submission_id)) || null; log('暂存完成' + (sid ? '(' + sid + ')' : '')); if (!doSubmit) { log('已填写未交卷(勾选“答完自动交卷”才会提交)'); return; } const answered = payload.filter((x) => (x.answer_option_ids && x.answer_option_ids.length) || x.answer || (x.answers && x.answers.some((a) => a.content))).length; const sub = await lmsPost('/api/exams/' + examId + '/submissions', { exam_paper_instance_id: inst, exam_submission_id: sid, subjects: payload, progress: { answered_num: answered, total_subjects: payload.length }, reason: 'user' }); const subId = sub && (sub.submission_id || sub.id); let score = sub && (sub.exam_score !== undefined ? sub.exam_score : sub.score); if (score === undefined) { try { const ls = await lmsGet('/api/exams/' + examId + '/submissions'); const arr = (ls && ls.submissions) || []; if (arr.length) score = arr[arr.length - 1].score; } catch (e) {} } log('交卷完成' + (subId ? '(' + subId + ')' : '') + (score !== undefined ? ',得分 ' + score : '')); } catch (e) { log('自动答题失败:' + (e && e.message ? e.message : e)); } finally { state.examRunning = false; btnExam.disabled = false; btnExam.textContent = examBtnIdleText(); } } btnExam.addEventListener('click', autoExam); async function runVideo() { if (state.running) { state.running = false; log('已停止'); return; } const v = pickVideo(); if (!v) { log('没找到视频:先打开一个视频活动页'); return; } const aid = aidInput.value.trim() || guessActivityId(); if (!aid) { log('没识别到活动ID:请在输入框手填'); return; } let dur = v.duration; if (!isFinite(dur) || dur <= 0) { log('视频时长还没加载:先点一下页面播放器再试'); return; } state.running = true; btnTest.textContent = '停止'; log(`开始试跑:活动 ${aid},时长 ${Math.round(dur)} 秒`); try { await v.play(); v.playbackRate = CFG.VIDEO_RATE; log('播放器已启动,倍速 ' + CFG.VIDEO_RATE + 'x'); } catch (e) { log('播放器启动失败(不影响区间上报)'); } let t = 0; while (t < dur - 0.5 && state.running) { const t1 = Math.min(t + CFG.CHUNK, dur); try { const r = await fetch('/api/course/activities-read/' + aid, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, body: JSON.stringify({ start: Math.floor(t), end: Math.floor(t1) }) }); log(`上报 ${Math.floor(t)}-${Math.floor(t1)} 秒 → HTTP ${r.status}`); if (r.status >= 400) { log('平台拒绝上报,先停'); break; } } catch (e) { log('上报失败:' + (e && e.message ? e.message : e)); } t = t1; await sleep(250); } state.running = false; btnTest.textContent = '试跑视频'; if (t >= dur - 0.5) log('区间已全部报完'); } btnTest.addEventListener('click', async () => { if (!(await ensureAuth())) return; if (!(await bindStudent(false))) return; runVideo(); }); async function askServer() { const q = qInput.value.trim(); if (!q) { log('先把题目贴进来'); return; } ansBox.textContent = '请求服务器…'; try { const j = await api('/dati/api/answer', { token: token(), device: deviceId(), course: guessCourse(), question: q, qtype: (qtypeInput.value || '').trim() }); if (!j.ok) throw new Error(j.error || ('HTTP ' + j._status)); ansBox.textContent = (j.answer || '(空)') + '\n来源:' + (j.source === 'bank' ? '网络题库' : 'AI 兜底'); } catch (e) { ansBox.textContent = '失败:' + (e && e.message ? e.message : e); } } btnAsk.addEventListener('click', async () => { if (!(await ensureAuth())) return; if (!(await bindStudent(false))) return; askServer(); }); qInput.addEventListener('keydown', (e) => { if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { e.preventDefault(); btnAsk.click(); } }); el('#redeem').addEventListener('click', async () => { if (!AUTH.token) { log('先注册登录再兑换'); return; } const code = el('#code').value.trim(); if (!code) { log('先填卡密'); return; } try { const j = await api('/dati/api/redeem', { token: AUTH.token, device: deviceId(), code: code }); if (!j.ok) throw new Error(j.error || ('HTTP ' + j._status)); log('兑换成功:+' + j.added + ' 点,当前 ' + j.credits + ' 点'); el('#code').value = ''; loadUsage(); } catch (e) { log('兑换失败:' + e.message); } }); if (typeof GM_registerMenuCommand === 'function') { GM_registerMenuCommand('打开国开助手面板', () => setOpen(true)); } setOpen(!!gmGet(CFG.PANEL_KEY, 0)); updateAuthline(); refreshPageInfo(); renderQuota(); log('脚本已加载(v0.5.8)'); resolveStudent().then((no) => { if (no) { log('学号已识别:' + maskStudent(no) + '(无需手动绑定)'); refreshPageInfo(); } }); if (isAuthed()) loadUsage(); setInterval(refreshPageInfo, 5000); })();