国家中小学智慧平台快速学习2004暑假研修(快速学习)

需要进入具体的播放页面,加载油猴,可全部完成本页视频播放。

  1. // ==UserScript==
  2. // @name 国家中小学智慧平台快速学习2004暑假研修(快速学习)
  3. // @namespace http://tampermonkey.net/
  4. // @version 3.7
  5. // @author 桥风online(修改版)
  6. // @description 需要进入具体的播放页面,加载油猴,可全部完成本页视频播放。
  7. // @match https://basic.smartedu.cn/teacherTraining/courseDetail*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=qlteacher.com
  9. // @license 桥风online
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. // 拦截和修改XHR请求
  17. function interceptXHR() {
  18. const XHR = XMLHttpRequest.prototype;
  19. const open = XHR.open;
  20. const send = XHR.send;
  21.  
  22. XHR.open = function (method, url) {
  23. this._url = url;
  24. return open.apply(this, arguments);
  25. };
  26.  
  27. XHR.send = function () {
  28. this.addEventListener('load', function () {
  29. if (this._url.includes('progress') || this._url.includes('heartbeat')) {
  30. console.log('拦截:', this._url);
  31. try {
  32. const json = JSON.parse(this.responseText);
  33. json.progress = 100;
  34. json.completed = true;
  35. Object.defineProperty(this, 'responseText', {
  36. get: function () { return JSON.stringify(json); }
  37. });
  38. } catch (e) {
  39. console.error('修改响应失败:', e);
  40. }
  41. }
  42. });
  43. return send.apply(this, arguments);
  44. };
  45. }
  46.  
  47. // 模拟用户交互
  48. function simulateUserInteraction(video) {
  49. if (video) {
  50. video.dispatchEvent(new MouseEvent('mousemove', {
  51. view: window,
  52. bubbles: true,
  53. cancelable: true
  54. }));
  55.  
  56. video.dispatchEvent(new MouseEvent('click', {
  57. view: window,
  58. bubbles: true,
  59. cancelable: true
  60. }));
  61. }
  62. }
  63.  
  64. // 更新存储
  65. function updateStorage() {
  66. const storageKeys = ['videoProgress', 'courseProgress', 'lessonComplete'];
  67. storageKeys.forEach(key => {
  68. try {
  69. localStorage.setItem(key, '100');
  70. sessionStorage.setItem(key, '100');
  71. } catch (e) {
  72. console.error('更新存储失败:', e);
  73. }
  74. });
  75. }
  76.  
  77. // 跳过单个视频
  78. function skipVideo(video) {
  79. return new Promise((resolve) => {
  80. if (video) {
  81. const button = document.querySelector('.fish-btn-primary span');
  82. if (button && button.textContent.trim() === '我知道了') {
  83. // 如果找到了按钮,模拟点击事件
  84. button.closest('button').click();
  85. console.log('已点击"我知道了"按钮');
  86. } else {
  87. console.log('未找到"我知道了"按钮');
  88. }
  89. video.dispatchEvent(new Event('ended'));
  90. setTimeout(function () {
  91. video.muted = true;
  92. video.playbackRate = 1.2;
  93. video.play()
  94. video.play().catch(e => console.error('播放视频错误:', e));
  95. }, 1500);
  96.  
  97. simulateUserInteraction(video);
  98. updateStorage();
  99. if (typeof window.onVideoComplete === 'function') {
  100. window.onVideoComplete();
  101. }
  102. if (typeof window.finishLesson === 'function') {
  103. window.finishLesson();
  104. }
  105.  
  106. setTimeout(resolve, 2000);
  107. } else {
  108. resolve();
  109. }
  110. });
  111. }
  112.  
  113. // 展开所有折叠项并点击所有资源项
  114. async function expandAndClickAll() {
  115. // 点击顶层折叠项
  116. const topLevelHeaders = document.querySelectorAll('.fish-collapse-item > .fish-collapse-header');
  117. for (const header of topLevelHeaders) {
  118. if (header.getAttribute('aria-expanded') === 'false') {
  119. header.click();
  120. await new Promise(resolve => setTimeout(resolve, 500));
  121. }
  122. }
  123.  
  124. // 点击二级折叠项
  125. const secondLevelHeaders = document.querySelectorAll('.fish-collapse-content .fish-collapse-header');
  126. for (const header of secondLevelHeaders) {
  127. if (header.getAttribute('aria-expanded') === 'false') {
  128. header.click();
  129. await new Promise(resolve => setTimeout(resolve, 500));
  130. }
  131. }
  132.  
  133. }
  134.  
  135. // 查找所有资源项
  136. async function findAllResourceItems() {
  137. await expandAndClickAll();
  138. return document.querySelectorAll('.resource-item.resource-item-train');
  139. }
  140.  
  141. // 处理所有视频
  142. async function processAllVideos() {
  143. const resourceItems = await findAllResourceItems();
  144. console.log(`找到的资源项总数: ${resourceItems.length}`);
  145.  
  146. for (let i = 0; i < resourceItems.length; i++) {
  147. const item = resourceItems[i];
  148. console.log(`正在处理第 ${i + 1} 项`);
  149.  
  150. item.click();
  151. await new Promise(resolve => setTimeout(resolve, 1000));
  152.  
  153. const video = document.querySelector('video');
  154. await skipVideo(video);
  155.  
  156. console.log(`完成第 ${i + 1} 项`);
  157. }
  158.  
  159. console.log("所有视频已处理完毕");
  160. }
  161.  
  162. // 检查并更新按钮显示状态
  163. function updateButtonVisibility(button) {
  164. if (!window.location.href.includes("https://basic.smartedu.cn/teacherTraining/courseDetail")) {
  165. button.style.display = 'none';
  166. } else {
  167. button.style.display = 'block';
  168. }
  169. }
  170.  
  171. // 主函数
  172. function main() {
  173. interceptXHR();
  174.  
  175. // 添加控制按钮
  176. const controlButton = document.createElement('button');
  177. controlButton.textContent = '开始处理视频';
  178. controlButton.style.position = 'fixed';
  179. controlButton.style.top = '10px';
  180. controlButton.style.right = '10px';
  181. controlButton.style.zIndex = '9999';
  182.  
  183. // 初始检查并更新按钮显示状态
  184. updateButtonVisibility(controlButton);
  185.  
  186. controlButton.addEventListener('click', () => {
  187. if (controlButton.textContent === '开始处理视频') {
  188. processAllVideos().catch(error => {
  189. console.error("发生错误:", error);
  190. });
  191. controlButton.textContent = '停止处理';
  192. } else {
  193. window.location.reload();
  194. }
  195. });
  196.  
  197. document.body.appendChild(controlButton);
  198. // 监听URL变化
  199. window.onpopstate = function () {
  200. updateButtonVisibility(controlButton);
  201. };
  202.  
  203. // 监听URL变化(包括点击返回按钮)
  204. const pushState = history.pushState;
  205. history.pushState = function () {
  206. pushState.apply(history, arguments);
  207. updateButtonVisibility(controlButton);
  208. };
  209. }
  210.  
  211. // 当页面加载完成时运行主函数
  212. if (document.readyState === 'loading') {
  213. document.addEventListener('DOMContentLoaded', main);
  214. } else {
  215. main();
  216. }
  217. })();