Greasy Fork

Greasy Fork is available in English.

职教云|智慧职教助手[稳定版]

智慧职教自动刷课,点击进入课程首页自动开始(播放视频第一次手动静音),可结合浏览器倍数插件一起使用(最好别超过1.5倍速)

当前为 2021-12-07 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         职教云|智慧职教助手[稳定版]
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  智慧职教自动刷课,点击进入课程首页自动开始(播放视频第一次手动静音),可结合浏览器倍数插件一起使用(最好别超过1.5倍速)
// @author       maple
// @match        https://zjy2.icve.com.cn/study/process/process.html*
// @match        https://zjy2.icve.com.cn/common/directory/directory.html*
// @icon         https://zjy2.icve.com.cn/common/images/logo.png
// @grant        none
// ==/UserScript==
////////课程首页参数///////////
//需要排除内容的列表
let exclude_array = [
    '自己添加需要过滤的内容名称,按照脚本说明来','例如:----->','《单筋矩形截面正截面受弯承载力计算公式》微课录像.mp4','《梁、板斜截面抗剪承载力计算公式的应用》微课录像.mp4',
    '《单筋矩形正截面梁的计算实例》微课录像.mp4','《梁、板裂缝宽度验算》微课录像.mp4'
];

//未完成的模块数组
let undoneModule = [];

//结束变量
let stop;

//包含章节的tr列表长度
let trList_len;

//模块下所有内容的数量
let contentList_num;

//模块指针
point = 0;

//是否下一个模块
let next = false;

//排除次数
let excludeNum = 0;

// 点击学习页面就不在执行循环【内部会有延迟,所有需要停止】
let continue_for = true;


///////学习页面参数///////////

//判断视频内容的次数
let judgeCount = 0;

//判断内容结束条件
let judgeStop;


//用于判断是否为视频的变量【其他页面也有】
let play;

//学习内容的类型
let contentType="";

//学习是否结束
let study_end = false;



////////////////////////////////////////////////【begin】////////////////////////////////////////////////////////////

//课程首页的网址
let url = 'https://zjy2.icve.com.cn/study/process/process.html?'

//判断是课程首页还是学习页面
if (document.URL.indexOf(url)!==-1) {
    //课程首页
    console.log("dir-begin");
    stop = setInterval(main, 2000);
}else {
    //学习页面开始
    console.log("study-begin")
    judgeStop = setInterval(studyMain, 2000);
}


///////////////////////////////////////////////课程首页//////////////////////////////////////////


//课程首页主函数
function main() {

    //首页加载超时处理
    exeTimeout();

    try{
        //数组中有数据就不需要获取数组
        if (undoneModule.length===0){
            findUndoneModule();
        }

        console.log("当前模块索引:"+point)
        openModule(undoneModule[point]);
        openSection(undoneModule[point]);
        clickContent(undoneModule[point]);
    }catch (e) {
        console.log("错误信息:"+e);
        //stop = setInterval(main, 5000);
    }

    next_module();
}

//找到所有未完成模块
function findUndoneModule() {
    //包含所有模块的div(里面还有别的标签)
    let div = document.getElementById("process_container");
    //过滤之后的所有模块[列表]
    let moduleList = div.getElementsByClassName("moduleList");

    //遍历模块数组
    for (let i = 0; i < moduleList.length; i++) {
        //找到每个模块的进度div
        let schedule = moduleList[i].getElementsByTagName("div")[2];
        //进度不为100%就添加到未完成
        if (" 100% " !== schedule.innerHTML){
            //添加未完成模块到数组
            undoneModule.push(moduleList[i]);
        }
    }
    console.log("所有模块数组:")
    console.log(undoneModule);

}

//展开模块
function openModule(m1) {
    //模块展开状态
    let status = m1.getElementsByClassName("topic_container")[0].style.display;

    //状态不可见,展开模块
    if ("block"!==status){
        //点击模块的三角箭头,【展开模块目录】
        m1.getElementsByTagName("span")[1].click();
    }
}

