东营继续教育

from ai build

// ==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秒执行
    };
})();