wsxy_Learn

网上学院函数库:自动报名、学习、考试等

当前为 2020-02-06 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/396002/770454/wsxy_Learn.js

  1. // ==UserScript==
  2. // @name wsxy_Learn
  3. // @namespace Vionlentmonkey
  4. // @version 0.10
  5. // @description 网上学院函数库:自动报名、学习、考试等
  6. // ==/UserScript==
  7.  
  8. // 自动报名高学分课程。2020 年初,高于 1 学分的有且仅有 20 门 3 学分课程。
  9. const autoSignupMaxCredit = async waitCourseInfo => {
  10. // 需要 iframe 提升才会执行
  11. if (window.top !== window.self) return;
  12. let courses = document.querySelectorAll('#requiredCourseTable .course');
  13. for (let w of waitCourseInfo) {
  14. // 学分高且未报名。
  15. // 取消报名的也有 apply_pk,但没有进度点数 jdpoint 。
  16. if (w.courseCredit > 1 && !w.jdpoint) {
  17. console.log(w.course_name);
  18. for (let c of courses) {
  19. let coursePk = Number(c.getElementsByClassName('coursePk')[0].textContent);
  20. // 不能作为判断依据。
  21. if (coursePk === w.course_pk) {
  22. c.click();
  23. const btn = document.getElementsByClassName('layui-layer-btn0');
  24. if (btn.length === 1) {
  25. btn[0].click();
  26. }
  27. }
  28. }
  29. }
  30. }
  31. };
  32.  
  33. // 自动报名高学时课程
  34. const autoSignupMaxTime = async waitCourseInfo => {
  35. // 需要 iframe 提升才会执行
  36. if (window.top !== window.self) return;
  37. // 存储所有未报名课程的课时和对应编号
  38. let timesMap = new Map();
  39. for (let w of waitCourseInfo) {
  40. // 报名后等于零,undefined 代表未报名
  41. if (w.jdpoint === undefined) {
  42. timesMap.set(w.courseTime, w.course_pk);
  43. }
  44. }
  45. let timesArray = [...timesMap.keys()];
  46. let longest = Math.max(...timesArray);
  47. console.log(`+${longest}h`);
  48. let maxTimeCourse_pk = timesMap.get(longest);
  49. let courses = document.querySelectorAll('#requiredCourseTable .course');
  50. for (let c of courses) {
  51. let coursePk = Number(c.getElementsByClassName('coursePk')[0].textContent);
  52. if (coursePk === maxTimeCourse_pk) {
  53. c.click();
  54. const btn = document.getElementsByClassName('layui-layer-btn0');
  55. if (btn.length === 1) {
  56. btn[0].click();
  57. }
  58. }
  59. }
  60. };
  61.  
  62. const autoOpenExam = async exams => {
  63. for await (let exam of exams) {
  64. const examURL = location.origin + '/sfxzwsxy/' + exam.getAttribute('onclick').split("'")[1];
  65. // 魔法打开的考卷确认交卷后不能自动关闭,只得如此暴力处理,1分钟后强行关闭。
  66. let autoExam = GM_openInTab(examURL, true);
  67. setTimeout(autoExam.close, 60000);
  68. }
  69. };
  70.  
  71. const autoOpenTrain = async waitCourseInfo => {
  72. let i = 0;
  73. // 全部未完成必修课程。为同时解决学时学分问题,只关注必修课。
  74. const courses = document.querySelectorAll('#requiredCourseTable .course');
  75. for await (let c of courses) {
  76. let applyPk = Number(c.getElementsByClassName('applyPk')[0].textContent);
  77. let jdjs = c.getElementsByClassName('jdjs')[0].textContent; // 完成进度定性
  78. // 未报名课程 applyPk === '',取消报名的课程却能直接获取 applyPk,可能不适合使用 for length++ 循环
  79. if (jdjs === '完成进度') {
  80. if (i < GM_config.get('batch')) {
  81. // 部分少见的新型播放器会弹出 confirm,避开为宜
  82. for (w of waitCourseInfo) {
  83. if (w.apply_pk === applyPk && w.player === 'old') {
  84. const trainURL =
  85. location.origin +
  86. '/sfxzwsxy/jypxks/modules/train/ware/course_ware_view.jsp?applyPk=' +
  87. applyPk +
  88. '&courseType=1';
  89. const openClose = GM_openInTab(trainURL, true);
  90. // 25分钟自动关闭
  91. setTimeout(openClose.close, 1500000);
  92. i++;
  93. }
  94. }
  95. } else {
  96. // 跳过的课程一样会计数,可能不准
  97. console.log(`已尝试批量打开${i}个课程`);
  98. return;
  99. }
  100. }
  101. }
  102. };
  103.  
  104. const autoLearn = async (exams, waitCourseInfo) => {
  105. if (window.top !== window.self) return;
  106. // 30 分钟刷新一次
  107. setInterval(() => {
  108. location.reload(true);
  109. }, 1800000);
  110. const total_hour = Number(localStorage.getItem('total_hour')); //规定需达到的总学时
  111. const required_hour = Number(localStorage.getItem('required_hour')); //规定需达到的必修学时
  112. const required_credit = Number(localStorage.getItem('required_credit')); //规定需达到的总学分
  113. const user_total_hour = Number(localStorage.getItem('user_total_hour')); //用户已获得的总学时
  114. const user_required_hour = Number(localStorage.getItem('user_required_hour')); //用户已获得的必修学时
  115. const user_required_credit = Number(localStorage.getItem('user_required_credit')); //用户已获得的总学分
  116.  
  117. console.log(`已获得:必修学时:${user_required_hour},学分:${user_required_credit}`);
  118. // 判断是否已完成。首次在新标签页打开本页显然是未完成,但刷新后可能进入已完成状态。
  119. if (
  120. user_total_hour >= total_hour &&
  121. user_required_hour >= required_hour &&
  122. user_required_credit >= required_credit
  123. ) {
  124. console.log(`本学年任务已经完成`);
  125. return;
  126. } else {
  127. // 初始化预期学时/学分为已得值
  128. let pendingCredit = user_required_credit;
  129. let pendingTime = user_total_hour;
  130. // 向预期学时/学分添加已报名课程数据
  131. for (w of waitCourseInfo) {
  132. // jdpoint 保证已报名,否则无法处理取消报名的问题
  133. if (w.player === 'old' && w.jdpoint >= 0) {
  134. pendingCredit += w.courseCredit;
  135. pendingTime += w.courseTime;
  136. }
  137. }
  138. if (user_required_credit < required_credit && exams.length > 0) {
  139. console.log('学分未满,有待考试课程');
  140. await autoOpenExam(exams);
  141. // 1分钟后考完关闭,2分钟后刷新
  142. setTimeout(() => {
  143. location.reload(true);
  144. }, 120000);
  145. } else if (pendingTime < total_hour) {
  146. console.log(
  147. `已报名:必修学时:${pendingTime.toFixed(1)},学分:${pendingCredit},继续报名。`
  148. );
  149. autoSignupMaxTime(waitCourseInfo);
  150. } else if (pendingTime >= total_hour && pendingCredit < required_credit) {
  151. // 因为全部学习必修课,出现本状况可能很小,暂不处理
  152. console.log(
  153. `已报名:必修学时:${pendingTime.toFixed(1)},学分:${pendingCredit},有待处理。`
  154. );
  155. } else if (pendingTime >= total_hour && pendingCredit >= required_credit) {
  156. console.log(
  157. `已报名:必修学时:${pendingTime.toFixed(1)},学分:${pendingCredit},已达预期。`
  158. );
  159. if (user_required_hour < total_hour) {
  160. console.log('学时未满,自动打开已报名课程,将定时关闭。');
  161. autoOpenTrain(waitCourseInfo);
  162. }
  163. }
  164. }
  165. };

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址