//展开模块下的章节
function openSection(m) {
    //包含模块下所有章节的div
    let div = m.getElementsByClassName("topic_container")[0];
    //包含章节的tr列表
    let trList = div.getElementsByTagName("tr");

    //等待才能获取到tr列表的长度
    if (trList_len===undefined || trList_len===0){
        trList_len = trList.length;
    }
    console.log("trList长度:"+trList_len)    //为零就等待下一次获取【为2表示这个是空模块】

    //前面有3个无效tr,不是章节(从索引为3的开始取)
    for (let i = 2; i < trList.length; i++) {
        if (i%2===1){
            //这个里面所有的都是有效章节 每一个为trList[i]
            //未打开才展开【未展开是有这个元素】
            let openStatus = m.getElementsByClassName("am-icon sh-toc-expand  topic_condensation am-icon-caret-right")[0];
            if (openStatus!==undefined){
                trList[i].click();          //展开模块中的每一个章节
            }
            //console.log(trList[i])
        }
    }

    //trList=2时表示这个模块为空【未获取到数据trList=0】
    if (trList_len===2){
        //开始下一个模块
        next=true;
    }


}


//点击章节中的内容(ppt,视频...)
function clickContent(m) {
    //包含所有内容的div [一个模块下所有的,不含不同章节的内容]
    let contentDiv = m.getElementsByClassName("sh-toc-list");
    if (contentList_num===undefined || contentList_num===0){
        contentList_num = contentDiv.length;
    }else {
        console.log("div长度::"+contentList_num);
        //clearInterval(stop)
    }
    for (let i = 0; i < contentList_num && continue_for === true; i++) {
        let contentList = contentDiv[i];    //模块中某一个章节的所有内容

        //console.log(contentList);         //如果输出的内容下没有子标签,那么这个章节中没有内容(直接下一个模块)

        //判断章节是否为空 [空返回true]
        if (isEmptySection(contentList) && point===0){
            next = true;
            continue;
        }

        //一个章节中的所有模块
        let contentS = contentList.getElementsByClassName("sh-res-h am-margin-top-xs");
        //console.log(contentS)

        // 点击内容之后就不在循环
        for (let j = 0; j < contentS.length && continue_for === true; j++) {
            //最小单位 内容
            let content = contentS[j];
            //console.log(content)

            //有a标签才是内容,不然有可能是文件夹
            if (content.getElementsByTagName("a").length!==0){

                //内容中的span标签,用来获取这个内容的进度
                let span = content.getElementsByTagName("span")[0];

                //学习进度不是100%就点击
                if (span.title!=="100%" && span.title!==undefined && span.title!==""){
                    //console.log("未完成:")
                    //console.log("学习进度:"+span.title);
                    //console.log(content);

                    //排除异常的内容(数组中的自定义)
                    exclude(content);
                }else if (i===contentS.length-1 && span.title ==="100%"){
                    //模块中的所有内容都已完成 【只是模块进度还没刷新,打开了这个模块】
                    next = true;    //下一个模块

                }



            }
        }
    }


}

//判断一个章节是否为空
function isEmptySection(contentList) {
    //子节点个数(为1就是章节为空[有一个text子标签])
    let childNodeNum = contentList.childNodes.length;
    //console.log("子节点的个数:"+childNodeNum);
    return childNodeNum <= 1;
}


//排除异常的内容(并点击)
function exclude(content) {
    //内容下包含[标题]的a标签(取出innerHtml就是title)
    let title = content.getElementsByTagName("a")[0].innerHTML;

    //包含在数组中的就排除
    if (exclude_array.indexOf(title)>=0){
        console.log("排除的内容title: "+title);
        //开始下一个模块
        if (excludeNum>=10){
            next = true;
        }
        excludeNum++;
        return;
    }

    console.log('------------')
    console.log("未完成内容:点击观看 "+title)
    console.log('------------')


    //不包含就点击,并结束下面的
    content.click();
    // 不继续循环
    continue_for = false;

    next = true;
    clearInterval(stop);
}



//如果上面结束了,开始下一个模块
function next_module() {
    if (next){
        point++;
        //重置
        trList_len = undefined;
        contentList_num = undefined;
        next = false;
    }
    //停止
    if (point>=30){
        clearInterval(stop);
        //刷新浏览器
        location.reload();
    }
}

