网上学院函数库:自动报名、听课、考试等
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/396002/770249/wsxy_Learn.js
// ==UserScript==
// @name wsxy_Learn
// @namespace Vionlentmonkey
// @version 0.5.4
// @description 网上学院函数库:自动报名、听课、考试等
// ==/UserScript==
// 自动报名高学分课程。2020年初,高于1学分的有且仅有20门3学分课程。
const autoSignupMaxCredit = async () => {
// 需要 iframe 提升才会执行
if (window.top === window.self) {
let courses = document.querySelectorAll('#requiredCourseTable .course');
for await (let c of courses) {
let coursePk = c.getElementsByClassName('coursePk')[0].textContent;
let title = c.getElementsByClassName('title')[0].getAttribute('title');
let jdjs = c.getElementsByClassName('jdjs')[0].textContent; // 进度
let csInfo = await getCourseInfo(coursePk);
let csCredit = csInfo.courseCredit;
if (jdjs === '未报名') {
// 自动报名高学分课程
if (csCredit > 1) {
console.log(`${csCredit}学分:${title}`);
c.click();
console.log('Click:' + title);
const info = document.getElementsByClassName('layui-layer-btn0');
if (info.length === 1) {
document.getElementsByClassName('layui-layer-btn0')[0].click();
console.log('报名:' + title);
}
}
}
}
}
};
// 自动报名高学时课程
const autoSignupMaxTime = async () => {
// 需要 iframe 提升才会执行
if (window.top === window.self) {
// 数组存储所有未报名课程故的课时数据
let timesArray = [];
// 获取所有未报名课程的子节点。若直接使用所有必修课程,可能出现课程数字相同而对已报名课程二次点击。
let unCoursesJdpoint = document.querySelectorAll(
'#requiredCourseTable .course > .jdpoint[style]'
);
for await (let u of unCoursesJdpoint) {
// 由子节点获取父节点从而获取课程编号
let coursePk = u.parentNode.getElementsByClassName('coursePk')[0].textContent;
let csInfo = await getCourseInfo(coursePk);
let csTime = csInfo.courseTime;
timesArray.push(csTime);
}
let longest = Math.max(...timesArray);
console.log(longest);
let indexMax = timesArray.indexOf(longest);
// 出现过该错误 indexMax === -Infinity 导致:
// TypeError: unCoursesJdpoint[timesArray.indexOf(...)] is undefined
if (unCoursesJdpoint[indexMax]) {
unCoursesJdpoint[indexMax].parentNode.click();
} else {
location.reload(true);
}
const notice = document.getElementsByClassName('layui-layer-btn0');
if (notice.length === 1) {
document.getElementsByClassName('layui-layer-btn0')[0].click();
}
}
};
const autoOpenExam = async exams => {
for await (let exam of exams) {
const examURL = location.origin + '/sfxzwsxy/' + exam.getAttribute('onclick').split("'")[1];
// 魔法打开的考卷确认交卷后不能自动关闭,只得如此暴力处理,1分钟后强行关闭。
let autoExam = GM_openInTab(examURL, true);
setTimeout(autoExam.close, 60000);
}
};
const autoOpenTrain = async (isNewPlayer, applyPk) => {
if (isNewPlayer) {
console.log(`跳过 applyPk: ${applyPk}`);
} else {
const trainURL =
location.origin +
'/sfxzwsxy/jypxks/modules/train/ware/course_ware_view.jsp?applyPk=' +
applyPk +
'&courseType=1';
const openClose = GM_openInTab(trainURL, true);
// 25分钟自动关闭
setTimeout(openClose.close, 1500000);
}
};
const autoLearn = async exams => {
if (window.top === window.self) {
// 30 分钟刷新一次
setInterval(() => {
location.reload(true);
}, 1800000);
const total_hour = Number(localStorage.getItem('total_hour')); //规定需达到的总学时
const required_hour = Number(localStorage.getItem('required_hour')); //规定需达到的必修学时
const required_credit = Number(localStorage.getItem('required_credit')); //规定需达到的总学分
const user_total_hour = Number(localStorage.getItem('user_total_hour')); //用户已获得的总学时
const user_required_hour = Number(localStorage.getItem('user_required_hour')); //用户已获得的必修学时
const user_required_credit = Number(localStorage.getItem('user_required_credit')); //用户已获得的总学分
// 全部未完成必修课程。为同时解决学时学分问题,只关注必修课。
const courses = document.querySelectorAll('#requiredCourseTable .course');
// 初始化预期学时/学分为已得值
let pendingCredit = user_required_credit;
let pendingTime = user_total_hour;
// 向预期学时/学分添加已报名课程数据
for await (let c of courses) {
let coursePk = c.getElementsByClassName('coursePk')[0].textContent;
let applyPk = c.getElementsByClassName('applyPk')[0].textContent;
let jdjs = c.getElementsByClassName('jdjs')[0].textContent; // 完成进度定性
if (jdjs === '完成进度') {
let csInfo = await getCourseInfo(coursePk);
let csCredit = csInfo.courseCredit;
let csTime = csInfo.courseTime;
skipNewVideoPlayerType(applyPk, (isNewPlayer, applyPk) => {
if (isNewPlayer) {
console.log(`跳过 applyPk: ${applyPk}`);
} else {
pendingCredit += csCredit;
pendingTime += csTime;
}
});
}
}
console.log(`已获得:必修学时:${user_required_hour},学分:${user_required_credit}`);
// 判断是否已完成。首次在新标签页打开本页显然是未完成,但刷新后可能进入已完成状态。
if (
user_total_hour >= total_hour &&
user_required_hour >= required_hour &&
user_required_credit >= required_credit
) {
console.log(`本学年任务已经完成`);
return;
} else {
if (user_required_credit < required_credit && exams.length > 0) {
console.log('学分未满,有待考试课程');
await autoOpenExam(exams);
// 1分钟后考完关闭,2分钟后刷新
setTimeout(() => {
location.reload(true);
}, 120000);
} else if (pendingTime < total_hour) {
console.log(
`已报名:必修学时:${pendingTime.toFixed(1)},学分:${pendingCredit},继续报名。`
);
autoSignupMaxTime();
} else if (pendingTime >= total_hour && pendingCredit < required_credit) {
// 因为全部学习必修课,出现本状况可能很小,暂不处理
console.log(
`已报名:必修学时:${pendingTime.toFixed(1)},学分:${pendingCredit},有待处理。`
);
} else if (pendingTime >= total_hour && pendingCredit >= required_credit) {
console.log(
`已报名:必修学时:${pendingTime.toFixed(1)},学分:${pendingCredit},已达预期。`
);
if (user_required_hour < total_hour) {
console.log('学时未满,自动打开已报名课程,将定时关闭。');
let i = 0;
for await (let c of courses) {
let applyPk = c.getElementsByClassName('applyPk')[0].textContent;
let jdjs = c.getElementsByClassName('jdjs')[0].textContent; // 完成进度定性
// 未报名课程 applyPk === '',取消报名的课程却能直接获取 applyPk,可能不适合使用 for length++ 循环
if (jdjs === '完成进度') {
if (i < GM_config.get('batch')) {
// 部分少见的新型播放器会弹出 confirm,避开为宜
skipNewVideoPlayerType(applyPk, autoOpenTrain);
i++;
} else {
// 跳过的课程一样会计数,可能不准
console.log(`已尝试批量打开${i}个课程`);
return;
}
}
}
}
}
}
}
};