// ==UserScript==
// @name 5.0华医网刷课脚本
// @namespace https://jiaobenmiao.com/
// @version 1.1
// @description 该油猴脚本用于 华医网 的辅助看课,脚本功能如下:自动静音播放,自动切换视频,屏蔽课堂问答,自动考试,原作者主页https://scriptcat.org/zh-CN/users/157973,在其代码的基础上修复而来
// @author 脚本喵
// @match *://*.91huayi.com/course_ware/course_ware_polyv.aspx?*
// @match *://*.91huayi.com/course_ware/course_ware_cc.aspx?*
// @match *://*.91huayi.com/pages/exam.aspx?*
// @match *://*.91huayi.com/pages/exam_result.aspx?*
// @match *://*.91huayi.com/*
// @grant none
// @icon https://jiaobenmiao.com/img/logo2.jpg
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// ===================== 苹果风格调试窗口 (仅修改UI) =====================
window.debugLog = function (msg) {
let box = document.getElementById('debug-box');
if (!box) return;
let time = new Date().toLocaleTimeString('zh-CN', { hour12: false });
box.value = `[${time}] ${msg}\n` + box.value;
};
function createDebugWindow() {
let debugUI = document.createElement("div");
// 宽度缩小至 320px,引入 macOS 磨砂玻璃质感
debugUI.style.cssText = `
position: fixed; top: 20px; left: 20px; z-index: 9999999;
width: 320px;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
color: #1d1d1f;
padding: 16px; border-radius: 22px; font-size:13px;
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", sans-serif;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12), 0 0 1px rgba(0,0,0,0.2);
border: 0.5px solid rgba(255, 255, 255, 0.4);
user-select: none;
`;
let currentMode = localStorage.getItem("华医mode") == "2" ? "视频+考试" : "单刷视频";
debugUI.innerHTML = `
运行日志
`;
document.body.appendChild(debugUI);
document.getElementById("close-debug").onclick = () => debugUI.remove();
let btn = document.getElementById("mode-btn");
btn.onclick = function () {
let now = localStorage.getItem("华医mode") == "2" ? "1" : "2";
localStorage.setItem("华医mode", now);
let txt = now == "2" ? "视频+考试" : "单刷视频";
this.innerText = `当前模式:${txt}`;
window.debugLog("✅ 已切换:" + txt);
};
// 苹果风格点击反馈
btn.onmousedown = () => btn.style.transform = "scale(0.97)";
btn.onmouseup = () => btn.style.transform = "scale(1)";
}
createDebugWindow();
// ===================== 核心变量 (完全保留) =====================
var submitTime = 6800;
var reTryTime = 3500;
var examTime = 7000;
var randomX = 5000;
var vSpeed = 1;
var autoSkip = false;
var keyPlayRate = "JJ_Playrate";
var keyTest = "JJ_Test";
var keyResult = "JJ_Result";
var keyThisTitle = "JJ_ThisTitle";
var keyTestAnswer = "JJ_TestAnswer";
var keyRightAnswer = "JJ_RightAnswer";
var keyAllAnswer = "JJ_AllAnswer";
var btstyleA = "font-size: 16px;font-weight: 300;text-decoration: none;text-align: center;line-height: 40px;height: 40px;padding: 0 40px;display: inline-block;appearance: none;cursor: pointer;border: none;box-sizing: border-box;transition-property: all;transition-duration: .3s;background-color: #4cb0f9;border-color: #4cb0f9;border-radius: 4px;margin: 5px;color: #FFF;";
var btstyleB = "font-size: 12px;font-weight: 300;text-decoration: none;text-align: center;line-height: 20px;height: 20px;padding: 0 5px;display: inline-block;appearance: none;cursor: pointer;border: none;box-sizing: border-box;transition-property: all;transition-duration: .3s;background-color: #4cb0f9;border-color: #4cb0f9;border-radius: 4px;margin: 5px;color: #FFF;";
var btstyleC = "font-size: 12px;font-weight: 300;text-decoration: none;text-align: center;line-height: 20px;height: 20px;padding: 0 5px;display: inline-block;appearance: none;cursor: pointer;border: none;box-sizing: border-box;transition-property: all;transition-duration: .3s;background-color: f15854;border-color: #f15854;border-radius: 4px;margin: 5px;color: #FFF;";
var urlInfos = window.location.href.split("/");
var urlTip = urlInfos[urlInfos.length - 1].split("?")[0];
var huayi = getHuayi();
var nspeed = 0;
var clock = null;
advis();
debugLog("🚀 脚本启动成功,版本:V1.1");
debugLog("✅ 当前页面已识别,准备执行任务");
document.querySelector("span[id='tixing']").innerHTML = "当前网址已适配 ✅";
// ===================== 路由判断 (完全保留) =====================
if (urlTip == "course_ware_polyv.aspx") {
document.querySelector("div[id='Div1']").style.top = "40px";
huayi.seeVideo(1);
} else if (urlTip == "course_ware_cc.aspx") {
document.querySelector("div[id='Div1']").style.top = "40px";
huayi.seeVideo(2);
} else if (urlTip == "exam.aspx") {
huayi.doTest();
} else if (urlTip == "course.aspx" || urlTip == "cme.aspx") {
huayi.courseList();
} else if (urlTip == "exam_result.aspx") {
huayi.doResult();
} else {
try {
document.querySelector("span[id='tixing']").innerHTML = "此页面非视频、考试或未适配
";
} catch (error) { };
};
function getHuayi() {
return {
courseList: function () {
addAnwserCopybtn();
DelAllAnwser();
},
seeVideo: function (e) {
var tr = localStorage.getItem(keyPlayRate);
var playRateNow = 1;
cleanKeyStorage();
asynckillsendQuestion();
killsendQuestion2();
killsendQuestion3();
addinfo();
window.onload = function () {
localStorage.setItem(keyThisTitle, JSON.stringify(window.document.title));
ratechg(playRateNow);
if (autoSkip == true) {
setTimeout(function () {
skipVideo();
}, (submitTime + Math.ceil(Math.random() * randomX)));
};
clock = setInterval(examherftest, 3000);
switch (e) {
case 1:
window.s2j_onPlayerInitOver()
{
player?.j2s_setVolume(0);
document.querySelector("video").defaultMuted = true;
setTimeout(function () {
try {
player.j2s_resumeVideo();
examherftest();
debugLog("▶️ 视频已自动播放,已静音");
} catch (error) { };
}, 8000);
};
break;
case 2:
window.on_CCH5player_ready()
{
cc_js_Player?.setVolume(0);
document.querySelector("video").defaultMuted = true;
setTimeout(function () {
try {
cc_js_Player.play();
examherftest();
debugLog("▶️ 视频已自动播放,已静音");
} catch (error) { };
}, 8000);
};
break;
};
};
},
// 你指定的点击逻辑 (完全保留)
doTest: function () {
var questions = JSON.parse(localStorage.getItem(keyTest)) || {};
var qRightAnswer = JSON.parse(localStorage.getItem(keyRightAnswer)) || {};
if (JSON.stringify(qRightAnswer) == "{}") {
qRightAnswer = LoadRightAnwser();
};
var qTestAnswer = {};
var index = 0;
while (true) {
var question = document.querySelectorAll("table[class='tablestyle']")[index];
if (question == null) break;
else {
var q = question.querySelector(".q_name").innerText.substring(2).replace(/\s*/g, "");
if (qRightAnswer.hasOwnProperty(q)) {
var rightSelection = findAnwser("tbody", index, qRightAnswer[q]);
rightSelection.click();
} else {
if (questions.hasOwnProperty(q)) {
questions[q] = getNextChoice(questions[q]);
} else {
questions[q] = "A";
};
var answer = getChoiceCode(questions[q]);
var element = document.querySelectorAll("tbody")[index].getElementsByTagName("label")[answer];
if (!element) {
console.log("找不到选项,选项更改为A index: " + index + " answer: " + answer);
questions[q] = "A";
answer = getChoiceCode("A");
element = document.querySelectorAll("tbody")[index].getElementsByTagName("label")[answer];
};
try {
var answerText = element.innerText.substring(3);
qTestAnswer[q] = answerText;
} catch (error) { console.log("答案文本获取失败A:" + error); };
element.click();
};
index = index + 1;
};
};
localStorage.setItem(keyTest, JSON.stringify(questions));
localStorage.setItem(keyTestAnswer, JSON.stringify(qTestAnswer));
setTimeout(function () {
document.querySelector("#btn_submit").click();
}, (submitTime + Math.ceil(Math.random() * randomX)));
function findAnwser(qakey, index, rightAnwserText) {
var answerslist = document.querySelectorAll(qakey)[index];
var arr = answerslist.getElementsByTagName("label");
for (var i = 0; i < arr.length; i++) {
if (arr[i].innerText.substring(3) == rightAnwserText) {
return arr[i];
};
};
};
function getChoiceCode(an) {
var charin = an || "A";
return charin.charCodeAt(0) - "A".charCodeAt(0);
};
function getNextChoice(an) {
var code = an.charCodeAt(0) + 1;
return String.fromCharCode(code);
};
},
doResult: function () {
var tipsEl = document.querySelector(".tips_text");
var res = tipsEl ? tipsEl.innerText : "";
var dds = document.querySelectorAll(".state_cour_lis");
localStorage.removeItem(keyResult);
if (res == "考试通过" || res == "考试通过!" || res == "完成项目学习可以申请学分了") {
saveRightAnwser();
SaveAllAnwser();
cleanKeyStorage();
setTimeout(function () {
let host = window.location.host;
let params = new URLSearchParams(window.location.search);
let cwid = params.get("cwid");
let target = `https://${host}/course_ware/course_ware_polyv.aspx?cwid=${cwid}&ff=0&ft=0`;
window.location.href = target;
}, 2000);
} else {
tipsEl.innerText = "本次未通过,正在尝试更换答案\r\n(此为正常现象,脚本几秒后刷新,请勿操作)";
var qWrong = {};
for (var i = 0; i < dds.length; ++i) {
if (!dds[i].querySelector("img").src.includes("bar_img")) {
qWrong[dds[i].querySelector("p").title.replace(/\s*/g, "")] = i;
};
};
if (qWrong != {}) {
localStorage.setItem(keyResult, JSON.stringify(qWrong));
saveRightAnwser();
setTimeout(function () {
var retryBtn = document.querySelector("input[type=button][value='重新考试']");
if (retryBtn) retryBtn.click();
}, (reTryTime + Math.ceil(Math.random() * randomX)) * 1);
};
};
},
};
};
// ===================== 辅助函数 (完全保留) =====================
function SaveAllAnwser() {
var qAllAnswer = JSON.parse(localStorage.getItem(keyAllAnswer)) || {};
var qRightAnswer = JSON.parse(localStorage.getItem(keyRightAnswer)) || {};
var qTitle = JSON.parse(localStorage.getItem(keyThisTitle)) || "没有记录到章节名称";
var qOldAnswer = qAllAnswer[qTitle] || {};
for (var q in qRightAnswer) {
qOldAnswer[q] = qRightAnswer[q];
};
qAllAnswer[qTitle] = qOldAnswer;
if (qAllAnswer != null) {
localStorage.setItem(keyAllAnswer, JSON.stringify(qAllAnswer));
};
};
function LoadRightAnwser() {
var qAllAnswer = JSON.parse(localStorage.getItem(keyAllAnswer)) || {};
var qTitle = JSON.parse(localStorage.getItem(keyThisTitle)) || "没有记录到章节名称";
if (qTitle == "没有记录到章节名称") return {};
return qAllAnswer[qTitle] || {};
};
function saveRightAnwser() {
var qRightAnswer = JSON.parse(localStorage.getItem(keyRightAnswer)) || {};
var qTestAnswer = JSON.parse(localStorage.getItem(keyTestAnswer)) || {};
var qWrongs = JSON.parse(localStorage.getItem(keyResult)) || {};
for (var q in qTestAnswer) {
if (!qWrongs.hasOwnProperty(q)) {
qRightAnswer[q] = qTestAnswer[q];
};
};
localStorage.removeItem(keyTestAnswer);
if (qRightAnswer != null) {
localStorage.setItem(keyRightAnswer, JSON.stringify(qRightAnswer));
};
};
function addAnwserCopybtn() {
let alink = document.createElement("a");
alink.innerHTML = '显示已记录答案';
alink.style = btstyleB;
alink.onclick = function (event) {
var qAllAnswer = JSON.parse(localStorage.getItem(keyAllAnswer)) || {};
var Aout = JSON.stringify(qAllAnswer, null, "\t")
if (document.getElementById("AnwserOut")) {
document.getElementById("AnwserOut").innerHTML = Aout;
} else {
let textout = document.createElement("textarea");
textout.id = "AnwserOut";
textout.innerHTML = Aout;
textout.rows = 20; textout.cols = 30;
document.getElementById("main_div").parentNode.append(textout);
};
};
document.getElementById("main_div").parentNode.append(alink);
};
function DelAllAnwser() {
let alink = document.createElement("a");
alink.innerHTML = '清除已记录答案';
alink.style = btstyleB;
alink.onclick = function (event) {
var r = confirm("确定清除历史答案?!");
if (r) localStorage.removeItem(keyAllAnswer);
};
document.getElementById("main_div").parentNode.append(alink);
};
function skipVideo() {
var oVideo = document.getElementsByTagName('video')[0];
if (oVideo) oVideo.currentTime = oVideo.duration - 1;
};
function clickexam() {
setTimeout(function () {
document.querySelector("#jrks").click();
}, (Math.ceil(Math.random() * randomX)));
};
function ratechg(ra) {
var videoObj = document.querySelector("video")
try {
clearInterval(nspeed);
nspeed = setInterval(() => {
videoObj.playbackRate = ra;
}, 1000);
localStorage.setItem(keyPlayRate, ra);
} catch (error) { };
};
function addinfo() {
debugLog("ℹ️ 视频页面初始化完成,运行正常");
};
function cleanKeyStorage() {
localStorage.removeItem(keyTest);
localStorage.removeItem(keyResult);
localStorage.removeItem(keyTestAnswer);
localStorage.removeItem(keyRightAnswer);
};
function examherftest() {
var hreftest = document.getElementById("jrks").attributes["disabled"];
var state = document.querySelectorAll("i[id='top_play']")[0].parentNode.nextElementSibling.nextElementSibling.nextElementSibling.innerText;
if (state == "已完成" || state == "待考试" || !hreftest) {
if (localStorage.getItem("华医mode") == "2" && state == "待考试") {
debugLog("📌 视频播放完成,自动进入考试");
try { clickexam(); } catch (error) { };
} else {
debugLog("📌 视频播放完成,寻找下一个视频");
const lis = document.querySelectorAll("li[class='lis-inside-content']");
const targetElements = document.querySelectorAll("i[id='top_play']");
const grandparentElement = targetElements[0].parentElement.parentElement;
var index = Array.from(lis).findIndex(li => li === grandparentElement);
if (index + 2 <= lis.length) {
index += 2;
document.querySelector("#top_body > div.video-container > div.page-container > div.page-content > ul > li:nth-child(" + index + ") > h2").click();
setTimeout(function () {
document.evaluate("//button[contains(., '知道了')]", document, null, XPathResult.ANY_TYPE).iterateNext().click();
}, 2000);
} else {
if ($('button:contains("未学习")').length > 0) {
$('button:contains("未学习")').siblings().eq(0).click();
} else if ($('button:contains("学习中")').length > 0) {
$('button:contains("学习中")').siblings().eq(0).click();
} else if ($('button:contains("待考试")').length > 0 && localStorage.getItem("华医mode") == "2") {
$('button:contains("待考试")').siblings().eq(0).click();
} else {
debugLog("✅ 全部课程学习完成!");
clearInterval(clock);
};
};
};
};
};
function sleep(timeout) { return new Promise((resolve) => { setTimeout(resolve, timeout); }); };
function asynckillsendQuestion() {
(async function () {
while (!window.player || !window.player.sendQuestion) { await sleep(20); };
player.sendQuestion = function () { };
})();
};
function killsendQuestion2() { if (typeof (isInteraction) != "undefined") isInteraction = "off"; };
function killsendQuestion3() {
setInterval(async function () {
try { if ($('.pv-ask-head').length > 0) $(".pv-ask-skip").click(); } catch (err) { };
try { if ($('.signBtn').length > 0) $(".signBtn").click(); } catch (err) { };
try { if ($("button[onclick='closeProcessbarTip()']").length > 0) { $("button[onclick='closeBangZhu()']").click(); $("button[onclick='closeProcessbarTip()']").click(); } } catch (err) { };
try { if ($("button[class='btn_sign']").length > 0) $("button[class='btn_sign']").click(); } catch (err) { };
try {
var state = document.querySelectorAll("i[id='top_play']")[0].parentNode.nextElementSibling.nextElementSibling.nextElementSibling.innerText;
if ($('video').prop('paused') == true && state != "已完成" && state != "待考试") {
$('video').get(0).play();
$('video').prop('muted') = true;
} else if (state == "已完成") {
document.querySelector("video").pause();
};
} catch (err) { };
}, 10000);
};
function advis() {
let div1 = document.createElement("div");
div1.innerHTML = ` `;
document.body.append(div1);
document.querySelector("span[id='clo']").onclick = function () { document.querySelector("div[id='Div1']").style.display = "none"; };
};
})();