//课程首页页面的超时提示
function exeTimeout() {
    //弹窗
    let popup = document.getElementsByClassName("popBox")[0];
    //弹窗存在
    if (popup){
        console.log("超时弹窗")
        //确定按钮
        let button = popup.getElementsByClassName("sgBtn ok")[0];
        button.click();
        //刷新浏览器
        location.reload();
    }
}



///////////////////////////////////////////////学习页面///////////////////////////////////////////////

//学习页面主函数
function studyMain(){
    //处理上一次学习记录弹窗
    hint();
    //判断学习内容类型
    judgeType();
    //控制器【不同类型执行不同操作】
    controller();
}

//处理提示[上次学习与这次学习]
function hint(){
    let link = document.getElementsByClassName("link");
    if (link.length===0){
        //没有弹出提示
        return;
    }
    //不会在控制台显示,因为点击之后会刷新浏览器
    console.log("上一次学习记录【已处理】");

    //【弹出提示】点击本次的学习记录
    link[1].getElementsByTagName("a")[0].click();
}

//判断当前学习的内容类型 【都需要第二次才能获取到】
function judgeType() {

    //执行一次判断【自增】
    judgeCount++;

    //文档   【正常】
    let doc = document.getElementsByClassName("swiper-pagination-total")[0];
    if(doc){
        // console.log("文档")
        // console.log(doc);
        contentType = "文档";
    }

    //ppt[动态]  【正常】
    let ppt = document.getElementsByClassName("stage-next-btn")[0];
    if(ppt){
        // console.log("ppt[动态]")
        // console.log(ppt);
        contentType = "ppt[动态]";
    }

    //ppt[静态] 【正常】
    let pt = document.getElementsByClassName("MPreview-pageCount")[0];
    if(pt){
        //获取到之后输出
        // console.log("ppt[静态]");
        // console.log(pt)
        contentType = "ppt[静态]";
    }

    // 图片
    let image = $("#docPlay").children("img")[0];
    if (image){
        // console.log("[图片]")
        // console.log(image)
        contentType = "图片";
    }


    //视频【这个其他页面也有,主要是用来获取后面的节点】  【正常】
    if (!play){
        play = document.getElementById("docPlay");
    }
    //下面有内容才是继续
    if(play.innerHTML!==""){
        //play中有这个类的标签就是视频
        let set = play.getElementsByClassName("jw-media jw-reset")[0];
        if(set){
            // console.log("视频")
            // console.log(set);
            contentType = "视频";
        }
    }

    //判断学习内容【只判断3次】
    if (judgeCount>=3){
        clearInterval(judgeStop)
    }
}


//控制器
function controller(){
    if(contentType!==""){
        //输出学习内容类型并结束获取
        console.log(contentType);
        clearInterval(judgeStop);

        //相应的内容做对应的操作
        sWitch(contentType);
        return;
    }

    //3次之后还未获取到 [重复获取]
    if(contentType==="" && judgeCount===3){
        console.log("未获取到学习内容类型");
        judgeStop = setInterval(studyMain, 4000);

    }
}


//执行相应的处理操作
function sWitch(type){
    switch(type){
        case      "文档": exeDoc();break;
        case "ppt[动态]": exePpt();break;
        case "ppt[静态]": exePt();break;
        case      "视频": exeVideo();break;
        case      "图片":exeImage();break;
    }
}


// 处理图片
function exeImage(){
    // 2秒之后直接返回首页
    study_end = true;
    setTimeout(back, 2000);
}


//处理文档
function exeDoc(){
    //当前图片页数
    let current = document.getElementsByClassName("swiper-pagination-current")[0].innerHTML;

    //所有图片页数
    let all = document.getElementsByClassName("swiper-pagination-total")[0].innerHTML;

    //点击次数【可能存在延迟,多点击2次】
    let count = all-current+3;

    console.log("点击次数:"+count);
    let docStop = setInterval(loop,1500);


    function loop(){
        // 学习异常处理
        except();

        if(count!==0){
            //下一张按钮 [可能需要等待]
            let button = document.getElementsByClassName("swiper-button-next")[0];
            button.click();
            count--;
        } else{
            //为零[点击完毕退出]
            clearInterval(docStop);
            //内容学习完毕
            study_end = true;
            console.log("结束");
            //回到首页
            back();
        }
    }



}

