智慧职教资源库|学习中心 --网课助手 (青版)

小巧强大的智慧职教自动学习辅助脚本,中文化自定义各项参数

// ==UserScript==
// @name         智慧职教资源库|学习中心 --网课助手 (青版)
// @version      0.2
// @description  小巧强大的智慧职教自动学习辅助脚本,中文化自定义各项参数
// @author        tuChanged
// @run-       document-end
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @match        *www.icve.com.cn/study/directory*
// @license      MIT
// @namespace https://greasyfork.org/users/449085
// @supportURL https://tuchg.github.io
// @contributionURL https://greasyfork.org/users/449085
// ==/UserScript==
(async function () {
    'use strict';
    const setting = {
        /*影响刷课速度关键选项,延时非最优解,过慢请自行谨慎调整*/
        最高延迟响应时间: 5000,//毫秒
        最低延迟响应时间: 3000,//毫秒
        //自行根据课件情况修改
        固定PPT页数: 20,//页
        //0-流畅 1-清晰 2-原画 
        视频清晰度: 0,
        //2倍速,允许开倍速则有效,请放心使用
        视频播放倍速: 2,
        //是否保持静音
        是否保持静音: true,
        //请求超时时间
        请求超时时间: 2000,
        /*
        * 📣如果您有软件定制(管理系统,APP,小程序等),毕设困扰,又或者课程设计困扰等欢迎联系,
        *    价格从优,源码调试成功再付款💰,
        *     实力保证,包远程,包讲解 QQ:2622321887
        */

    }, _self = unsafeWindow,
        url = location.pathname,
        top = _self
    /** 等待获取jquery @油猴超星网课助手 wyn665817*/
    try {
        while (top != _self.top) top = top.parent.document ? top.parent : _self.top;
    } catch (err) {
        console.log(err);
        top = _self;
    }
    var $ = _self.jQuery || top.jQuery;
    /** */

    //产生区间随机数
    const rnd = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);

    //课程ID
    const courseID = getQueryValue("courseId")
    //章节ID
    const chapterID = getQueryValue("chapterId")
    //小节ID
    let cellID = getQueryValue("#")
    //小节类型
    const type = getQueryValue("type")
    let db = undefined
    await initDB()

    if (!chapterID) {
        //非小节,解析目录
        dirParser()
    } else {
        console.log(`当前课件为${type}`);
        switch (type) {
            case "video":
                delayExec(() => mediaHandler())
                break;
            case "text":
            case "doc":
                delayExec(() => docHandler())
                break
            default:
                delayExec(() => currentCompleted())
                break;
        }
    }
    /**
     * 当前课程结束调用
     * @param {*} params 
     */
    function currentCompleted() {
        db.transaction(['course'], 'readwrite').objectStore('course')
            .delete(cellID).onsuccess = function (params) {
                console.log(`课程${cellID}已完成`);
                delayExec(() => nextLesson())
            }
    }

    function nextLesson() {
        db.transaction(['course'], 'readwrite').objectStore('course')
            .openCursor()
            .onsuccess = (event) => {
                console.log(event, `课程已准备`);
                const result = event.target.result;
                if (result) {
                    let { ChapterId, CellType, Id } = result.value || {};
                    gotoURL(`dir_course.html?courseId=${courseID}&chapterId=${ChapterId}&type=${CellType}#${Id}`)
                } else {
                  console.log("数据库读取失败,请规范操作,从课程目录进入\n清除浏览器IndexDB数据库后再次尝试");
                }

            }
    }
    /**
     * 跳转
     * @param {*} url 
     */
    function gotoURL(url) {
        console.log(url);

        top.location = url
    }
    //值监听
    unsafeWindow.addEventListener("hashchange", () => cellID = getQueryValue("#"));

    /**
        * 获取url查询字段
        * @param {查询字段} query
        */
    function getQueryValue(query) {
        let url = window.location.search; //获取url中"?"符后的字串
        //返回hash
        if (query == "#")
            return location.hash.slice(1);
        //返回Query
        let theRequest = new Object();
        if (url.indexOf("?") != -1) {
            let str = url.substr(1);
            let strs = str.split("&");
            for (let i = 0; i < strs.length; i++)
                theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
        }
        return theRequest[query];
    }
    //解析目录
    function dirParser() {
        request("GET", `https://www.icve.com.cn/study/Directory/directoryList?courseId=${courseID}`,
            {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                },
                onSuccess: (xhr) => {
                    const json = JSON.parse(xhr.responseText).directory;
                    // console.log(dbRequest);
                    //将课程目录解析
                    parseLessons(json)
                    // parseLessons(JSON.parse(temp1.responseText).directory || {})
                }
            }
        )
    }
    //解析并处理储存课程列表
    function parseLessons(json) {
        //status 0(未看)  status 1已看
        //将读取到课程的放到localStorge,并记录状态 进行 未进行 未完成 完成

        // 0->->cells->0->status
        //             chapter
        //将未完成的课程信息提取
        if (db != undefined) {
            const tx = db.transaction(['course'], 'readwrite');
            tx.oncomplete = (e) => {
                console.log('课程批量插入成功', e)
                nextLesson()
            };
            tx.onerror = (e) => console.log('批量插入失败', e);

            const store = tx
                .objectStore('course');

            json.forEach(e => {
                e.chapters.forEach(i => {
                    i.cells.forEach(x => {
                        if (x.Status == 0)
                            store.put(x)
                    })
                })
            })
        }
        else console.log("数据库启动失败,程序终止");

    }
    /**
     * 初始化indexDB
     * @param {} version 
     */
    function initDB(version = 1) {

        return new Promise((resolve, reject) => {

            const dbRequest = indexedDB.open('ICVE', version)
            dbRequest.addEventListener('upgradeneeded', e => {
                const objectStore = e.target.result
                    .createObjectStore('course', { keyPath: 'Id', autoIncrement: false });
                // //多字段查询
                // objectStore.createIndex('SectionIdIndex', 'SectionId', { unique: false });
                // objectStore.createIndex('ChapterIdIndex', 'ChapterId', { unique: false });
            });
            dbRequest.onsuccess = function (e) {
                db = e.target.result;
                console.log("数据库连接成功!");
                resolve()
            }
        })
    }

    /**
     * 对XHR的二次全局封装,方便后期扩展
     * @param {*} method 
     * @param {*} url 
     * @param {*} headers 
     * @param {*} data 
     * @param {*} onSuccess 
     */
    function request(method, url, { headers, data, onSuccess }) {
        GM_xmlhttpRequest({
            method: method,
            url: url,
            headers: headers,
            data: data,
            timeout: setting.请求超时,
            onload: function (xhr) {
                switch (xhr.status) {
                    case 200:
                        // var obj = $.parseJSON(xhr.responseText) || {};
                        onSuccess(xhr)
                        break;
                    default:
                        console.log("服务器异常 " + xhr);
                        break;
                }
            },
            ontimeout: function () {
                console.log("响应超时");
            }
        });
    }
    /**
        * 使用异步实现
        *
        *  随机延迟执行方法
        * @param {需委托执行的函数} func
        */

    function delayExec(func) {
        return new Promise((resolve, reject) => {
            setTimeout(async () => {
                try {
                    await func()
                } catch (error) {
                    console.log(func, error);
                }
                resolve();
            }, rnd(setting.最低延迟响应时间, setting.最高延迟响应时间));
        })
    }
    /**
    * 视频/音频类处理
    */
    function mediaHandler() {
        let player = jwplayer($(".jwplayer").attr("id"))

        //视频暂停状态
        if (player.getState() == "PAUSED") {
            console.log("媒体已暂停,恢复播放");
            player.play()
        }

        //播放回调
        if (player.getState() == "COMPLETE") {
            console.log("媒体已播放完毕\n");
            delayExec(currentCompleted());
            return;
        }
        //配置
        player.setMute(setting.是否保持静音)//静音
        player.setCurrentQuality(setting.视频清晰度)
        try {
            player.setPlaybackRate(setting.视频播放倍速)
        } catch (error) {
            console.log('倍速开启失败');
        }

        //播放回调
        player.onPlaylistComplete(function () {
            console.log("媒体播放完成\n");
            delayExec(currentCompleted());
        })
    }

    /**
   * 文档处理
   * @param {*} current
   */
    async function docHandler() {

        //根据按钮状态判断是否还有下一页
        while ($(".MPreview-pageNext").hasClass('current')) {
            console.log("文档翻页了");

            //ppt翻页 异步方式
            await delayExec(() => {
                $(".MPreview-pageNext").click()
            })
        }
        delayExec(currentCompleted());
    }
})();