Greasy Fork

Greasy Fork is available in English.

东营继续教育

from ai build

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         东营继续教育
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  from ai build
// @author       xuefeng
// @match        *://*.yxlearning.com/*
// @grant        none
// @license
// ==/UserScript==

(function () {
    'use strict';

    // 确保页面完全加载后再执行脚本
    window.onload = function () {
        // 确保页面完全加载后再执行脚本,在这使用的是延时的办法
        setTimeout(function () {
            // 获取当前页所有章节的元素的ID
            function getAllUnitID() {
                // 声明一个存储当前课程的每章节id的数组
                var allUnitID = [];
                // 获取所有 class 为 "pt5" 的 ul 元素
                var ulElements = document.querySelectorAll('ul.pt5');

                // 遍历每个 ul 元素
                ulElements.forEach(function (ul) {
                    // 获取 ul 元素下的所有 li 元素
                    var liElements = ul.querySelectorAll('li');

                    // 遍历每个 li 元素并获取其 id
                    liElements.forEach(function (li) {
                        allUnitID.push(li.id);
                    });
                });
                console.log("已经获取所有的章节ID", allUnitID);
                return allUnitID;
            }

            // 找到当前章节的管视频播放的那个video标签,也即当前页面真实的视频标签
            // nowUnitVideoElement 当前章节真实的视频元素标签
            function nowUnitTrueVideo() {
                var nowUnitTrueVideoElement = document.querySelectorAll("video");
                for (var i = 0; i < nowUnitTrueVideoElement.length; i++) {
                    if (nowUnitTrueVideoElement[i].duration) { // 判断当前页面是否有视频标签 duration是看所拿到的视频标签是否有播放时长的属性,如果有那就是真实的视频元素
                        return nowUnitTrueVideoElement[i];//拿到真实的视频元素就返回给调用该函数的变量
                    }
                }
            }

            // 点击这个视频所在的章节(即点击nowUnitID,即点击这个对应标题进入视频播放页),并确保完全进入该章节后改变promise状态
            // inNowUnitID 进入当前的章节,以便于播放该小标题下的视频
            // nowUnitID 当前小标题的ID(即当前章节的ID)
            const inNowUnitID = (nowUnitID) => {
                return new Promise((resolve) => { // promise 一旦建立就立即执行,但是状态的改变需要resolve()
                    document.querySelectorAll('li[id="' + nowUnitID + '"]')[0].click();
                    setTimeout(() => { resolve("等待时间到,应该已完全进入该章节") }, 40000) //往往是刚通过上句.click()点击该视频之后,改小标题下的视频还没有出来,如果此时接着点击播放视频,就会失败,所以添加了一个延时点击。
                })
            }

            // 进入当前章节后找到真正的视频元素,并且保持持续播放,直到100%
            // getNowUnitTrueVideoElement_AND_keepVideoPlay  获得当前小章节的真实视频元素 并 保证持续播放
            // nowUnitID:当前小章节的ID
            const getNowUnitTrueVideoElement_AND_keepVideoPlay = (nowUnitID) => { //传入nowUnitID,也就是传入当前的小章节ID,然后在本函数内嵌套有chekckVideoPlay函数,会用到
                return new Promise((resolve) => {
                    const nowUnitTrueVideoElement = () => { //定义一个函数,用于获取当前小章节的视频元素
                        var nowUnitTrueVideoElement = document.querySelectorAll("video");  //获取当前页面的所有video标签
                        for (var i = 0; i < nowUnitTrueVideoElement.length; i++) { //遍历所有video标签
                            if (nowUnitTrueVideoElement[i].duration) { //判断当前video标签是否为真实视频(即有duration属性)
                                return nowUnitTrueVideoElement[i]; //返回真实视频
                            }
                        }
                    }


                    const checkVideo_IS_Done = setInterval(() => { // 检测视频是否播放完毕,只有播放完毕之后才允许该promise resolve()
                        console.log("当前章节视频完成了" + document.querySelector('[id="' + nowUnitID + '-badge"]').textContent);
                        if (document.querySelector('[id="' + nowUnitID + '-badge"]').textContent != '100%') {  //当播放未达到100%
                            try {
                                if (nowUnitTrueVideoElement().paused) { // 如果视频暂停
                                    nowUnitTrueVideoElement().muted = true;  // 静音
                                    nowUnitTrueVideoElement().play();   // 就点击播放
                                    console.log("刚才检测到视频暂停,已自动点击本页视频播放");
                                } else {
                                   // console.log("当前小节视频没有暂停,正在播放无需处理");
                                }
                            } catch (error) {
                                console.error("播放视频时发生错误:", error);
                            }
                        }else{  //当播放已经达到100%

                            clearInterval(checkVideo_IS_Done);  //清除定时检查功能
                            resolve("本节播放完成")
                        }
                    }, 1000)
                })

            }



            // 视频播放特殊处理,检测弹出的答题框
            function autoClickSkipButton() {
                // 选择需要观察变动的节点
                var targetNode = document.body;
                // 配置观察选项
                var config = { childList: true, subtree: true };

                const changecallback = function (mutations) {
                    mutations.forEach(function (mutation) {
                        if (document.querySelector('div.ccQuestion')) {
                            // 找到并点击 "跳过" 按钮
                            var skipButton = document.querySelector('input[value="跳过"]');
                            if (skipButton) {
                                skipButton.click();
                                // 重新启动观察者,以便处理后续的变化
                                observer.disconnect();
                                observer.observe(document.body, config);
                            }
                        }
                    });
                };

                // 创建一个观察者实例
                var observer = new MutationObserver(changecallback);

                // 开始观察
                observer.observe(targetNode, config);
                console.log("已开启自动跳过答题框");
            }
            //-------------------------事件顺序-------------------------------



            // 获取本课程所有的章节ID(也即allUnitID)
            const allUnitID = getAllUnitID();


            // 开始播放课程所有章节
            const start = async (allUnitID) => {
                console.log("Type of allUnitID:", typeof allUnitID);
                for (const nowUnitID of allUnitID) {
                    console.log("当前播放的是第" + (allUnitID.indexOf(nowUnitID) + 1) + "个小节");
                    const res1 = await inNowUnitID(nowUnitID) //进入当前章节
                    console.log(res1)
                    const res2 = await getNowUnitTrueVideoElement_AND_keepVideoPlay(nowUnitID) //获得当前小章节的视频元素并保持持续播放
                    console.log(res2)
                }
            }
            // 开始
            start(allUnitID);
            // 调用观察者确保跳过答题框
            autoClickSkipButton();  // 不需要传入参数

        }, 20000); // 延迟10秒执行
    };
})();