//处理ppt[动态]
function exePpt(){

    //新页的数值
    let new_pag = "xxx";
    //结束条件
    let pptStop = setInterval(loop, 2000);
    //一张ppt的动态计数 【最大值20】
    let count = 0;

    function loop(){
        // 学习异常处理
        except();
        //新页面的数值还在变化
        if (new_pag!==getNum()){
            //上一次和这一次的页数不一致【点击下一张,并】
            new_pag = getNum();
            //图片下一张按钮[点击]
            let button = document.getElementsByClassName("stage-next-btn")[0];
            button.click();
            console.log("静态点击");

            //如果有了新的ppt页执行,动态计数清零
            count=0;
        }else{

            console.log("动态计数:"+count)
            count++;
            //如果指定次数还没有新页,则认定结束
            if (count===20){
                clearInterval(pptStop);
                console.log("结束");
                //内容学习完毕
                study_end = true;
                //回到首页
                back();
                //结束
                return;
            }

            //稍微延时之后点击一个ppt图片中的动态效果
            sleep(50).then(() => {
                //先点击下一张
                let button = document.getElementsByClassName("stage-next-btn")[0];
                button.click();

                //没有变化,可能是到了动态的ppt,也有可能是结束了
                loop();
            })
        }

    }

    function getNum(){
        //新的ppt数量【随点击而变化,不变化了就说明没有新的图片了,结束了】
        new_pag = $("input[name='newlyPicNum']").val();
        return new_pag;
    }

}

//处理ppt[静态]
function exePt(){
    let new_pag_num = 'xxx';
    let ptStop = setInterval(loop,1500);

    function loop() {
        // 学习异常处理
        except();
        //页数还在变化执行
        if(new_pag_num!==getNum()){
            //重新获取
            new_pag_num = getNum();
            //下一张按钮 [这是个侧边按钮(如果是文档走了这里,就没有侧边按钮)]
            //let button = document.getElementsByClassName("MPreview-arrowBottom")[0];

            // 下一张按钮,下方按钮【类似ppt的文档也能使用】
            let button = document.getElementsByClassName("MPreview-pageNext current")[0];
            if (button){
                button.click();
            }


        } else{
            //这一次和上一次相同了,结束
            clearInterval(ptStop);
            //内容学习完毕
            study_end = true;
            //回到首页
            back();
            console.log("结束");
        }
    }

    function getNum(){
        //新的ppt数量【随点击而变化,不变化了就说明没有新的图片了,结束了】
        new_pag_num = $("input[name='newlyPicNum']").val();
        return new_pag_num;
    }


}

//处理视频
function exeVideo(){
    //视频进度
    let schedule = "xx";
    //视频停止计数
    let count = 0;
    let videoStop = setInterval(loop, 2000);

    function loop(){
        // 学习异常处理
        except();
        //视频进度到达100%就退出
        if (schedule==="100%"){
            //结束
            console.log("结束")
            clearInterval(videoStop);
            //内容学习完毕
            study_end = true;
            //回到首页
            back();
            return;
        }else if (schedule===getSchedule()){
            //当前进进度和上一次的进度是否一样
            if (count===10){
                //重复10次进度一直,刷新浏览器
                location.reload();   //【可能无效,刷新之后还是为播放】
            }
            //视频停止计数
            count++;
        }else{
            //没有停止【计数清零】
            count=0;
        }
        //获取进度
        schedule = getSchedule();
        console.log("视频进度:"+getSchedule());
    }

}

//获取视频进度
function getSchedule(){
    try {
        let bar = document.querySelector(".jw-progress");
        return bar.style.width;
    }catch (e){
        return "error";
    }
}

//学习异常弹窗
function except(){
    //找到异常按钮a标签
    let a = document.getElementsByClassName("sgBtn ok")[0];
    //异常按钮存在就点击
    if (a !== undefined && a !== null){
        console.log("学习异常【已处理】")
        console.log(a);
        a.click();
    }else{
        //console.log("无异常")
    }
}


//学习完毕,返回首页
function back() {
    //是否学习结束
    if (study_end){
        //返回按钮
        let back = document.getElementsByClassName("np-menu-nav-li")[0];
        //延迟两秒之后返回首页
        sleep(4000).then(() => {
            back.getElementsByTagName("a")[0].click();
        })
    }
}


//延时函数
function sleep (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
}