// ==UserScript==
// @name 天津继续医学教育培训网 - 全自动极速学习助手 (2026天津市卫生培训)秒刷
// @version 5.2.0
// @description 天津继续医学教育培训网,全自动极速学习助手 (2026天津市卫生培训),我的课表中有多少学多少,秒刷。
// @author Assistant & Gemini
// @license MIT
// @match *://tjs.cmechina.net/*
// @run-at document-end
// @grant unsafeWindow
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_openInTab
// ==/UserScript==
(function () {
'use strict';
// ------------------- 全局配置与状态通信 -------------------
const STORAGE_RUN_STATUS = 'cme_auto_running_status_v5';
const STORAGE_LAST_FINISHED = 'cme_last_finished_timestamp';
const ACTION_DELAY = 2500; // 统一延迟时间:2.5秒
const MAIN_LIST_URL = 'https://tjs.cmechina.net/sip/r/814?_item=814'; // 目标列表地址
function getAutoStatus() { return GM_getValue(STORAGE_RUN_STATUS, false); }
function setAutoStatus(status) { GM_setValue(STORAGE_RUN_STATUS, status); }
function notifyCourseFinished() {
GM_setValue(STORAGE_LAST_FINISHED, Date.now());
}
// 强行返回主列表页 (关页失败则直接重定向)
function returnToMainList() {
console.log('[全自动学习助手] 触发返回主列表流程...');
notifyCourseFinished();
// 1. 优先尝试关闭窗口
try { window.close(); } catch (e) {}
// 2. 如果窗口未被浏览器关闭,启动顶级强跳
setTimeout(() => {
console.log('[全自动学习助手] 窗口未关闭,强制跳转至:', MAIN_LIST_URL);
try {
if (window.top) window.top.location.href = MAIN_LIST_URL;
else window.location.href = MAIN_LIST_URL;
} catch (e) {
window.location.href = MAIN_LIST_URL;
}
}, 500);
}
// 全局弹窗拦截
const originalAlert = unsafeWindow.alert;
unsafeWindow.alert = function (msg) {
console.log('[脚本拦截 Alert]:', msg);
if (msg && (
msg.includes('播放完成') || msg.includes('学完') ||
msg.includes('分数') || msg.includes('结果:') ||
msg.includes('通过') || msg.includes('顺利完成') ||
msg.includes('保存成功') || msg.includes('提交成功') ||
msg.includes('请重新考试')
)) {
return;
}
originalAlert(msg);
};
// UI 悬浮面板 (仅在顶层窗口显示)
function createUI(statusText) {
if (window.self !== window.top) return;
let panel = document.getElementById('auto-study-panel');
if (!panel) {
panel = document.createElement('div');
panel.id = 'auto-study-panel';
panel.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 999999;
background: #ffffff; border: 2px solid #1890ff; border-radius: 8px;
padding: 12px 16px; box-shadow: 0 4px 12px rgba(0,0,0,0.15);
font-size: 13px; color: #333; min-width: 240px; font-family: sans-serif;
`;
(document.body || document.documentElement).appendChild(panel);
}
const isRunning = getAutoStatus();
panel.innerHTML = `
⚡ 支持代刷代学👉 微信 wkds995
${statusText}
`;
document.getElementById('btn-toggle').onclick = function () {
const nextStatus = !getAutoStatus();
setAutoStatus(nextStatus);
location.reload();
};
}
const currentUrl = location.href;
// =========================================================================
// 步骤 1:主框架页面 (sip/r/814) -> 自动进入实际列表页
// =========================================================================
if (currentUrl.includes('/sip/r/814')) {
setTimeout(() => {
if (!getAutoStatus()) {
createUI('⏸️ 主框架就绪,点击开始运行');
return;
}
createUI('🔍 检测内部实际列表页...');
const iframe = document.querySelector('iframe');
if (iframe && iframe.src && iframe.src.includes('portalClassSchedule')) {
window.location.href = iframe.src;
} else {
const realListLink = Array.from(document.querySelectorAll('a')).find(a => a.href.includes('portalClassSchedule'));
if (realListLink) window.location.href = realListLink.href;
}
}, 1500);
return;
}
// =========================================================================
// 步骤 2:实际列表页 (portalClassSchedule_toCwarePage.do)
// =========================================================================
const isListPage = currentUrl.includes('portalClassSchedule') || currentUrl.includes('studentProjectList');
if (isListPage) {
let initialFinishTime = GM_getValue(STORAGE_LAST_FINISHED, 0);
setInterval(() => {
if (!getAutoStatus()) return;
const latestFinishTime = GM_getValue(STORAGE_LAST_FINISHED, 0);
if (latestFinishTime > initialFinishTime) {
createUI('🎉 子课程已完成,刷新列表页中...');
setTimeout(() => location.reload(), 1000);
}
}, 1500);
function getPendingCourses() {
const pendingLinks = [];
const allLinks = document.querySelectorAll('a[onclick*="queryCardByLoginUser"]');
allLinks.forEach(link => {
const onclickAttr = link.getAttribute('onclick') || '';
if (onclickAttr.includes('未学习') || onclickAttr.includes('学习中')) {
const isDuplicate = pendingLinks.some(item => item.getAttribute('onclick') === onclickAttr);
if (!isDuplicate) pendingLinks.push(link);
}
});
return pendingLinks;
}
function openCourseInNewTab(targetCourse) {
const onclickStr = targetCourse.getAttribute('onclick') || '';
const windowOpenHook = window.open;
window.open = function (url) {
GM_openInTab(url, { active: true });
return null;
};
try { targetCourse.click(); } catch (e) {
if (onclickStr) eval(`unsafeWindow.${onclickStr}`);
}
setTimeout(() => { window.open = windowOpenHook; }, 1000);
}
setTimeout(() => {
createUI(getAutoStatus() ? '🟢 列表页监控中...' : '⏸️ 等待开启');
if (!getAutoStatus()) return;
const pendingList = getPendingCourses();
if (pendingList.length > 0) {
createUI(`🚀 发现 ${pendingList.length} 门待学课程,2.5 秒后在新窗口打开...`);
setTimeout(() => {
if (getAutoStatus()) openCourseInNewTab(pendingList[0]);
}, ACTION_DELAY);
} else {
const nextPageBtn = Array.from(document.querySelectorAll('a')).find(a => a.innerText.trim().includes('下一页'));
if (nextPageBtn) {
createUI('⏩ 本页课程已全部完成,2.5 秒后翻页...');
setTimeout(() => { if (getAutoStatus()) nextPageBtn.click(); }, ACTION_DELAY);
} else {
createUI('🎉 所有课程均已全部完成!');
setAutoStatus(false);
}
}
}, 1200);
return;
}
// =========================================================================
// 步骤 3:课程/视频学习页 (zyyPxptStudy_studyCware.do)
// =========================================================================
const isExamPage = currentUrl.includes('afterExam') || document.getElementById('addExam1') !== null;
const isVideoPage = !isExamPage && (currentUrl.includes('studyCware') || document.querySelector('video') !== null);
if (isVideoPage) {
function getPlayer() { return unsafeWindow.player || unsafeWindow.cc_js_Player || null; }
function triggerExam() {
const examBtn = document.getElementById('examAfter') || document.getElementById('jinruks');
if (examBtn && !examBtn.disabled) {
examBtn.removeAttribute('disabled');
if (examBtn.getAttribute('onclick')) {
try { eval(`unsafeWindow.${examBtn.getAttribute('onclick')}`); return true; } catch (e) {}
}
try { examBtn.click(); return true; } catch (e) {}
}
if (typeof unsafeWindow.jinruks === 'function') {
try {
const logId = (document.getElementById('logId') || {}).value;
const cid = (document.getElementById('cid') || {}).value;
if (logId && cid) { unsafeWindow.jinruks(logId, cid); return true; }
} catch (e) {}
}
return false;
}
function playThenSkip() {
let attempts = 0;
const checkTimer = setInterval(() => {
attempts++;
const player = getPlayer();
const videoEl = document.querySelector('video');
let duration = 0;
if (player && typeof player.getDuration === 'function') {
duration = player.getDuration();
} else if (videoEl && videoEl.duration) {
duration = videoEl.duration;
}
if (duration > 3) {
clearInterval(checkTimer);
createUI(`▶️ 检测到视频(时长 ${Math.floor(duration)}s),已启动播放...`);
try {
if (player && typeof player.play === 'function') player.play();
if (videoEl) { videoEl.muted = true; videoEl.play(); }
} catch (e) {}
// 严格等待 2.5 秒后跳转
setTimeout(() => {
if (!getAutoStatus()) return;
const targetTime = Math.max(0, duration - 3);
createUI(`⚡ 已播放 2.5 秒,正在跳至结尾 (${Math.floor(targetTime)}s)...`);
if (player) {
try {
if (typeof player.setVolume === 'function') player.setVolume(0);
if (typeof player.jumpToTime === 'function') player.jumpToTime(targetTime);
else if (typeof player.seek === 'function') player.seek(targetTime);
} catch (e) {}
} else if (videoEl) {
try {
videoEl.currentTime = targetTime;
videoEl.play();
} catch (e) {}
}
// 监控视频结束并触发测验
const finishMonitor = setInterval(() => {
let isEnded = false;
if (player && typeof player.getPosition === 'function') {
try { if (player.getPosition() >= duration - 1) isEnded = true; } catch (e) {}
} else if (videoEl) {
if (videoEl.ended || videoEl.currentTime >= duration - 1) isEnded = true;
}
if (isEnded) {
clearInterval(finishMonitor);
createUI('📝 视频播放完成,2.5 秒后进入课后测验...');
setTimeout(() => {
if (!getAutoStatus()) return;
const hasExam = triggerExam();
if (!hasExam) {
createUI('✅ 该课件无测验,2.5 秒后强跳回到 sip/r/814...');
setTimeout(() => returnToMainList(), ACTION_DELAY);
}
}, ACTION_DELAY);
}
}, 1000);
}, ACTION_DELAY);
}
if (attempts > 15) {
clearInterval(checkTimer);
createUI('⚠️ 未检测到视频或视频已播放完,尝试进入测验或返回...');
const hasExam = triggerExam();
if (!hasExam) {
setTimeout(() => returnToMainList(), ACTION_DELAY);
}
}
}, 1000);
}
setTimeout(() => {
createUI(getAutoStatus() ? '🟢 检测页面状态中...' : '⏸️ 等待开启');
if (getAutoStatus()) playThenSkip();
}, 1200);
return;
}
// =========================================================================
// 步骤 4:考试/答题页 (zyyPxptStudy_afterExam.do) - 严格规则重构
// =========================================================================
if (isExamPage) {
function autoAnswerAndClose() {
if (!getAutoStatus()) return;
// 获取页面中所有带有 value="1" 属性的元素 (input/option 等)
const value1Elements = Array.from(document.querySelectorAll('input, [value="1"]'))
.filter(el => el.getAttribute('value') === '1' || el.value === '1');
// 核心判定:没有 value="1" 这个标签/属性 -> 代表课程已完成!
if (value1Elements.length === 0) {
createUI('🎉 测验页未检测到 value="1" 标签,判定课程已完成!2.5秒后跳转 sip/r/814...');
setTimeout(() => {
if (getAutoStatus()) returnToMainList();
}, ACTION_DELAY);
return;
}
// 存在 value="1" 标签 -> 属于未做测验状态,自动勾选并提交
createUI(`🎯 检测到 ${value1Elements.length} 个正确答案标记 (value="1"),正在自动填涂...`);
value1Elements.forEach(input => {
if (input.tagName === 'INPUT') {
if (!input.checked) {
try { input.click(); } catch (e) {}
input.checked = true;
}
}
});
createUI('✅ 正确答案填涂完成,2.5 秒后提交试卷...');
// 提交试卷
setTimeout(() => {
if (!getAutoStatus()) return;
const submitBtn = document.getElementById('addExam1');
if (typeof unsafeWindow.addexam === 'function') {
try { unsafeWindow.addexam(); } catch (e) { if (submitBtn) submitBtn.click(); }
} else if (submitBtn) {
submitBtn.click();
}
// 提交后倒计时跳转回到 sip/r/814
setTimeout(() => {
if (getAutoStatus()) {
createUI('🚀 试卷提交成功,2.5 秒后跳转回到 sip/r/814...');
setTimeout(() => returnToMainList(), ACTION_DELAY);
}
}, ACTION_DELAY);
}, ACTION_DELAY);
}
setTimeout(() => {
createUI(getAutoStatus() ? '📝 测验助手就绪,检测 value="1" 标记中...' : '⏸️ 等待开启');
if (getAutoStatus()) autoAnswerAndClose();
}, 1200);
}
})();