// ==UserScript==
// @name 2026年5月广东省教师继续教育-自动学习答题
// @namespace auto-study-gds
// @version 12.4
// @description 自动播放视频、自动切换下一节、自动答题、防挂机检测、AI考核
// @match https://jsxx.gds.edu.cn/study/course/*
// @match https://jsglpt.gds.edu.cn/study/course/*
// @match https://jsxx.gds.edu.cn/*/study/course/*
// @match https://jsglpt.gds.edu.cn/*/study/course/*
// @grant GM_xmlhttpRequest
// @run-at document-idle
// ==/UserScript==
(function () {
'use strict';
var CFG = {
CHECK_MS: 5000,
MOUSE_MS: 15000,
SCROLL_MS: 25000,
CLICK_MS: 45000,
QUIZ_MS: 2000,
COMPLETE_WAIT: 60000,
INIT_MS: 3000,
MAX_LOG: 200,
DQ_TIMEOUT: 60000,
DQ_INTERVAL: 1500,
};
var CID = (function () {
var m = location.pathname.match(/c_([a-f0-9]{32})/i);
return m ? 'c_' + m[1] : null;
})();
var STKEY = '_as9_' + (CID || 'unk');
var _db = {};
function loadDB() {
try {
var s = localStorage.getItem(STKEY);
if (s) _db = JSON.parse(s);
if (!_db || typeof _db !== 'object') _db = {};
} catch (e) { _db = {}; }
if (!_db.items) _db.items = {};
}
function saveDB() {
try { localStorage.setItem(STKEY, JSON.stringify(_db)); } catch (e) { }
}
function setStatus(aid, wat, req, done, name) {
if (!_db.items[aid]) _db.items[aid] = {};
_db.items[aid].wat = wat;
_db.items[aid].req = req;
_db.items[aid].done = done;
_db.items[aid].name = name || '';
_db.items[aid].ts = Date.now();
saveDB();
}
function getStatus(aid) {
return _db.items[aid] || null;
}
function isKnownDone(aid) {
var s = getStatus(aid);
return s && s.done === true;
}
function allDBItems() {
return _db.items || {};
}
function getProgress() {
var items = _db.items || {};
var keys = Object.keys(items);
var total = 0, done = 0;
for (var i = 0; i < keys.length; i++) {
if (keys[i].indexOf('a_') !== 0) continue;
total++;
if (items[keys[i]].done) done++;
}
return { total: total, done: done };
}
var LOG = [];
function log(msg, t) {
t = t || 'info';
var ts = new Date().toLocaleTimeString();
var p = { info: 'INF', warn: 'WRN', error: 'ERR', quiz: 'Q', vid: 'V', exam: 'E' };
var line = '[' + ts + '][' + (p[t] || 'INF') + '] ' + msg;
console.log('[AS] ' + line);
LOG.push(line);
if (LOG.length > CFG.MAX_LOG) LOG.shift();
refreshLogUI();
}
var _paused = false;
var _panel = false;
var _collapsed = false;
function makePanel() {
if (_panel || document.getElementById('_asP')) return;
_panel = true;
var css = document.createElement('style');
css.textContent =
'#_asP{position:fixed;top:12px;right:12px;z-index:999999;width:320px;' +
'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;' +
'user-select:none;transition:all .35s cubic-bezier(.4,0,.2,1);overflow:hidden;border-radius:14px;' +
'box-shadow:0 8px 32px rgba(0,0,0,.35),0 0 0 1px rgba(255,255,255,.06);}' +
'#_asP._coll{width:52px;border-radius:26px;}' +
'#_asH{padding:14px 16px 10px;background:linear-gradient(135deg,#1a1a2e 0%,#16213e 50%,#0f3460 100%);' +
'cursor:pointer;display:flex;align-items:center;justify-content:space-between;position:relative;overflow:hidden;}' +
'#_asP._coll #_asH{padding:12px;border-radius:26px;justify-content:center;}' +
'#_asH::before{content:"";position:absolute;top:-50%;left:-50%;width:200%;height:200%;' +
'background:conic-gradient(from 0deg,transparent,rgba(0,255,200,.06),transparent,rgba(100,100,255,.06),transparent);' +
'animation:_asSpin 8s linear infinite;}@keyframes _asSpin{to{transform:rotate(360deg)}}' +
'#_asHT{display:flex;flex-direction:column;gap:4px;position:relative;z-index:1;transition:opacity .2s;}' +
'#_asP._coll #_asHT{display:none;}' +
'#_asH1{font-size:14px;font-weight:700;color:#e0e0e0;letter-spacing:.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px;}' +
'#_asH2{font-size:11px;color:rgba(255,255,255,.5);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px;}' +
'#_asToggle{position:relative;z-index:1;width:28px;height:28px;border-radius:50%;border:1.5px solid rgba(255,255,255,.25);' +
'background:rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;flex-shrink:0;' +
'transition:transform .35s cubic-bezier(.4,0,.2,1);cursor:pointer;}' +
'#_asToggle svg{width:14px;height:14px;fill:none;stroke:rgba(255,255,255,.7);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .35s;}' +
'#_asP._coll #_asToggle{transform:rotate(180deg);}' +
'#_asBody{max-height:600px;overflow:hidden;transition:max-height .4s cubic-bezier(.4,0,.2,1),opacity .25s;opacity:1;background:#1e1e2e;}' +
'#_asP._coll #_asBody{max-height:0;opacity:0;}' +
'#_asProgWrap{padding:10px 16px 6px;background:rgba(0,0,0,.2);}' +
'#_asProgTop{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:8px;}' +
'#_asProgTxt{font-size:13px;font-weight:600;color:#e0e0e0;}' +
'#_asProgPct{font-size:11px;color:rgba(255,255,255,.45);font-weight:500;}' +
'#_asProgBar{width:100%;height:6px;background:rgba(255,255,255,.08);border-radius:3px;overflow:hidden;position:relative;}' +
'#_asProgFill{height:100%;border-radius:3px;transition:width .6s ease;position:relative;' +
'background:linear-gradient(90deg,#00d2ff,#3a7bd5);' +
'box-shadow:0 0 8px rgba(0,210,255,.4);}' +
'#_asProgFill::after{content:"";position:absolute;top:0;right:0;width:20px;height:100%;' +
'background:linear-gradient(90deg,transparent,rgba(255,255,255,.4));border-radius:3px;animation:_asShim 1.5s infinite;}' +
'@keyframes _asShim{0%{opacity:0}50%{opacity:1}100%{opacity:0}}' +
'#_asVidWrap{padding:10px 16px;display:flex;align-items:center;gap:14px;border-bottom:1px solid rgba(255,255,255,.05);}' +
'#_asRing{width:48px;height:48px;flex-shrink:0;position:relative;}' +
'#_asRing svg{width:48px;height:48px;transform:rotate(-90deg);}' +
'#_asRingBg{fill:none;stroke:rgba(255,255,255,.08);stroke-width:3.5;}' +
'#_asRingFg{fill:none;stroke-width:3.5;stroke-linecap:round;transition:stroke-dashoffset .8s ease,stroke .3s;' +
'filter:drop-shadow(0 0 4px rgba(0,255,136,.3));}' +
'#_asRingTxt{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:10px;font-weight:700;color:#e0e0e0;}' +
'#_asVidInfo{flex:1;min-width:0;}' +
'#_asVidTitle{font-size:12px;color:rgba(255,255,255,.8);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:4px;}' +
'#_asVidTime{font-size:11px;color:rgba(255,255,255,.45);font-family:Consolas,monospace;}' +
'#_asStudyRow{padding:6px 16px 10px;border-bottom:1px solid rgba(255,255,255,.05);}' +
'#_asStudyBar{width:100%;height:4px;background:rgba(255,255,255,.06);border-radius:2px;overflow:hidden;margin-top:4px;}' +
'#_asStudyFill{height:100%;border-radius:2px;transition:width .6s ease;background:linear-gradient(90deg,#f7971e,#ffd200);}' +
'#_asStudyTxt{font-size:11px;color:rgba(255,255,255,.5);}' +
'#_asTabs{display:flex;padding:0 16px;border-bottom:1px solid rgba(255,255,255,.05);}' +
'#_asTabs button{flex:1;padding:8px 0;background:none;border:none;color:rgba(255,255,255,.35);font-size:11px;font-weight:600;' +
'cursor:pointer;position:relative;transition:color .2s;}' +
'#_asTabs button:hover{color:rgba(255,255,255,.6);}' +
'#_asTabs button._act{color:#00d2ff;}' +
'#_asTabs button._act::after{content:"";position:absolute;bottom:0;left:20%;right:20%;height:2px;' +
'background:#00d2ff;border-radius:1px;box-shadow:0 0 6px rgba(0,210,255,.5);}' +
'#_asPanels{max-height:200px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.1) transparent;}' +
'#_asPanels::-webkit-scrollbar{width:4px;}' +
'#_asPanels::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:2px;}' +
'#_asPanel{display:none;padding:8px 16px 10px;}' +
'#_asPanel._act{display:block;}' +
'#_asList ._asItem{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid rgba(255,255,255,.03);font-size:11px;}' +
'#_asList ._asItem:last-child{border-bottom:none;}' +
'#_asDot{width:8px;height:8px;border-radius:50%;flex-shrink:0;}' +
'#_asDot.ok{background:#00ff88;box-shadow:0 0 6px rgba(0,255,136,.4);}' +
'#_asDot.ing{background:#ffd200;box-shadow:0 0 6px rgba(255,210,0,.4);}' +
'#_asDot.no{background:rgba(255,255,255,.15);}' +
'#_asDot.cur{background:#00d2ff;box-shadow:0 0 6px rgba(0,210,255,.5);animation:_asPulse 1.5s infinite;}' +
'@keyframes _asPulse{0%,100%{box-shadow:0 0 4px rgba(0,210,255,.3)}50%{box-shadow:0 0 10px rgba(0,210,255,.6)}}' +
'#_asINm{flex:1;color:rgba(255,255,255,.7);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}' +
'#_asINm.cur{color:#00d2ff;font-weight:600;}' +
'#_asITm{font-size:10px;color:rgba(255,255,255,.3);font-family:Consolas,monospace;flex-shrink:0;}' +
'#_asLogLine{font-size:10px;color:rgba(255,255,255,.4);font-family:Consolas,monospace;padding:2px 0;border-bottom:1px solid rgba(255,255,255,.02);line-height:1.5;word-break:break-all;}' +
'#_asLogLine .t{color:rgba(255,255,255,.2);margin-right:6px;}' +
'#_asLogLine .tag{color:#00d2ff;}' +
'#_asLogLine .w{color:#ffd200;}' +
'#_asLogLine .e{color:#ff5555;}' +
'#_asLogLine .q{color:#c084fc;}' +
'#_asLogLine .v{color:#00ff88;}' +
'#_asLogLine .ex{color:#ff9f43;}' +
'#_asBtns{display:flex;gap:8px;padding:10px 16px 14px;background:rgba(0,0,0,.15);}' +
'#_asBtns button{flex:1;padding:7px 0;border:none;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;' +
'transition:all .2s;position:relative;overflow:hidden;}' +
'#_asBtns button:active{transform:scale(.96);}' +
'#_asB1{background:rgba(255,255,255,.08);color:#e0e0e0;}' +
'#_asB1:hover{background:rgba(255,255,255,.14);}' +
'#_asB1._paused{background:linear-gradient(135deg,#3a7bd5,#00d2ff);color:#fff;}' +
'#_asB2{background:rgba(0,210,255,.12);color:#00d2ff;}' +
'#_asB2:hover{background:rgba(0,210,255,.22);}' +
'#_asB4{background:rgba(0,255,136,.12);color:#00ff88;}' +
'#_asB4:hover{background:rgba(0,255,136,.22);}' +
'#_asExam{padding:10px 16px 14px;border-top:1px solid rgba(255,255,255,.08);background:rgba(100,50,200,.08);}' +
'#_asExamKey{padding:6px 16px 8px;border-bottom:1px solid rgba(255,255,255,.08);background:rgba(0,0,0,.1);}' +
'#_asExamKeyH{font-size:11px;color:rgba(255,255,255,.5);margin-bottom:4px;}' +
'#_asExamKey input{width:100%;box-sizing:border-box;padding:6px 10px;border-radius:6px;border:1px solid rgba(255,255,255,.15);' +
'background:rgba(0,0,0,.3);color:#e0e0e0;font-size:11px;font-family:Consolas,monospace;outline:none;transition:border-color .2s;}' +
'#_asExamKey input:focus{border-color:#c084fc;}' +
'#_asExamKey input::placeholder{color:rgba(255,255,255,.2);}' +
'#_asExamKeyBtns{display:flex;gap:6px;margin-top:6px;}' +
'#_asExamKeyBtns button{flex:1;padding:4px 0;border:none;border-radius:4px;font-size:10px;font-weight:600;cursor:pointer;transition:all .2s;}' +
'#_asExamKeyBtns button:active{transform:scale(.96);}' +
'#_asK1{background:rgba(0,255,136,.15);color:#00ff88;}' +
'#_asK1:hover{background:rgba(0,255,136,.25);}' +
'#_asK2{background:rgba(255,255,255,.06);color:rgba(255,255,255,.5);}' +
'#_asK2:hover{background:rgba(255,255,255,.12);}' +
'#_asExamH{margin-bottom:8px;}' +
'#_asExamH1{font-size:13px;font-weight:700;color:#c084fc;}' +
'#_asExamH2{font-size:11px;color:rgba(255,255,255,.5);margin-top:2px;}' +
'#_asExamQ{font-size:11px;color:rgba(255,255,255,.8);margin:8px 0;max-height:60px;overflow:hidden;line-height:1.5;}' +
'#_asExamOpts{margin:6px 0;}' +
'#_asExamOpts button{display:block;width:100%;padding:5px 8px;margin:3px 0;border:1px solid rgba(255,255,255,.1);border-radius:6px;' +
'background:rgba(255,255,255,.04);color:rgba(255,255,255,.7);font-size:11px;text-align:left;cursor:pointer;transition:all .15s;}' +
'#_asExamOpts button:hover{background:rgba(255,255,255,.08);}' +
'#_asExamOpts button._sel{background:rgba(100,50,200,.25);border-color:#c084fc;color:#fff;}' +
'#_asExamAct{display:flex;gap:6px;margin-top:8px;}' +
'#_asExamAct button{flex:1;padding:6px 0;border:none;border-radius:6px;font-size:11px;font-weight:600;cursor:pointer;transition:all .2s;}' +
'#_asExamAct button:active{transform:scale(.96);}' +
'#_asEB1{background:rgba(100,50,200,.2);color:#c084fc;}' +
'#_asEB1:hover{background:rgba(100,50,200,.35);}' +
'#_asEB2{background:rgba(255,255,255,.08);color:#e0e0e0;}' +
'#_asEB2:hover{background:rgba(255,255,255,.14);}' +
'#_asEB3{background:rgba(0,255,136,.15);color:#00ff88;}' +
'#_asEB3:hover{background:rgba(0,255,136,.25);}' +
'#_asEB4{background:rgba(255,100,50,.15);color:#ff6432;}' +
'#_asEB4:hover{background:rgba(255,100,50,.25);}' +
'#_asExamProg{width:100%;height:4px;background:rgba(255,255,255,.06);border-radius:2px;margin-top:8px;overflow:hidden;}' +
'#_asExamProgFill{height:100%;border-radius:2px;background:linear-gradient(90deg,#c084fc,#ff6b9d);transition:width .4s ease;}';
document.head.appendChild(css);
var d = document.createElement('div');
d.id = '_asP';
d.innerHTML =
'
' +
'
' +
'
AutoStudy v12.0
' +
'
自动学习中...
' +
'
' +
'
' +
'
' +
'' +
'
' +
'
0 / 0 已完成0%
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'' +
'' +
'
' +
'
' +
'
' +
'' +
'' +
'' +
'' +
'
' +
'
' +
'
硅基流动 API Key
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'' +
'' +
'' +
'' +
'
' +
'
' +
'
' +
'
';
document.body.appendChild(d);
document.getElementById('_asToggle').onclick = function () {
_collapsed = !_collapsed;
var p = document.getElementById('_asP');
if (_collapsed) { p.classList.add('_coll'); }
else { p.classList.remove('_coll'); }
};
document.getElementById('_asB1').onclick = function () {
_paused = !_paused;
if (_paused) {
this.textContent = '继续';
this.classList.add('_paused');
} else {
this.textContent = '暂停';
this.classList.remove('_paused');
}
log(_paused ? '已暂停' : '已继续', 'warn');
};
document.getElementById('_asB2').onclick = function () {
log('手动下一节', 'warn');
_switching = false;
_promptDone = false;
nextVideo();
};
document.getElementById('_asB4').onclick = function () {
switchTab('log');
};
document.getElementById('_asB5').onclick = function () { goToExam(); };
document.getElementById('_asEB3').onclick = function () { startAutoExam(); };
document.getElementById('_asEB1').onclick = function () { enterManualExamMode(); };
document.getElementById('_asEB4').onclick = function () { stopAutoExam(); };
document.getElementById('_asEB2').onclick = function () { exitExamMode(); };
document.getElementById('_asTab1').onclick = function () { switchTab('list'); };
document.getElementById('_asTab2').onclick = function () { switchTab('log'); };
var keyInput = document.getElementById('_asKeyInput');
var savedKey = getApiKey();
if (savedKey) keyInput.value = savedKey.substring(0, 8) + '***';
document.getElementById('_asK1').onclick = function () {
var val = keyInput.value.trim();
if (val && !val.endsWith('***')) { setApiKey(val); log('API Key 已保存', 'warn'); keyInput.value = val.substring(0, 8) + '***'; }
else { log('请输入有效的 Key', 'error'); }
};
document.getElementById('_asK2').onclick = function () { setApiKey(''); keyInput.value = ''; log('API Key 已清除', 'warn'); };
keyInput.onfocus = function () {
var realKey = getApiKey();
if (realKey) keyInput.value = realKey;
};
log('API Key: ' + (savedKey ? '已设置' : '未设置'), savedKey ? 'warn' : 'warn');
}
function switchTab(name) {
var btns = document.querySelectorAll('#_asTabs button');
for (var i = 0; i < btns.length; i++) {
if (btns[i].getAttribute('data-p') === name) btns[i].classList.add('_act');
else btns[i].classList.remove('_act');
}
var panels = document.querySelectorAll('#_asPanels ._asPanel');
for (var i = 0; i < panels.length; i++) {
if (panels[i].id === '_asPanel' + name.charAt(0).toUpperCase() + name.slice(1)) panels[i].classList.add('_act');
else panels[i].classList.remove('_act');
}
if (name === 'list') refreshListUI();
if (name === 'log') refreshLogUI();
}
function refreshLogUI() {
var el = document.getElementById('_asPanelLog');
if (!el || !el.classList.contains('_act')) return;
var html = '';
for (var i = LOG.length - 30; i < LOG.length; i++) {
if (i < 0) continue;
var line = LOG[i];
var cls = '_asLogLine';
line = line.replace(/\[ERR\]/g, '[ERR]');
line = line.replace(/\[WRN\]/g, '[WRN]');
line = line.replace(/\[Q\]/g, '[Q]');
line = line.replace(/\[E\]/g, '[E]');
line = line.replace(/\[V\]/g, '[V]');
line = line.replace(/\[INF\]/g, '[INF]');
html += '' + line + '
';
}
el.innerHTML = html;
el.scrollTop = el.scrollHeight;
}
function refreshVideoUI() {
var v = vid();
var ringFg = document.getElementById('_asRingFg');
var ringTxt = document.getElementById('_asRingTxt');
var vidTitle = document.getElementById('_asVidTitle');
var vidTime = document.getElementById('_asVidTime');
var studyTxt = document.getElementById('_asStudyTxt');
var studyFill = document.getElementById('_asStudyFill');
var h1 = document.getElementById('_asH1');
var h2 = document.getElementById('_asH2');
if (!v || !v.duration) {
if (ringTxt) ringTxt.textContent = '--';
if (vidTitle) vidTitle.textContent = '等待视频...';
if (vidTime) vidTime.textContent = '--:-- / --:--';
if (h2) h2.textContent = '等待视频加载...';
refreshProgUI();
return;
}
var cur = fmt(v.currentTime), dur = fmt(v.duration);
var pct = v.duration > 0 ? v.currentTime / v.duration * 100 : 0;
var circ = 125.66;
var offset = circ - (circ * pct / 100);
if (ringFg) {
ringFg.setAttribute('stroke-dashoffset', offset);
var col = pct >= 99.5 ? '#00ff88' : pct > 50 ? '#00d2ff' : '#ffd200';
ringFg.setAttribute('stroke', col);
}
if (ringTxt) ringTxt.textContent = Math.round(pct) + '%';
if (vidTitle) {
var nm = curName();
vidTitle.textContent = nm || '未知视频';
}
if (vidTime) {
var st = v.paused ? ' ||' : v.ended ? ' END' : ' >>';
vidTime.textContent = cur + ' / ' + dur + st;
}
if (h1) h1.textContent = 'AutoStudy v12.0';
if (h2) {
var nm2 = curName();
h2.textContent = nm2 ? nm2.substring(0, 30) : '自动学习中...';
}
var si = studyInfo();
if (si && si.req >= 0 && si.wat >= 0) {
if (studyTxt) studyTxt.textContent = '学习时长: ' + si.wat + ' / ' + si.req + ' min' + (si.wat >= si.req ? ' ✓' : '');
if (studyFill) {
var sp = Math.min(si.wat / si.req * 100, 100);
studyFill.style.width = sp + '%';
studyFill.style.background = sp >= 100 ? 'linear-gradient(90deg,#00ff88,#00cc6a)' : 'linear-gradient(90deg,#f7971e,#ffd200)';
}
} else {
if (studyTxt) studyTxt.textContent = '学习时长: 计算中...';
if (studyFill) studyFill.style.width = '0%';
}
refreshProgUI();
}
function refreshProgUI() {
var txt = document.getElementById('_asProgTxt');
var pct = document.getElementById('_asProgPct');
var fill = document.getElementById('_asProgFill');
if (!txt) return;
var pg = getProgress();
var p = pg.total > 0 ? Math.round(pg.done / pg.total * 100) : 0;
txt.textContent = pg.done + ' / ' + pg.total + ' 已完成';
if (pct) pct.textContent = p + '%';
if (fill) fill.style.width = p + '%';
}
function refreshListUI() {
var el = document.getElementById('_asPanelList');
if (!el) return;
var aids = allAids();
var cur = curAid();
var html = '';
for (var i = 0; i < aids.length; i++) {
var aid = aids[i];
var nm = nameById(aid) || aid.substring(0, 12);
var st = getStatus(aid);
var isCur = aid === cur;
var dotCls, nmCls;
if (isCur) {
dotCls = 'cur';
nmCls = ' cur';
} else if (st && st.done) {
dotCls = 'ok';
nmCls = '';
} else if (st && st.wat >= 0 && st.wat < st.req) {
dotCls = 'ing';
nmCls = '';
} else {
dotCls = 'no';
nmCls = '';
}
var tm = '';
if (st && st.wat >= 0 && st.req >= 0) tm = st.wat + '/' + st.req + 'm';
html += '' +
'
' + nm + '
' +
'
' + tm + '
';
}
el.innerHTML = html;
}
function spoofVis() {
try { Object.defineProperty(document, 'hidden', { get: function () { return false; }, configurable: true }); } catch (e) { }
try { Object.defineProperty(document, 'visibilityState', { get: function () { return 'visible'; }, configurable: true }); } catch (e) { }
['visibilitychange', 'webkitvisibilitychange'].forEach(function (n) {
document.addEventListener(n, function (e) { e.stopImmediatePropagation(); }, true);
});
window.addEventListener('blur', function (e) { e.stopImmediatePropagation(); }, true);
}
function fakeMouse(x, y) {
try {
var el = document.elementFromPoint(x, y);
['mouseenter', 'mouseover', 'mousemove'].forEach(function (t) {
try {
var ev = new MouseEvent(t, { bubbles: true, cancelable: true });
try { ev = new MouseEvent(t, { clientX: x, clientY: y, bubbles: true, cancelable: true }); } catch (e2) {}
if (el) el.dispatchEvent(ev);
document.dispatchEvent(ev);
} catch (e3) {}
});
} catch (e) {}
}
function fakeClick(x, y) {
try {
var el = document.elementFromPoint(x, y);
if (!el) return;
var tg = el.tagName.toLowerCase();
if (['video', 'input', 'select', 'textarea', 'a', 'button'].indexOf(tg) >= 0) return;
if (el.closest('video,input,select,textarea,a.btn,button')) return;
['mousedown', 'mouseup', 'click'].forEach(function (t) {
try {
var ev = new MouseEvent(t, { bubbles: true, cancelable: true, button: 0 });
try { ev = new MouseEvent(t, { clientX: x, clientY: y, bubbles: true, cancelable: true, button: 0 }); } catch (e2) {}
el.dispatchEvent(ev);
} catch (e3) {}
});
} catch (e) {}
}
function vid() { return document.querySelector('video'); }
function ckp() {
if (window.player) return window.player;
try {
var f = document.querySelector('iframe');
if (f && f.contentWindow && f.contentWindow.player) return f.contentWindow.player;
} catch (e) { }
return null;
}
function studyInfo() {
var vt = document.getElementById('viewTimeTxt');
if (!vt) return null;
var wat = parseInt(vt.textContent, 10);
if (isNaN(wat)) wat = -1;
var p = vt.closest('.g-study-prompt');
if (!p) return { req: -1, wat: wat };
var spans = p.querySelectorAll('span');
var req = -1;
for (var i = 0; i < spans.length; i++) {
if (spans[i] === vt) continue;
var n = parseInt(spans[i].textContent, 10);
if (!isNaN(n)) { req = n; break; }
}
if (req < 0) {
var hi = p.querySelector('input[type="hidden"]');
if (hi) {
var hv = parseInt(hi.value, 10);
if (!isNaN(hv)) req = hv;
}
}
return { req: req, wat: wat };
}
function resume() {
var v = vid();
if (!v || v.ended) return false;
if (!v.paused) return true;
var ck = ckp();
if (ck) {
try { if (typeof ck.videoPlay === 'function') { ck.videoPlay(); return true; } } catch (e) { }
try { if (typeof ck.play === 'function') { ck.play(); return true; } } catch (e) { }
}
try {
var r = v.play();
if (r && typeof r.catch === 'function') r.catch(function () { });
return true;
} catch (e) { }
return false;
}
function fmt(s) {
var m = Math.floor(s / 60), sec = Math.floor(s % 60);
return m + ':' + (sec < 10 ? '0' : '') + sec;
}
var _quizDone = false, _quizHash = '';
function checkQuiz() {
if (_paused) return;
var qd = document.getElementById('questionDiv');
var ly = document.querySelector('.mylayer-layer');
if (!ly || !qd) { _quizDone = false; _quizHash = ''; return; }
if (ly.style.display === 'none') return;
if (ly.offsetWidth === 0 && ly.style.width === '0px') return;
var h = qd.textContent.length + '|' + (qd.querySelector('.qs-type') || {}).textContent;
if (_quizDone && h === _quizHash) return;
var ans = extractAns(qd);
if (!ans || ans.length === 0) { log('答案提取失败,重试中', 'error'); return; }
_quizDone = true;
_quizHash = h;
log('答案: ' + ans.join(','), 'quiz');
selectAndSubmit(qd, ans);
}
function extractAns(qd) {
var sc = findScripts(qd);
if (sc.length === 0) { log('无script', 'error'); return null; }
for (var i = 0; i < sc.length; i++) {
var c = sc[i].textContent;
var m1 = c.match(/var\s+answerList;\s*if\s*\('([^']+)'\.includes\('/);
if (m1) { var r = m1[1]; if (r.indexOf(',') >= 0) { try { return JSON.parse(r); } catch (e) { } } return [r]; }
var m2 = c.match(/answerList\s*=\s*\[([^\]]+)\]/);
if (m2) { return m2[1].replace(/'/g, '').split(',').map(function (v) { return v.trim(); }); }
var m3 = c.match(/answerList\s*=\s*JSON\.parse\('([^']+)'\)/);
if (m3) { try { return JSON.parse(m3[1]); } catch (e) { } }
}
return null;
}
function findScripts(qd) {
var p = qd.parentElement;
if (p) { var s = p.querySelectorAll('script'); if (s.length > 0) return s; }
var g = qd.closest('.mylayer-layer');
if (g) return g.querySelectorAll('script');
var all = document.querySelectorAll('script');
var res = [];
for (var i = 0; i < all.length; i++) { if (all[i].textContent.indexOf('finishTest') >= 0) res.push(all[i]); }
return res;
}
function selectAndSubmit(qd, ans) {
var ins = qd.querySelectorAll('input[name="response"]');
ins.forEach(function (inp) {
inp.checked = false;
var lb = inp.closest('label');
if (lb) { var st = lb.querySelector('strong'); if (st) st.className = ''; }
});
ans.forEach(function (a) {
ins.forEach(function (inp) {
if (inp.value === a) {
inp.checked = true;
var lb = inp.closest('label');
if (lb) { var st = lb.querySelector('strong'); if (st) st.className = 'on'; }
var sp = lb ? lb.querySelector('span') : null;
log('选: ' + a + ' ' + (sp ? sp.textContent.trim() : ''), 'quiz');
}
});
});
setTimeout(function () { submit(qd); }, 500);
}
function submit(qd) {
if (typeof window.finishTest === 'function') {
try {
window.finishTest();
log('finishTest() OK', 'quiz');
setTimeout(function () {
var ly = document.querySelector('.mylayer-layer');
if (ly && ly.style.display !== 'none' && ly.offsetWidth > 0) { _quizDone = false; }
else { log('答题弹窗关闭', 'quiz'); setTimeout(resume, 1000); }
}, 2000);
return;
} catch (e) { log('finishTest err: ' + e.message, 'error'); }
}
var btn = qd.querySelector('.u-main-btn');
if (btn) {
btn.click();
setTimeout(function () {
var ly = document.querySelector('.mylayer-layer');
if (ly && ly.style.display !== 'none' && ly.offsetWidth > 0) { _quizDone = false; }
else { setTimeout(resume, 1000); }
}, 2000);
return;
}
_quizDone = false;
}
function checkCompletePopup() {
if (_paused) return;
var lys = document.querySelectorAll('.mylayer-layer');
for (var i = 0; i < lys.length; i++) {
var ly = lys[i];
if (ly.style.display === 'none' || ly.offsetWidth === 0) continue;
var ct = ly.querySelector('.mylayer-content');
if (!ct) continue;
var tx = ct.textContent || '';
if (tx.indexOf('已完成这个活动') >= 0 || tx.indexOf('已完成此活动') >= 0) {
log('"已完成活动"弹窗', 'warn');
var aid = curAid();
var nm = curName() || '';
var si = studyInfo();
if (aid) setStatus(aid, si ? si.wat : -1, si ? si.req : -1, true, nm);
var ob = ly.querySelector('.mylayer-btn.type1') || ly.querySelector('button.mylayer-btn');
if (ob) {
ob.click();
log('点击确定');
if (_examMode || _autoExamRunning) {
log('考核模式,不自动切换', 'exam');
} else {
setTimeout(function () { _promptDone = false; nextVideo(); }, 2000);
}
}
else { var cb = ly.querySelector('.mylayer-closeico'); if (cb) cb.click(); }
return;
}
}
}
var _promptDone = false;
var _completeTimer = null;
function checkStudyProgress() {
if (_paused) return;
if (_examMode || isExamPage()) return;
var si = studyInfo();
if (!si || si.req < 0 || si.wat < 0) return;
var aid = curAid();
var nm = curName() || '';
if (!aid) return;
setStatus(aid, si.wat, si.req, si.wat >= si.req, nm);
if (_promptDone) return;
if (isKnownDone(aid)) {
_promptDone = true;
log('已知完成: ' + nm + ' (' + si.wat + '>=' + si.req + ') 切下一节(等60秒)', 'vid');
if (_completeTimer) clearTimeout(_completeTimer);
_completeTimer = setTimeout(function () {
_promptDone = false;
nextVideo();
}, CFG.COMPLETE_WAIT);
return;
}
if (si.wat >= si.req) {
_promptDone = true;
setStatus(aid, si.wat, si.req, true, nm);
log('学习达标 ' + si.wat + '>=' + si.req + 'min 切下一节(等60秒)', 'vid');
if (_completeTimer) clearTimeout(_completeTimer);
_completeTimer = setTimeout(function () {
_promptDone = false;
nextVideo();
}, CFG.COMPLETE_WAIT);
}
}
function curAid() {
var m = location.pathname.match(/a_([a-f0-9]{32})/i);
if (m) return 'a_' + m[1];
var c = document.querySelector('a.section.z-crt');
if (c) { var dd = c.closest('dd[childsectionactivitieid]'); if (dd) return dd.getAttribute('childsectionactivitieid'); }
return null;
}
function curName() {
var c = document.querySelector('a.section.z-crt');
if (c) { var sp = c.querySelector('.txt'); if (sp) return sp.textContent.trim(); return c.textContent.trim(); }
var h = document.querySelector('.g-studyAct-box h3');
return h ? h.textContent.trim() : null;
}
function nameById(aid) {
var dd = document.querySelector('dd[childsectionactivitieid="' + aid + '"]');
if (dd) { var sp = dd.querySelector('.txt'); if (sp) return sp.textContent.trim(); var a = dd.querySelector('a.section'); if (a) return a.textContent.trim(); }
return null;
}
function allAids() {
var ids = [];
document.querySelectorAll('dd[childsectionactivitieid]').forEach(function (dd) {
var id = dd.getAttribute('childsectionactivitieid');
var a = dd.querySelector('a.section');
if (a && a.textContent.indexOf('考核') < 0) ids.push(id);
});
return ids;
}
function nextAid(cur) {
var ids = allAids();
var idx = ids.indexOf(cur);
return idx >= 0 && idx < ids.length - 1 ? ids[idx + 1] : null;
}
function findFirstIncomplete() {
var aids = allAids();
for (var i = 0; i < aids.length; i++) {
if (!isKnownDone(aids[i])) return aids[i];
}
return null;
}
var _switching = false;
function nextVideo() {
if (_switching) return false;
if (isExamPage() || _examMode) { _switching = false; log('考核页面,停止自动切换', 'exam'); return false; }
_switching = true;
_promptDone = false;
var btns = document.querySelectorAll('a.btn.next');
for (var i = 0; i < btns.length; i++) {
if (btns[i].classList.contains('disable') || btns[i].classList.contains('disabled')) continue;
if (btns[i].offsetWidth === 0) continue;
btns[i].click();
log('"下一个活动"按钮', 'vid');
schedResume();
return true;
}
var c = curAid(), n = nextAid(c);
if (n && CID && typeof studyCourse === 'function') {
studyCourse(CID, '', n);
log('studyCourse -> ' + n.substring(0, 12), 'vid');
schedResume();
return true;
}
_switching = false;
log('没有下一节了', 'warn');
return false;
}
function schedResume() {
[4000, 7000, 11000, 18000].forEach(function (d) {
setTimeout(function () {
if (d === 4000) {
var si = studyInfo();
var aid = curAid();
var nm = curName() || '';
if (si && si.req >= 0 && si.wat >= 0 && si.wat >= si.req) {
if (aid) setStatus(aid, si.wat, si.req, true, nm);
if (isKnownDone(aid)) {
log('新活动已完成,跳过', 'vid');
_promptDone = true;
setTimeout(function () {
_promptDone = false;
nextVideo();
}, CFG.COMPLETE_WAIT);
return;
}
}
}
var v = vid();
if (v && v.paused && !v.ended) {
resume();
if (d < 11000) log('恢复播放 ' + d + 'ms', 'vid');
}
if (d >= 11000) _switching = false;
}, d);
});
}
var _endDone = false;
function onEnd() {
if (_endDone) return;
if (_examMode || isExamPage()) return;
_endDone = true;
var v = vid();
if (!v) return;
var si = studyInfo();
if (si && si.req >= 0 && si.wat >= 0 && si.wat < si.req) {
log('视频播完但学习时间不够 ' + si.wat + '/' + si.req + ' 重新播放', 'warn');
_endDone = false;
setTimeout(function () {
v.currentTime = 0;
var ck = ckp();
if (ck && typeof ck.videoPlay === 'function') ck.videoPlay();
else if (ck && typeof ck.play === 'function') ck.play();
else v.play();
}, 3000);
return;
}
log('视频结束,学习达标', 'vid');
var aid = curAid();
var nm = curName() || '';
if (aid) setStatus(aid, si ? si.wat : -1, si ? si.req : -1, true, nm);
_promptDone = true;
setTimeout(function () {
_promptDone = false;
nextVideo();
_endDone = false;
}, CFG.COMPLETE_WAIT);
}
function isExamPage() {
var c = document.querySelector('a.section.z-crt');
if (c && c.textContent.indexOf('考核') >= 0) return true;
var aid = curAid();
if (aid === getExamAid()) return true;
var nm = curName() || '';
if (nm === '考核' || nm === '考试') return true;
return false;
}
function videoLoop() {
if (_paused) return;
if (_examMode || isExamPage()) return;
if (location.href.indexOf('/study/course/') < 0) return;
var v = vid();
if (!v) return;
refreshVideoUI();
if (v.paused && !v.ended) {
for (var i = 0; i < 3; i++) { if (!v.paused) break; resume(); }
}
if (v.ended || (v.duration > 0 && v.currentTime >= v.duration - 3)) onEnd();
}
var _examMode = false;
var _autoExamRunning = false;
var _autoExamIdx = 0;
var _autoExamQuestions = [];
var _examTimer = null;
var _examHash = '';
var _examSelected = [];
var _examMulti = false;
var _examDoc = null;
var _manualExam = false;
var _dqAnswerTimer = null;
function getApiKey() { return localStorage.getItem('_as_si_key') || ''; }
function setApiKey(k) { try { localStorage.setItem('_as_si_key', k); } catch (e) { } }
var SI_API_URL = 'https://api.siliconflow.cn/v1/chat/completions';
var SI_MODEL = 'deepseek-ai/DeepSeek-V4-Pro';
function getExamAid() {
var els = document.querySelectorAll('dd[childsectionactivitieid]');
for (var i = 0; i < els.length; i++) {
var a = els[i].querySelector('a.section');
if (a && a.textContent.indexOf('考核') >= 0) return els[i].getAttribute('childsectionactivitieid');
}
return null;
}
function getExamDoc() {
var iframes = document.querySelectorAll('iframe');
for (var i = 0; i < iframes.length; i++) {
try {
var doc = iframes[i].contentDocument || iframes[i].contentWindow.document;
if (doc && doc.body && doc.body.innerHTML.length > 50) {
if (doc.querySelector('.m-topic-item') || doc.querySelector('.g-topic-lst')) return doc;
}
} catch (e) { }
}
if (document.querySelector('.m-topic-item') || document.querySelector('.g-topic-lst')) return document;
return null;
}
function goToExam() {
var eid = getExamAid();
if (!eid) { log('未找到考核活动', 'error'); return; }
if (CID && typeof studyCourse === 'function') { studyCourse(CID, '', eid); log('跳转考核', 'warn'); }
}
function enterExamMode() {
if (_examMode) return;
_examMode = true;
_examHash = '';
_examSelected = [];
_manualExam = false;
var el = document.getElementById('_asExam');
if (el) el.classList.add('_show');
log('进入考核模式', 'warn');
}
function enterManualExamMode() {
_manualExam = true;
if (_examTimer) { clearInterval(_examTimer); _examTimer = null; }
_examTimer = setInterval(scanExamQuestion, 3000);
setTimeout(scanExamQuestion, 1000);
log('手动答题模式', 'exam');
updateExamStatus('手动答题 - 题目加载中...');
}
function exitExamMode() {
stopAutoExam();
_examMode = false;
if (_examTimer) { clearInterval(_examTimer); _examTimer = null; }
var el = document.getElementById('_asExam');
if (el) el.classList.remove('_show');
log('退出考核模式', 'warn');
}
function stopAutoExam() {
_autoExamRunning = false;
if (_dqAnswerTimer) { clearTimeout(_dqAnswerTimer); _dqAnswerTimer = null; }
if (_dqSafetyTimer) { clearTimeout(_dqSafetyTimer); _dqSafetyTimer = null; }
if (_examTimer) { clearInterval(_examTimer); _examTimer = null; }
log('停止自动答题', 'exam');
updateExamStatus('已停止');
}
function parseAllExamQuestions(doc) {
var questions = [];
var items = doc.querySelectorAll('.m-topic-item');
if (items.length === 0) {
var topicList = doc.getElementById('topicList');
if (topicList) items = topicList.querySelectorAll('li');
}
for (var i = 0; i < items.length; i++) {
var item = items[i];
var titleEl = item.querySelector('.title');
if (!titleEl) continue;
var typeEl = titleEl.querySelector('.qs-type');
var typeText = typeEl ? typeEl.textContent.trim() : '';
var qText = titleEl.textContent.replace(typeEl ? typeEl.textContent : '', '').replace(/^\d+[、.]\s*/, '').trim();
var isMulti = typeText.indexOf('多选') >= 0;
var isJudge = typeText.indexOf('是非') >= 0 || typeText.indexOf('判断') >= 0;
var options = [];
var inputs = item.querySelectorAll('input[type="radio"], input[type="checkbox"]');
for (var j = 0; j < inputs.length; j++) {
var label = inputs[j].closest('label');
var text = '';
if (label) {
var span = label.querySelector('span');
text = span ? span.textContent.trim() : label.textContent.trim();
}
options.push({
value: inputs[j].value,
text: text,
input: inputs[j]
});
}
if (options.length > 0) {
questions.push({
index: questions.length,
text: qText,
type: typeText,
multi: isMulti || isJudge,
judge: isJudge,
options: options,
item: item
});
}
}
return questions;
}
var _examRetryCount = 0;
var _examGoCount = 0;
var _dqSafetyTimer = null;
function startAutoExam() {
if (_autoExamRunning) {
log('自动答题已在运行', 'warn');
return;
}
if (!getApiKey()) {
log('请先在面板填写硅基流动 API Key!', 'error');
updateExamStatus('请填写 API Key');
return;
}
var doc = getExamDoc();
if (!doc) {
_examRetryCount++;
if (_examRetryCount > 10) {
log('考核页面加载失败,已重试10次,放弃', 'error');
_examRetryCount = 0;
_examGoCount = 0;
return;
}
log('等待考核题目加载(' + _examRetryCount + '/10)', 'exam');
if (_examGoCount < 1) {
_examGoCount = 1;
goToExam();
}
setTimeout(startAutoExam, 5000);
return;
}
_examRetryCount = 0;
_examGoCount = 0;
_autoExamQuestions = parseAllExamQuestions(doc);
if (_autoExamQuestions.length === 0) {
_examRetryCount++;
if (_examRetryCount > 10) {
log('未找到考核题目,已重试10次,放弃', 'error');
_examRetryCount = 0;
return;
}
log('考核题目解析中(' + _examRetryCount + '/10)', 'exam');
setTimeout(startAutoExam, 5000);
return;
}
_examRetryCount = 0;
_examGoCount = 0;
_autoExamRunning = true;
_autoExamIdx = 0;
_manualExam = false;
log('开始自动答题,共' + _autoExamQuestions.length + '题', 'exam');
updateExamStatus('硅基流动就绪');
updateExamProg(0, _autoExamQuestions.length);
setTimeout(processNextExamQ, 2000);
}
function callSiliconFlow(prompt, callback) {
log('调用硅基流动 API...', 'exam');
GM_xmlhttpRequest({
method: 'POST',
url: SI_API_URL,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + getApiKey()
},
data: JSON.stringify({
model: SI_MODEL,
messages: [
{ role: 'system', content: '你是一个考试答题助手。请只回答选项字母(如A、BC、ABD),不要任何解释。' },
{ role: 'user', content: prompt }
],
temperature: 0.1,
max_tokens: 50
}),
timeout: CFG.DQ_TIMEOUT,
onload: function (resp) {
try {
var data = JSON.parse(resp.responseText);
var answer = data.choices && data.choices[0] && data.choices[0].message ?
data.choices[0].message.content.trim() : '';
log('API返回: ' + answer, 'exam');
callback(answer);
} catch (e) {
log('解析API响应失败: ' + e.message, 'error');
callback('');
}
},
onerror: function () {
log('API请求失败', 'error');
callback('');
},
ontimeout: function () {
log('API超时', 'error');
callback('');
}
});
}
function processNextExamQ() {
if (!_autoExamRunning) return;
if (_dqSafetyTimer) { clearTimeout(_dqSafetyTimer); _dqSafetyTimer = null; }
if (_autoExamIdx >= _autoExamQuestions.length) {
log('全部 ' + _autoExamQuestions.length + ' 题已答完,提交中...', 'exam');
submitExamForm();
return;
}
var q = _autoExamQuestions[_autoExamIdx];
var num = _autoExamIdx + 1;
var total = _autoExamQuestions.length;
updateExamStatus('第' + num + '/' + total + '题: API调用中...');
updateExamProg(num - 1, total);
showExamQ(q);
var optTexts = [];
var optLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
for (var i = 0; i < q.options.length; i++) {
optTexts.push(optLetters[i] + '. ' + q.options[i].text);
}
var prompt = '[' + q.type + '] ' + q.text + '\n\n' + optTexts.join('\n');
var answered = false;
var doneOnce = function () {
if (answered) return;
answered = true;
if (_dqSafetyTimer) { clearTimeout(_dqSafetyTimer); _dqSafetyTimer = null; }
};
// 安全兜底:20秒后如果API还没回来,跳过此题
_dqSafetyTimer = setTimeout(function () {
if (!_autoExamRunning) return;
if (!answered) {
log('第' + num + '题 API 超时(安全兜底),跳过', 'error');
doneOnce();
_autoExamIdx++;
updateExamProg(_autoExamIdx, total);
setTimeout(processNextExamQ, 1000);
}
}, 20000);
callSiliconFlow(prompt, function (answer) {
if (!_autoExamRunning) return;
doneOnce();
var choices = parseAnswer(answer, q.options);
if (choices && choices.length > 0) {
fillExamQ(q, choices);
log('第' + num + '题答案: ' + choices.join(','), 'exam');
} else {
log('第' + num + '题解析失败: ' + answer + ',跳过', 'error');
}
_autoExamIdx++;
updateExamProg(_autoExamIdx, total);
setTimeout(processNextExamQ, 2000);
});
}
function fillExamQ(q, choices) {
for (var i = 0; i < q.options.length; i++) {
var opt = q.options[i];
var checked = choices.indexOf(opt.value) >= 0;
try { opt.input.checked = checked; } catch (e) { }
var label = opt.input.closest('label');
if (label) {
var strong = label.querySelector('strong');
if (strong) strong.className = checked ? 'on' : '';
}
}
}
function submitExamForm() {
var doc = getExamDoc();
if (!doc) { log('考核文档丢失', 'error'); return; }
try {
if (typeof window.finishTest === 'function') {
window.finishTest();
log('finishTest() 提交', 'exam');
_autoExamRunning = false;
updateExamStatus('已提交');
return;
}
} catch (e) { }
try {
if (doc.defaultView && doc.defaultView.finishTest) {
doc.defaultView.finishTest();
log('iframe finishTest() 提交', 'exam');
_autoExamRunning = false;
updateExamStatus('已提交');
return;
}
} catch (e) { }
var form = doc.getElementById('testForm');
if (form) {
var btn = form.querySelector('button[type="submit"]') ||
form.querySelector('.u-main-btn') ||
form.querySelector('input[type="submit"]') ||
form.querySelector('button');
if (btn) { btn.click(); log('点击提交按钮', 'exam'); }
else { try { form.submit(); log('提交表单', 'exam'); } catch (e) { } }
}
_autoExamRunning = false;
updateExamStatus('已提交');
}
function showExamQ(q) {
var qEl = document.getElementById('_asExamQ');
var optsEl = document.getElementById('_asExamOpts');
if (qEl) qEl.textContent = q.text.substring(0, 80);
if (optsEl) {
var html = '';
for (var i = 0; i < q.options.length; i++) {
html += '';
}
optsEl.innerHTML = html;
}
}
function updateExamStatus(msg) {
var el = document.getElementById('_asExamH2');
if (el) el.textContent = msg;
}
function updateExamProg(current, total) {
var fill = document.getElementById('_asExamProgFill');
if (fill && total > 0) {
fill.style.width = (current / total * 100) + '%';
}
}
function scanExamQuestion() {
if (!_examMode || _paused || !_manualExam) return;
var doc = getExamDoc();
if (!doc) return;
var items = doc.querySelectorAll('.m-topic-item');
if (items.length === 0) items = doc.querySelectorAll('#topicList li');
if (items.length === 0) { updateExamStatus('等待题目加载...'); return; }
var qs = parseAllExamQuestions(doc);
if (qs.length === 0) return;
var q = qs[0];
var h = q.text;
if (h === _examHash) return;
_examHash = h;
_examSelected = [];
_examMulti = q.multi;
_examDoc = doc;
showExamQ(q);
try { if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(q.text).catch(function () { }); } catch (e) { }
}
function init() {
if (window._asRun) return;
window._asRun = true;
window._asPaused = false;
log('v12.0 启动 | ' + (CID || '?'));
loadDB();
spoofVis();
makePanel();
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', startAll);
else startAll();
}
function startAll() {
log('启动定时器');
refreshProgUI();
setInterval(videoLoop, CFG.CHECK_MS);
setInterval(function () {
var x = 400 + Math.floor(Math.random() * 500);
var y = 200 + Math.floor(Math.random() * 400);
fakeMouse(x, y);
var v = vid();
if (v) { var r = v.getBoundingClientRect(); if (r.width > 0) fakeMouse(r.left + Math.random() * r.width, r.top + Math.random() * r.height); }
}, CFG.MOUSE_MS + Math.random() * 10000);
setInterval(function () {
var dy = Math.floor(Math.random() * 30) - 15;
window.scrollBy(0, dy);
setTimeout(function () { window.scrollBy(0, -dy); }, 3000);
}, CFG.SCROLL_MS + Math.random() * 15000);
setInterval(function () {
var areas = [
function () { return { x: 100 + Math.random() * 200, y: 300 + Math.random() * 200 }; },
function () { return { x: 500 + Math.random() * 300, y: 600 + Math.random() * 100 }; },
function () { return { x: 800 + Math.random() * 200, y: 100 + Math.random() * 200 }; }
];
var pos = areas[Math.floor(Math.random() * areas.length)]();
fakeClick(pos.x, pos.y);
}, CFG.CLICK_MS + Math.random() * 20000);
setInterval(refreshVideoUI, 3000);
setInterval(checkQuiz, CFG.QUIZ_MS);
setInterval(checkCompletePopup, 3000);
setInterval(checkStudyProgress, CFG.CHECK_MS);
setTimeout(function () {
if (_examMode || _autoExamRunning) {
log('考核模式活跃,跳过初始化导航', 'exam');
return;
}
var v = vid();
var si = studyInfo();
var aid = curAid();
var nm = curName() || '';
if (v && si && si.req >= 0 && si.wat >= 0) {
var done = si.wat >= si.req;
setStatus(aid, si.wat, si.req, done, nm);
if (done && isKnownDone(aid)) {
log('当前已标记完成: ' + nm + ' 切下一节(等60秒)', 'vid');
_promptDone = true;
setTimeout(function () {
_promptDone = false;
nextVideo();
}, CFG.COMPLETE_WAIT);
} else if (done) {
log('当前已完成: ' + nm + ' 切下一节(等60秒)', 'vid');
_promptDone = true;
setStatus(aid, si.wat, si.req, true, nm);
setTimeout(function () {
_promptDone = false;
nextVideo();
}, CFG.COMPLETE_WAIT);
} else {
log('当前未完成: ' + nm + ' (' + si.wat + '/' + si.req + 'min) 开始播放', 'vid');
resume();
}
} else if (!v && !si) {
if (isExamPage() || _examMode) {
log('考核页面,等待手动操作', 'exam');
return;
}
var firstAid = findFirstIncomplete();
if (firstAid && CID && typeof studyCourse === 'function') {
log('课程列表页,自动开始: ' + (nameById(firstAid) || firstAid.substring(0, 12)), 'vid');
studyCourse(CID, '', firstAid);
schedResume();
} else if (aid && CID && typeof studyCourse === 'function') {
log('课程列表页,点击第一节', 'vid');
studyCourse(CID, '', aid);
schedResume();
} else {
log('未找到活动ID,等待手动操作', 'warn');
}
} else {
resume();
}
}, CFG.INIT_MS);
var origSC = window.studyCourse;
if (origSC && typeof origSC === 'function') {
window.studyCourse = function (cid, p2, aid) {
log('切换: ' + aid, 'vid');
_switching = true;
_endDone = false;
_promptDone = false;
if (_completeTimer) { clearTimeout(_completeTimer); _completeTimer = null; }
if (_examMode && aid !== getExamAid()) exitExamMode();
if (aid === getExamAid()) enterExamMode();
var ret = origSC(cid, p2, aid);
schedResume();
return ret;
};
log('劫持 studyCourse()');
}
setInterval(function () {
if (_paused) return;
var v = vid(); if (!v || !v.duration) return;
var ci = curAid(), ids = allAids(), idx = ids.indexOf(ci);
log(fmt(v.currentTime) + '/' + fmt(v.duration) + ' | ' + (idx + 1) + '/' + ids.length + '节', 'vid');
}, 60000);
log('就绪');
}
init();
function parseAnswer(text, options) {
text = text.toUpperCase();
var letters = [];
var re = /\\b([A-E])\\b/g;
var m;
while ((m = re.exec(text)) !== null) {
letters.push(m[1]);
}
if (letters.length === 0) {
if (text.indexOf('正确') >= 0 && text.indexOf('错误') < 0) letters.push('A');
if (text.indexOf('错误') >= 0 && text.indexOf('正确') < 0) letters.push('B');
}
if (letters.length === 0) {
var shortMatch = text.match(/^([A-E]{1,5})$/);
if (shortMatch) letters = shortMatch[1].split('');
}
var choices = [];
var seen = {};
for (var i = 0; i < letters.length; i++) {
var l = letters[i];
if (seen[l]) continue;
seen[l] = true;
var idx = l.charCodeAt(0) - 65;
if (idx < options.length) {
choices.push('Choice' + idx);
}
}
return choices;
}
})();