Greasy Fork

Greasy Fork is available in English.

职教云|智慧职教助手

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

当前为 2021-09-28 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴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      0.5.beta
// @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==


//需要排除内容的列表
exclude_array = [

];

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

//结束变量
let stop;

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

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

//模块指针
point = 0;

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




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

//判断是课程首页还是学习页面
if (document.URL.indexOf(url)!==-1) {
    //课程首页
    console.log("dir-begin");
    deleteCookie();
    stop = setInterval(main, 2000);
}else {
    sleep(5000).then(()=>{
        console.clear();
        //学习页面(观看视频或者图片)
        console.log("study-begin");
        let look = new Look();
        look.main();

    })
}


function main() {

    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("所有模块数组:"+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)    //为零就等待下一次获取

    //前面有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])
        }
    }


}


//点击章节中的内容(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; 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; 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);
    if (childNodeNum<=1){
        //为空返回true
        return true;
    }else {
        return false;
    }
}


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

    //包含在数组中的就排除
    if (exclude_array.indexOf(title)>=0){
        console.log("排除的内容title: "+title)
        return;
    }

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

    //获取内容类型
    currentContentType(content);

    //不包含就点击,并结束下面的
    content.click();
    next = true;
    clearInterval(stop);
}


//获取当前内容类型(设置cookie)
function currentContentType(content) {
    let type = content.getElementsByTagName("span")[1].innerHTML.trim();
    console.log(type)
    document.cookie = "contentType="+type+";path=/";

}

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

//获取对应的cookie
function getCookie(name){
    let arr = document.cookie.split(";");
    for(let i = 0;i<arr.length;i++){
        let arrName = arr[i].split("=");
        if(arrName[0].trim() === name){
            return arrName[1];
        }
    }
    return " ";
}

//删除cookie
function deleteCookie() {
    //获取当前时间
    let date=new Date();
    //将date设置为过去的时间
    date.setTime(date.getTime()-1);
    //这个cookie删除
    document.cookie="contentType=0; expire="+date;
}


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

class Look {

    //视频进度
    schedule = "0";


    //处理学习时候的上次学习提示
    Hint(){
        let link = document.getElementsByClassName("link");
        if (link.length===0){
            //没有弹出提示
            console.log("--2.hint");
            return;
        }
        //点击本次的学习记录
        link[1].getElementsByTagName("a")[0].click();
    }

    //控制器(对于ppt,文档,视频做出不同的操作)
    controller(){
        //文档
        if (document.getElementsByClassName("swiper-pagination-current")[0]){
            console.log("当前观看的为文档");
            return 0;
        }else if(document.getElementsByClassName("stage-next-btn")[0]){
            console.log("当前观看的为ppt");
            return 1;
        }else if(document.getElementsByClassName("MPreview-arrowBottom")[0]){  //另一种ppt
            console.log("当前观看的为ppt(无特效)");
            return 2;
        }else if (typeof(this.getSchedule())!=="error"){
            console.log("当前观看的为视频");
            return 3;
        }else {
            console.log("出错")
        }
    }

    //控制器之后执行
    execute(status){
        switch (status) {
            case 0: //文档
                this.clickNext(this.getClickNum()); break;
            case 1: //ppt
                this.ppt(); break;
            case 2: //ppt(没有特效)
                this.ppt_(); break;
            case 3: //视频
                setInterval(this.video,1000); break;
            default:
                console.log("出错1")
        }
    }

    //处理视频
    video(){
        this.schedule = getSchedule();
        if(this.schedule!=="100%" ){
            console.log("观看进度:"+getSchedule())
            except();

        }else {
            backUp();
        }
    }


    //处理ppt
    ppt() {
        for (let i = 1; i <= 350; i++) {
            sleep(20*i).then(() => {
                //图片下一张按钮
                let next = document.getElementsByClassName("stage-next-btn")[0];
                console.log("点击:"+i);
                next.click();
            })

        }

        console.log("等待")
        //等待一分钟
        sleep(60000).then(() => {
            console.log("开始")
            debugger;
            this.backUp();
        })

    }



    //处理没有特效的ppt
    ppt_(){
        let imgNum_ = null
        for (let i = 1; i <= 200; i++) {

            let next = document.getElementsByClassName("MPreview-arrowBottom")[0];

            //获取当前的图片数
            let imgNum = document.getElementsByName("newlyPicNum")[0].value;
            console.log("点击"+i);
            next.click();

            //点击之后如果等于点击之前,就说明刷完了 (break)
            if (imgNum_===imgNum){
                console.log("ppt_break")
                break;
            }else
                imgNum_ = imgNum
        }

        console.log("等待")
        //等待一分钟
        sleep(60000).then(() => {
            console.log("开始")
            this.backUp();
        })
    }


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

    //获取需要点击多少次图片(处理文档)
    getClickNum(){
        //当前图片页数
        let current = document.getElementsByClassName("swiper-pagination-current")[0].innerHTML;

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

        console.log("需要点击"+(all-current+1)+"次")

        //返回点击次数
        return all-current+1;




    }

    //点击下一张图片(处理文档)
    clickNext(num){
        console.log("4.num")
        let div = document.getElementsByClassName("swiper-button-next");
        for (let i = 1; i <= num+1; i++) {
            sleep(2000*i).then(() => {
                console.log("5.click");
                div[0].click();
                if (i===num+1){
                    this.backUp();
                }
            })
        }
    }



    //点击后退,返回课程首页
    backUp(){
        let back = document.getElementsByClassName("np-menu-nav-li")[0];
        back.getElementsByTagName("a")[0].click();
    }

    main(){
        console.log("--1.Look main")
        this.Hint();
        //控制器
        let status = this.controller();
        this.execute(status);

    }
}



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

//获取视频进度
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(a);
        a.click();
    }else{
        //console.log("无异常")
    }
}

//点击后退,返回课程首页
function backUp(){
    let back = document.getElementsByClassName("np-menu-nav-li")[0];
    back.getElementsByTagName("a")[0].click();
}