// ==UserScript==
// @name 联大学堂函授 全自动刷课答题【播放1分钟自动填答案+自定义提交进度】
// @namespace http://tampermonkey.net/
// @version 2.7 视频播放满一分钟自动识别填写答案
// @description 1.15倍速、防验证、后台播放,视频累计播放60秒后自动填答案,达到设置进度才提交切换章节
// @match *://*.jxjypt.cn/*
// @require https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1.min.js
// @require https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js
// @grant GM_xmlhttpRequest
// @run-at document-end
// @license All Rights Reserved
// ==/UserScript==
(function () {
'use strict';
// 环境校验,禁止Node.js运行
if (typeof window === 'undefined' || typeof document === 'undefined') {
console.warn('该脚本仅支持浏览器Tampermonkey插件运行');
return;
}
console.log('✅ 联大优化版:播放满60秒自动填答案,达标进度再提交切课');
// 全局基础配置
const PLAYBACK_RATE = 1.15;
const JUMP_DELAY = 2000;
const AUTO_FILL_SECONDS = 60; // 播放满60秒自动填答案
let hasJumped = false;
let currentBaseSection = null;
// 达标提交进度 70/80/90/100
let targetProgress = 100;
let hasVideo = !!document.querySelector('video');
const hasExam = !!document.querySelector('.m-question');
// ====================== 1. 人机行为模拟 防无操作检测 ======================
function simulateHumanActivity() {
window.focus();
document.dispatchEvent(new MouseEvent('mousemove', {
clientX: 300 + Math.random() * 80,
clientY: 300 + Math.random() * 80,
bubbles: true
}));
document.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', bubbles: true }));
setTimeout(() => document.body.click(), 200);
}
setInterval(simulateHumanActivity, 15000);
// ====================== 2. 自动关闭弹窗/AI助教/验证框 ======================
function autoCloseVerify() {
const closeBtn = document.querySelector('.alipay-layer-close, .layui-layer-close, [class*="dialog"] button');
if (closeBtn) {
closeBtn.click();
console.log('自动关闭验证/AI弹窗');
return;
}
$('button:contains("确定"),button:contains("继续"),button:contains("我知道了")').click();
}
setInterval(autoCloseVerify, 800);
// ====================== 3. 监听课程点击,记录基准课时 ======================
document.addEventListener('click', (e) => {
const target = e.target.closest('dd');
if (target && target.textContent.includes('节') && target.querySelector('i')) {
currentBaseSection = target;
hasJumped = false;
console.log(`更新基准课时:${currentBaseSection.textContent.trim()}`);
}
}, true);
// ====================== 4. 后台保活:页面最小化持续播放 ======================
function keepAliveBackground() {
document.addEventListener('visibilitychange', () => {
const video = document.querySelector('video');
if (!video || !isRunning) return;
if (document.hidden) {
video.play().catch(() => {});
}
});
setInterval(() => {
if (!isRunning) return;
const video = document.querySelector('video');
if (!video) return;
video.muted = true;
if (video.paused) video.play().catch(() => {});
video.onpause = function () {
if (isRunning && document.hidden) this.play().catch(() => {});
};
}, 1200);
}
// ====================== 5. 视频统一处理:倍速+缓冲+静音 ======================
async function autoPlaySync() {
const video = document.querySelector('video');
if (!video) return;
if (video.readyState < 4) {
await new Promise(resolve => {
const check = () => video.readyState >= 4 ? resolve() : requestAnimationFrame(check);
check();
});
}
if (video.paused) try { await video.play(); } catch (e) {}
if (video.playbackRate !== PLAYBACK_RATE) {
video.playbackRate = PLAYBACK_RATE;
}
video.muted = true;
}
// ==============================================
// 功能1:视频刷课 【播放满60秒自动填答案,达标进度才提交】
// ==============================================
function initVideoModule() {
// OCR识别处理
async function recognizeImage(file) {
const { data } = await Tesseract.recognize(file, 'chi_sim+eng');
let text = data.text;
if (text.includes('如')) text += 'AB';
text = text.replace(/4/g, 'A')
.replace(/©/g, 'C')
.replace(/×/g, '')
.replace(/条/g, '释')
.replace(/可/g, '释')
.replace(/了/g, 'B')
.toUpperCase();
return text;
}
// 悬浮控制面板
function createPanel() {
let panel = document.createElement('div');
panel.id = 'autoStudyPanel';
panel.style.cssText = `
position:fixed;top:140px;right:20px;z-index:999999;
background:#fff;padding:12px;border-radius:10px;box-shadow:0 0 10px rgba(0,0,0,0.2);
width:240px;max-height:80vh;overflow-y:auto;box-sizing:border-box;
`;
panel.innerHTML = `
🎯 全自动连刷(播放1分钟自动填答案)
计时:00:00
总长:00:00
进度:0%
提交线:100%
状态:等待启动,播放满60秒自动填答案
OCR状态:未获取
`;
document.body.appendChild(panel);
// 切换提交进度阈值
$('#progressSelect').on('change', function () {
targetProgress = Number($(this).val());
$('#status').text(`已设置提交进度:${targetProgress}%,播放满60秒自动填答案`);
updateInfo();
});
}
let isRunning = false;
let timer = 0; // 视频累计播放秒数
let total = 0;
let interval = null;
let aiAlreadyCalled = false; // 标记是否已自动填过答案
function fmt(s) {
let m = Math.floor(s / 60);
let sec = Math.floor(s % 60);
return `${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}`;
}
function closePopups() {
try {
$("button:contains('确定'),button:contains('关闭'),.close,.layui-layer-close").click();
$(".layui-layer,.modal,.popup").hide();
} catch (e) {}
}
function loadDurationNow() {
let checkVideo = setInterval(() => {
let video = document.querySelector('video');
if (video && video.duration > 0) {
total = video.duration;
updateInfo();
clearInterval(checkVideo);
}
}, 100);
}
function updateInfo() {
let percent = total > 0 ? (timer / total) * 100 : 0;
$('#videoInfo').html(`计时:${fmt(timer)}
总长:${fmt(total)}
进度:${percent.toFixed(1)}%
提交线:${targetProgress}%`);
}
// 主循环:计时+满一分钟自动填答案,达标再提交
function loop() {
if (!isRunning || hasJumped) return;
closePopups();
autoPlaySync();
const video = document.querySelector('video');
if (!video) return;
if (!video.paused && !video.ended && video.readyState >= 4) {
timer++;
}
updateInfo();
// 新增:播放满60秒 自动填答案(仅执行一次)
if (timer >= AUTO_FILL_SECONDS && !aiAlreadyCalled) {
$('#status').text(`已播放满${AUTO_FILL_SECONDS}秒,自动识别填写答案`);
getAnswerOnce(true);
}
// 进度达标才提交跳转
let percent = total > 0 ? (timer / total) * 100 : 0;
if (percent >= targetProgress && aiAlreadyCalled) {
$('#status').text(`进度达${targetProgress}%,准备提交答案跳转`);
realSubmit();
}
}
// 精准跳转下一课,重置计时与填答案标记
function goNext() {
aiAlreadyCalled = false;
timer = 0; // 重置播放计时
$('#questionDisplay').text('');
$('#answerStatus').text('OCR状态:未获取');
const allSections = Array.from(document.querySelectorAll('dd'))
.filter(dd => dd.textContent.includes('节') && dd.querySelector('i'));
if (allSections.length === 0) return;
let currentIdx = -1;
if (currentBaseSection) {
currentIdx = allSections.findIndex(sec => sec === currentBaseSection);
}
if (currentIdx === -1) {
allSections.forEach((sec, idx) => {
const icon = sec.querySelector('i, img');
if (icon && (icon.src?.includes('green') || sec.style.color === 'green')) {
currentIdx = idx;
currentBaseSection = sec;
}
});
}
if (currentIdx === -1) currentIdx = 0;
const nextIdx = currentIdx + 1;
if (nextIdx >= allSections.length) {
$('#status').text('状态:已全部课程刷完');
return;
}
const nextSec = allSections[nextIdx];
console.log(`跳转下一节:${nextSec.textContent.trim()}`);
nextSec.click();
currentBaseSection = nextSec;
setTimeout(() => {
total = 0;
hasJumped = false;
loadDurationNow();
$('#status').text(`下一节加载,播放满${AUTO_FILL_SECONDS}秒自动填答案,${targetProgress}%提交`);
setTimeout(showQuestions, 1200);
autoPlaySync();
}, JUMP_DELAY);
}
function start() {
isRunning = true;
$('#status').text(`运行中:播放满${AUTO_FILL_SECONDS}秒自动填答案,${targetProgress}%进度提交切课`);
clearInterval(interval);
interval = setInterval(loop, 1000);
keepAliveBackground();
}
function stop() {
isRunning = false;
clearInterval(interval);
$('#status').text('状态:已暂停');
let video = document.querySelector('video');
if (video) video.pause();
}
function getExamQuestions() {
const result = [];
document.querySelectorAll('.m-question').forEach(el => {
const q = {};
q.title = el.querySelector('.sub-dotitle pre')?.innerText.trim() || '无题目';
q.options = {};
el.querySelectorAll('.m-question-option').forEach(opt => {
const k = opt.getAttribute('data-value');
const v = opt.innerText.trim().replace(/^[A-Z]\./, '').trim();
if (k && v && !v.includes('null')) q.options[k] = v;
});
result.push(q);
});
return result;
}
function showQuestions() {
const qs = getExamQuestions();
let txt = '';
if (!qs.length) txt = '未检测到题目';
else qs.forEach((q, i) => {
txt += `第${i+1}题:${q.title}\n`;
Object.entries(q.options).forEach(([k, v]) => txt += `${k}. ${v}\n`);
txt += `——————————\n`;
});
$('#questionDisplay').text(txt);
}
async function getImageAnswer() {
try {
$('.zkjx').click();
const img = document.querySelector('.solution img');
if (!img) {
$('#answerStatus').text('OCR:未找到答案图');
return null;
}
const response = await fetch(img.src);
const blob = await response.blob();
const text = await recognizeImage(blob);
let oldText = $('#questionDisplay').text();
$('#questionDisplay').text(oldText + `\n✅识别答案:${text}\n`);
const matchAll = text.match(/[A-D]/g);
if (matchAll && matchAll.length > 0) {
return [...new Set(matchAll)];
}
} catch (e) {
$('#answerStatus').text('OCR:识别失败');
}
return null;
}
// 提交逻辑(仅进度达标才执行)
function realSubmit() {
setTimeout(() => {
let submitBtn = document.getElementById('submitSelfBtn');
if (submitBtn) {
$('#status').text('✅ 答案已提交,跳转下一课');
submitBtn.click();
}
setTimeout(() => { hasJumped = true; goNext(); }, JUMP_DELAY);
}, 1200);
}
/**
* @param isAuto true=播放满60秒自动填,只勾选不校验提交进度;false=手动点击
*/
async function getAnswerOnce(isAuto = false) {
if (aiAlreadyCalled && isAuto) return;
aiAlreadyCalled = true;
$('#answerStatus').text('OCR状态:识别中...');
const ans = await getImageAnswer();
if (ans && Array.isArray(ans)) {
$('#answerStatus').text(`OCR状态:${ans.join("、")}`);
// 直接勾选答案
for (let key of ans) {
let opt = document.querySelector(`.m-question-option[data-value="${key}"]`);
if (opt) {
opt.dispatchEvent(new MouseEvent('mousedown', {bubbles: true}));
opt.dispatchEvent(new MouseEvent('mouseup', {bubbles: true}));
opt.click();
opt.classList.add('active');
}
}
} else {
$('#answerStatus').text('OCR:无有效答案');
}
// 手动点击才校验进度、允许提交
if (!isAuto) {
let percent = total > 0 ? (timer / total) * 100 : 0;
if (percent < targetProgress) {
$('#answerStatus').text(`当前${percent.toFixed(1)}%,需${targetProgress}%才可提交`);
return;
}
realSubmit();
}
}
$(function () {
createPanel();
loadDurationNow();
setTimeout(showQuestions, 800);
$('#startBtn').click(start);
$('#stopBtn').click(stop);
$('#showQBtn').click(showQuestions);
$('#getAnswerBtn').click(()=>getAnswerOnce(false));
});
}
// ==============================================
// 功能2:试卷全自动答题(无改动)
// ==============================================
function initExamModule() {
window.confirm = () => true;
window.alert = () => {};
window.prompt = () => null;
function createPanel() {
if (document.getElementById('autoStudyPanel')) return;
let panel = $('');
panel.css({
position: 'fixed', top: '100px', right: '20px', zIndex: '999999',
background: '#fff', padding: '12px', borderRadius: '10px', boxShadow: '0 0 12px rgba(0,0,0,0.25)',
width: '260px', maxHeight: '80vh', overflowY: 'auto', fontSize: '14px'
});
panel.html(`
🎯 联大学堂自动答题
状态:加载完成,就绪
`);
$('body').append(panel);
}
function closePopups() {
try {
$("button:contains('确定'),button:contains('关闭'),.close,.layui-layer-close,.modal-close").click();
$(".layui-layer,.modal,.popup").hide();
} catch (e) {}
}
function expandAllAnswers() {
$('.zkjx').click();
$('.solution').show();
}
function getAllAnswers() {
expandAllAnswers();
const result = [];
$('.m-question').each((i, el) => {
const q = {};
q.title = $(el).find('.sub-dotitle pre').text().trim() || $(el).find('.sub-dotitle').text().trim();
q.answer = $(el).find('.da-list:first .wenzi').text().trim();
q.element = el;
if ($(el).find('.sub-answer-double').length > 0) q.type = "多选题";
else if ($(el).find('dd[data-value]').length > 0) q.type = "单选题";
else if ($(el).find('textarea').length > 0) q.type = "简答题";
else q.type = "其他题型";
result.push(q);
});
return result;
}
function showAllAnswers() {
const list = getAllAnswers();
let txt = '';
list.forEach((q, i) => {
txt += `【第${i+1}题】(${q.type})\n答案:${q.answer || '无'}\n---\n`;
});
$('#answerDisplay').text(txt);
$('#status').text(`状态:已显示 ${list.length} 题完整答案`);
}
function autoAnswerOne(questionEl, answer) {
if (!answer || answer === '') return;
const $el = $(questionEl);
let ans = answer.trim();
if (ans === "对" || ans === "正确") ans = "A";
if (ans === "错" || ans === "错误") ans = "B";
for (let c of ans) {
if (c >= 'A' && c <= 'Z') {
const opt = $el.find(`dd[data-value="${c}"]`);
if (opt.length) opt.click().css({ background: '#e6f7ff', border: '1px solid #1890ff' });
const optText = c === 'A' ? "正确" : "错误";
const opt2 = $el.find(`dd[data-value="${optText}"]`);
if (opt2.length) opt.click().css({ background: '#e6f7ff', border: '1px solid #1890ff' });
}
}
const textarea = $el.find('textarea.e__textarea, textarea');
if (textarea.length) textarea.val(answer).trigger('input').trigger('change').css({ background: '#e6f7ff', border: '1px solid #1890ff' });
}
function autoAnswerAll() {
closePopups();
const list = getAllAnswers();
if (list.length === 0) {
$('#status').text('❌ 未找到题目,请确认页面加载完成');
return;
}
let count = 0;
list.forEach((q, i) => {
setTimeout(() => {
autoAnswerOne(q.element, q.answer);
count++;
$('#status').text(`状态:答题中 ${count}/${list.length} 题`);
}, i * 300);
});
setTimeout(() => $('#status').text(`✅ 全部答题完成!共 ${list.length} 题`), list.length * 300 + 600);
}
function submitPaper() {
closePopups();
setTimeout(() => {
const btn = $('#btn_submit')[0] || $("button:contains('交卷')")[0] || $("a:contains('交卷')")[0];
if (btn) {
btn.click();
$('#status').text('✅ 已触发交卷');
} else {
$('#status').text('❌ 未找到交卷按钮');
}
}, 1000);
}
$(function () {
createPanel();
$('#autoAllBtn').click(autoAnswerAll);
$('#showAnswerBtn').click(showAllAnswers);
$('#submitBtn').click(submitPaper);
$('#status').text('✅ 试卷答题加载成功,支持单选多选简答判断');
});
}
// 等待视频DOM加载完成
function waitForVideo() {
const check = setInterval(() => {
const video = document.querySelector('video');
if (video) {
clearInterval(check);
hasVideo = true;
initVideoModule();
}
}, 500);
}
window.addEventListener('load', () => {
if (hasExam) initExamModule();
else waitForVideo();
setTimeout(autoPlaySync, 1500);
});
})();