🧰蓝墨云工具箱 Mosoteach Toolkit

让蓝墨云更加强大、易用!Make Mosoteach more powerful & user-friendly !

  1. // ==UserScript==
  2. // @name 🧰蓝墨云工具箱 Mosoteach Toolkit
  3. // @namespace https://blog.younnt.one
  4. // @version 1.4.6
  5. // @license MIT
  6. // @description 让蓝墨云更加强大、易用!Make Mosoteach more powerful & user-friendly !
  7. // @author Younntone
  8. // @match https://www.mosoteach.cn/web/index.php?c=interaction_quiz&m=person_quiz_result&clazz_course_id=*&id=*&order_item=group&user_id=*
  9. // @match https://www.mosoteach.cn/web/index.php?c=interaction_quiz&m=person_quiz_result&clazz_course_id=*&id=*&order_item=group
  10. // @match https://www.mosoteach.cn/web/index.php?c=interaction_quiz&m=reply&clazz_course_id=*&id=*&order_item=group
  11. // @match https://www.mosoteach.cn/web/index.php?c=*&m=index&clazz_course_id=*
  12. // @match https://www.mosoteach.cn/web/index.php?c=res&m=index&clazz_course_id=*
  13. // @grant none
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. 'use strict';
  18.  
  19. // 获取 当前页面
  20. const a = $('<a>', { href: window.location.search });
  21.  
  22. const c = a.prop('search').split('?c=')[1].split('&')[0];
  23.  
  24. const m = a.prop('search').split('&m=')[1].split('&')[0];
  25.  
  26. if (m == 'index') {
  27. let classes = $('.cc-name')[0].children[0].innerText;
  28. $('.cc-name')[0].children[0].innerText = $(
  29. '.cc-name'
  30. )[0].children[2].innerText;
  31. $('.cc-name')[0].children[2].innerText = classes;
  32. }
  33.  
  34. // 获取 课程 id
  35. let clazzCourseId = a
  36. .prop('search')
  37. .split('&clazz_course_id=')[1]
  38. .split('&')[0];
  39.  
  40. // 判断 当前页面
  41. switch (c) {
  42. case 'interaction':
  43. /**
  44. * *---------------------------------------*
  45. * * 为 已结束 的 测试活动 添加直接查看分析的按钮 *
  46. * *---------------------------------------*
  47. */
  48.  
  49. // 获取 活动节点集合
  50. let activities = $('.interaction-row');
  51.  
  52. // 遍历所有活动
  53. for (let index = 0; index < activities.length; index++) {
  54. const activity = activities[index];
  55. const activityType = activity.getAttribute('data-type');
  56. const quizStatus =
  57. activity.children[1].children[0].children[0].className;
  58. // 判断 每个活动节点是否为测试
  59. if (activityType === 'QUIZ') {
  60. let id = activity.getAttribute('data-id');
  61. // 如果 是测试并且已经结束
  62. if (quizStatus === 'interaction-status end') {
  63. // 添加 直接打开分析页面的按钮
  64. let url = `https://www.mosoteach.cn/web/index.php?c=interaction_quiz&m=person_quiz_result&clazz_course_id=${clazzCourseId}&id=${id}&order_item=group`;
  65. let button = document.createElement('div');
  66. button.className = 'interaction-status processing';
  67. button.innerText = '习题分析';
  68. button.addEventListener('click', () => {
  69. window.open(url);
  70. event.stopPropagation();
  71. });
  72. activity.children[1].children[0].appendChild(button);
  73. }
  74. // 如果 是测试并且本地有答案
  75. if (JSON.parse(window.localStorage.getItem(id))) {
  76. let button = document.createElement('div');
  77. button.className = 'interaction-status processing';
  78. button.innerText = '有答案';
  79. activity.children[1].children[0].appendChild(button);
  80. }
  81. }
  82. }
  83. break;
  84.  
  85. case 'interaction_quiz':
  86. /**
  87. * *-------------------------------------*
  88. * * 为 测试分析 添加导出全部题目到粘贴板的按钮 *
  89. * *-------------------------------------*
  90. */
  91.  
  92. const id = a.prop('search').split('&id=')[1].split('&')[0];
  93.  
  94. if (m === 'reply') {
  95. $('[style="text-align:center;"]').attr(
  96. 'style',
  97. 'position: sticky;text-align:center;bottom: 100px;'
  98. );
  99.  
  100. let _answersList = JSON.parse(window.localStorage.getItem(id));
  101.  
  102. let quizList = $('.student-topic-row');
  103.  
  104. // 创建标示
  105. var copyButton = document.createElement('button');
  106. if (_answersList) {
  107. copyButton.innerHTML = '该测试有答案';
  108. copyButton.style =
  109. 'width: 100px;height: 50px;position: fixed;top: 400px;left: 30px;background-color: green;';
  110. copyButton.addEventListener('click', function () {
  111. for (const key in _answersList) {
  112. if (_answersList.hasOwnProperty(key)) {
  113. const answers = _answersList[key];
  114. for (let i = 0; i < quizList.length; i++) {
  115. const quiz = quizList[i];
  116. if (
  117. quiz.children[0].children[1].children[1].innerText.indexOf(
  118. key
  119. ) === 0
  120. ) {
  121. for (let j = 0; j < answers.length; j++) {
  122. const answer = answers[j];
  123. switch (answer) {
  124. case 'A':
  125. quizList[i].children[2].click();
  126. break;
  127.  
  128. case 'B':
  129. quizList[i].children[3].click();
  130. break;
  131.  
  132. case 'C':
  133. quizList[i].children[4].click();
  134. break;
  135.  
  136. case 'D':
  137. quizList[i].children[5].click();
  138. break;
  139.  
  140. case 'E':
  141. quizList[i].children[6].click();
  142. break;
  143.  
  144. case 'F':
  145. quizList[i].children[7].click();
  146. break;
  147.  
  148. case 'G':
  149. quizList[i].children[8].click();
  150. break;
  151.  
  152. case 'H':
  153. quizList[i].children[9].click();
  154. break;
  155.  
  156. case 'I':
  157. quizList[i].children[10].click();
  158. break;
  159.  
  160. case 'J':
  161. quizList[i].children[11].click();
  162. break;
  163.  
  164. case 'K':
  165. quizList[i].children[12].click();
  166. break;
  167.  
  168. case 'L':
  169. quizList[i].children[13].click();
  170. break;
  171.  
  172. case 'M':
  173. quizList[i].children[14].click();
  174. break;
  175.  
  176. default:
  177. break;
  178. }
  179. }
  180. }
  181. }
  182. }
  183. }
  184. });
  185. } else {
  186. copyButton.innerHTML = '该测试无答案';
  187. copyButton.style =
  188. 'width: 100px;height: 50px;position: fixed;top: 400px;left: 30px;background-color: red;';
  189. }
  190.  
  191. // 挂载 按钮节点
  192. document.body.appendChild(copyButton);
  193. } else {
  194. let _answersList = JSON.parse(window.localStorage.getItem(id));
  195.  
  196. // 创建 按钮节点
  197. var copyButton = document.createElement('button');
  198. if (_answersList) {
  199. copyButton.innerHTML = '该测试已有答案,导出试题';
  200. copyButton.style =
  201. 'width: fit-content;padding: 30px;height: 50px;position: fixed;top: 400px;left: 30px;background-color: green;';
  202. } else {
  203. copyButton.innerHTML = '该试题无答案,点击导出试题并保存答案';
  204. copyButton.style =
  205. 'width: fit-content;padding: 30px;height: 50px;position: fixed;top: 400px;left: 30px;background-color: red;';
  206. }
  207. copyButton.addEventListener('click', function () {
  208. getQuiz(id);
  209. });
  210.  
  211. // 挂载 按钮节点
  212. document.body.appendChild(copyButton);
  213. }
  214.  
  215. break;
  216.  
  217. case 'res':
  218. /**
  219. * *-------------------------------------*
  220. * * 为 资源 添加是否可拖动进度条开关 *
  221. * *-------------------------------------*
  222. */
  223. const dragSwitch = $(
  224. '<i class="icon-ok-circle" id="dragable" style="margin-left: 10px;"></i><span>视频进度可拖拽</span>'
  225. );
  226.  
  227. $('div[data-mime=video]').attr('data-drag', 'Y');
  228.  
  229. dragSwitch.click(() => {
  230. if ($('#dragable').attr('class') == 'icon-circle-blank') {
  231. $('#dragable').attr('class', 'icon-ok-circle');
  232.  
  233. $('div[data-mime=video]').attr('data-drag', 'Y');
  234. } else {
  235. $('#dragable').attr('class', 'icon-circle-blank');
  236.  
  237. $('div[data-mime=video]').attr('data-drag', 'N');
  238. }
  239. });
  240.  
  241. $("div[style='display:inline-block;']").after(dragSwitch);
  242.  
  243. /**
  244. * *-------------------------------------*
  245. * * 点开视频再关闭即可实现看完 *
  246. * *-------------------------------------*
  247. */
  248. $.ajaxSetup({
  249. beforeSend: function () {
  250. console.log(arguments[1].data);
  251. let data = arguments[1].data;
  252. let encodedData = '';
  253. for (const key in data) {
  254. if (data.hasOwnProperty(key)) {
  255. let value = data[key];
  256. if (key.includes('watch_to')) {
  257. value = data.duration;
  258. }
  259. encodedData = encodedData.concat(`&${key}=${value}`);
  260. }
  261. }
  262. arguments[1].data = encodedData.substring(1, encodedData.length);
  263. },
  264. processData: false,
  265. });
  266. break;
  267.  
  268. default:
  269. break;
  270. }
  271.  
  272. const getQuiz = (id) => {
  273. const quizTitle = $('.info-con')[0].children[0].innerText;
  274. const quizCollection = $('.topic-item');
  275. const quizAnswerCollection = $('.answer-l');
  276. let quizList = [];
  277. let answerList = {};
  278. // 获取 所有题目
  279. for (let quizIndex = 0; quizIndex < quizCollection.length; quizIndex++) {
  280. const quiz = quizCollection[quizIndex];
  281. const num = quiz.children[0].children[0].innerHTML;
  282. const question =
  283. quiz.children[0].children[1].children[1].children[0].innerText;
  284. const optionCount =
  285. quiz.children[0].children[1].children[2].childElementCount;
  286. let options = [];
  287.  
  288. // 获取 该题所有选项
  289. for (let optionIndex = 0; optionIndex < optionCount; optionIndex++) {
  290. const optionMark =
  291. quiz.children[0].children[1].children[2].children[optionIndex]
  292. .children[0].innerText;
  293. const option =
  294. quiz.children[0].children[1].children[2].children[optionIndex]
  295. .children[1].innerText;
  296. options.push(`
  297. ${optionMark} ${option}`);
  298. }
  299.  
  300. // 获取 答案
  301. let answer = quizAnswerCollection[quizIndex].children[0].innerHTML;
  302.  
  303. quizList.push(`
  304. ${num}. ${question} ${answer}
  305. ${options}`);
  306.  
  307. answerList[question] = answer;
  308. }
  309.  
  310. // 整理内容
  311. var detail = `题目标题: ${quizTitle}
  312. 题目总数: ${quizCollection.length}
  313. 题目: ${quizList}
  314. `;
  315.  
  316. var oInput = document.createElement('textarea');
  317. oInput.value = detail;
  318. document.body.appendChild(oInput);
  319. oInput.select();
  320. document.execCommand('Copy');
  321. oInput.className = 'oInput';
  322. oInput.style.display = 'none';
  323. alert('已复制到粘贴板');
  324. window.localStorage.setItem(id, JSON.stringify(answerList));
  325. copyButton.style =
  326. 'width: fit-content;padding: 30px;height: 50px;position: fixed;top: 400px;left: 30px;background-color: green;';
  327. };
  328. })();

QingJ © 2025

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