Greasy Fork

来自缓存

Greasy Fork is available in English.

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

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==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 http://greasyfork.icu/users/449085
// @supportURL https://tuchg.github.io
// @contributionURL http://greasyfork.icu/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());
    }
})();