Greasy Fork

Greasy Fork is available in English.

chinahrt继续教育

全新2.0版本,可以自行添加播放列表(彻底解放双手,请到课程详情中添加),自动开始并静音,播放速度控制,进度拖动。增加配置面板,可以自由调节。

当前为 2022-05-14 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         chinahrt继续教育
// @include      http://web.chinahrt.com
// @include      https://web.chinahrt.com
// @version      2.4.1
// @description  全新2.0版本,可以自行添加播放列表(彻底解放双手,请到课程详情中添加),自动开始并静音,播放速度控制,进度拖动。增加配置面板,可以自由调节。
// @author       yikuaibaiban(https://github.com/yikuaibaiban)
// @match        http://*.chinahrt.com/*
// @match        https://*.chinahrt.com/*
// @match        http://videoadmin.chinahrt.com.cn/videoPlay/play*
// @match        http://videoadmin.chinahrt.com/videoPlay/play*
// @match        https://videoadmin.chinahrt.com.cn/videoPlay/play*
// @match        https://videoadmin.chinahrt.com/videoPlay/play*
// @grant        none
// @license      MIT
// @namespace https://github.com/yikuaibaiban/chinahrt
// ==/UserScript==

window.onload = function() {
    function getCourses() {
        var json = localStorage.getItem('courses');
        if (json) {
            json = JSON.parse(json);
        } else {
            json = [];
        }

        return json;
    }


    // 刷新播放列表
    function refreshPlaylist() {
        if (!playlistDiv) {
            // 播放列表
            playlistDiv = document.createElement('div');
            playlistDiv.style.cssText = "position:fixed;right:255px;top:0;width:250px;height:400px;background-color:#FFF;z-index:9999;border: 1px solid #ccc;overflow: auto;";
            document.body.appendChild(playlistDiv);
        } else {
            playlistDiv.innerHTML = "";
        }

        // 获取localStorage 转换为 json
        var json = getCourses();
        for (var i = 0; i < json.length; i++) {
            var _t = document.createElement('div');
            _t.style.fontSize = "12px";
            _t.style.overflow = "hidden";
            _t.style.whiteSpace = "nowrap";
            _t.style.textOverflow = "ellipsis";
            _t.innerText = i + 1 + " " + json[i].title;
            playlistDiv.appendChild(_t);
        }
    }

    var href = window.location.href;

    // 播放列表
    var playlistDiv;

    // 课程页面 /course/preview
    if (href.indexOf('/course/preview') > -1) {
        var button = document.createElement("button");
        button.innerHTML = "添加到播放列表";
        button.style.fontSize = "20px";
        button.style.border = "1px solid rgb(204, 204, 204)";
        button.style.borderRadius = "5px";
        button.style.padding = "5px 10px";
        button.style.background = "#4bccf2";
        button.style.color = "#fff";
        button.style.marginTop = "10px";
        button.style.cursor = "pointer";
        button.onclick = function() {
            // 获取localStorage 转换为 json
            var json = getCourses();

            var allCourses = document.getElementsByClassName("memu-in")[0].getElementsByTagName("li");
            for (var i = 0; i < allCourses.length; i++) {
                if (allCourses[i].getElementsByTagName("span")[0].innerText.indexOf("已学完") == -1) {
                    var flag = 0;
                    for (var j = 0; j < json.length; j++) {
                        if (json[j].href == allCourses[i].getElementsByTagName("a")[0].href) {
                            flag = 1;
                            break;
                        }
                    }

                    if (flag == 0) {
                        json.push({
                            "title": allCourses[i].getElementsByTagName("a")[0].innerText,
                            "href": allCourses[i].getElementsByTagName("a")[0].href
                        });
                    }
                }
            }

            // 存储到localStorage
            localStorage.setItem('courses', JSON.stringify(json));
            alert("添加完成");
        }

        document.getElementsByClassName("menu")[0].insertBefore(button, document.getElementsByClassName("menu")[0].lastChild);
    }

    // 课程页面 /course/play_video
    if (href.indexOf('/course/play_video') > -1) {
        refreshPlaylist();

        setInterval(() => {
            refreshPlaylist();
        }, 5000);

        window.addEventListener("message", function(e) {
            // 获取localStorage 转换为 json
            var json = getCourses();

            var newJson = new Array();

            for (var i = 0; i < json.length; i++) {
                // 正则提取 href 中  sectionId courseId trainplanId
                var jsonHref = json[i].href;
                var jsonSectionId = jsonHref.match(/sectionId=([^&]*)/)[1];
                var jsonCourseId = jsonHref.match(/courseId=([^&]*)/)[1];
                var jsonTrainplanId = jsonHref.match(/trainplanId=([^&]*)/)[1];

                // 正则提取 window.location.href 中  sectionId courseId trainplanId
                var href = window.location.href;
                var sectionId = href.match(/sectionId=([^&]*)/)[1];
                var courseId = href.match(/courseId=([^&]*)/)[1];
                var trainplanId = href.match(/trainplanId=([^&]*)/)[1];

                if (jsonCourseId == courseId && jsonSectionId == sectionId && jsonTrainplanId == trainplanId) {
                    continue;
                }
                newJson.push(json[i]);
            }

            localStorage.setItem("courses", JSON.stringify(newJson));

            if (newJson.length > 0) {
                window.top.location.href = newJson[0].href;
            } else {
                alert("课程列表已经播放完毕");
            }
        });
    }

    // 播放页面
    if (href.indexOf('/videoPlay/play') > -1) {
        $(document).ready(function() {
            // 顶端漂浮提示
            var $topTips = $('<div style="position: fixed;top:0;left:10%;font-size:16px;font-weight: bold;color:red;background: #FFF;">' +
                '点击课程详情页中的插件提供的【添加到播放列表】按钮添加需要自动播放的课程' +
                '<br/>受到浏览器策略影响第一次可能无法自动播放,请手动点击播放。</div>');
            $(document.body).append($topTips);


            // 从localstorage中获取设置
            var autoplay = (localStorage.getItem('autoplay') || 'true') === 'true';
            var mute = (localStorage.getItem('mute') || 'true') === 'true';
            var speed = parseInt(localStorage.getItem('speed') || '1');
            var drag = parseInt(localStorage.getItem('drag') || '5');

            // ==================页面设计开始==========================
            // 增加页面配置
            var configDiv = document.createElement("div");
            configDiv.style.cssText = "position:fixed;right:0;top:0;width:250px;height:400px;background-color:#FFF;z-index:9999;border: 1px solid #ccc;";

            // 标题
            var configTitle = document.createElement("div");
            configTitle.style.cssText = "border-bottom:1px solid #ccc ;padding: 5px;font-weight: bold;";
            configTitle.innerHTML = "视频控制配置";
            configDiv.appendChild(configTitle);

            // 外部包裹
            var configWrapper = document.createElement("div");
            configWrapper.style.cssText = "padding: 5px;padding-bottom: 5px;font-size: 12px;line-height: 150%;";

            // 是否自动播放
            var configAutoPlay = document.createElement("div");
            configAutoPlay.style.cssText = "border-bottom: 1px dotted #ccc ;padding-bottom: 5px;";
            var p = document.createElement("p");
            p.innerHTML = "是否自动播放:";
            configAutoPlay.appendChild(p);
            var inputAutoPlay = document.createElement("input");
            inputAutoPlay.type = "radio";
            inputAutoPlay.name = "autoPlay";
            inputAutoPlay.value = "true";
            inputAutoPlay.checked = autoplay;
            inputAutoPlay.onclick = function() {
                localStorage.setItem('autoplay', 'true');
            }
            configAutoPlay.appendChild(inputAutoPlay);
            var labelAutoPlay = document.createElement("label");
            labelAutoPlay.innerHTML = "是";
            configAutoPlay.appendChild(labelAutoPlay);
            var inputAutoPlay2 = document.createElement("input");
            inputAutoPlay2.type = "radio";
            inputAutoPlay2.name = "autoPlay";
            inputAutoPlay2.value = "false";
            inputAutoPlay2.checked = !autoplay;
            inputAutoPlay2.onclick = function() {
                localStorage.setItem('autoplay', 'false');
            }
            configAutoPlay.appendChild(inputAutoPlay2);
            var labelAutoPlay2 = document.createElement("label");
            labelAutoPlay2.innerHTML = "否";
            configAutoPlay.appendChild(labelAutoPlay2);
            configWrapper.appendChild(configAutoPlay);

            // 是否静音
            var configMute = document.createElement("div");
            configMute.style.cssText = "border-bottom: 1px dotted #ccc ;padding-bottom: 5px;";
            var p = document.createElement("p");
            p.innerHTML = "是否静音:";
            configMute.appendChild(p);
            var inputMute = document.createElement("input");
            inputMute.type = "radio";
            inputMute.name = "mute";
            inputMute.value = "true";
            inputMute.checked = mute;
            inputMute.onclick = function() {
                localStorage.setItem('mute', 'true');
                player.videoMute();
            }
            configMute.appendChild(inputMute);
            var labelMute = document.createElement("label");
            labelMute.innerHTML = "是";
            configMute.appendChild(labelMute);
            var inputMute2 = document.createElement("input");
            inputMute2.type = "radio";
            inputMute2.name = "mute";
            inputMute2.value = "false";
            inputMute2.checked = !mute;
            inputMute2.onclick = function() {
                localStorage.setItem('mute', 'false');
                player.videoEscMute();
            }
            configMute.appendChild(inputMute2);
            var labelMute2 = document.createElement("label");
            labelMute2.innerHTML = "否";
            configMute.appendChild(labelMute2);
            var muteTip = document.createElement("p");
            muteTip.style.cssText = "font-size:13px;font-weight:bold;";
            muteTip.innerHTML = "注意:不静音,视频可能会出现不会自动播放";
            configMute.appendChild(muteTip);

            configWrapper.appendChild(configMute);

            // 启用拖放
            var configDrag = document.createElement("div");
            configDrag.style.cssText = "border-bottom: 1px dotted #ccc ;padding-bottom: 5px;";
            var p = document.createElement("p");
            p.innerHTML = "启用拖放(慎用):";
            configDrag.appendChild(p);
            var inputDrag = document.createElement("input");
            inputDrag.type = "radio";
            inputDrag.name = "drag";
            inputDrag.value = "5";
            inputDrag.checked = drag === 5;
            inputDrag.onclick = function() {
                localStorage.setItem('drag', '5');
                player.changeConfig('config', 'timeScheduleAdjust', 5);
            }
            configDrag.appendChild(inputDrag);
            var labelDrag = document.createElement("label");
            labelDrag.innerHTML = "还原";
            configDrag.appendChild(labelDrag);
            var inputDrag2 = document.createElement("input");
            inputDrag2.type = "radio";
            inputDrag2.name = "drag";
            inputDrag2.value = "1";
            inputDrag2.checked = drag === 1;
            inputDrag2.onclick = function() {
                localStorage.setItem('drag', '1');
                player.changeConfig('config', 'timeScheduleAdjust', 1);
            }
            configDrag.appendChild(inputDrag2);
            var labelDrag2 = document.createElement("label");
            labelDrag2.innerHTML = "启用";
            configDrag.appendChild(labelDrag2);

            configWrapper.appendChild(configDrag);

            // 播放速度调整
            var configSpeed = document.createElement("div");
            configSpeed.style.cssText = "border-bottom: 1px dotted #ccc ;padding-bottom: 5px;";
            var p = document.createElement("p");
            p.innerHTML = "播放速度调整(慎用,不知后台是否检测):";
            configSpeed.appendChild(p);
            var inputSpeed = document.createElement("input");
            inputSpeed.type = "radio";
            inputSpeed.name = "speed";
            inputSpeed.value = "0";
            inputSpeed.checked = speed === 0;
            inputSpeed.onclick = function() {
                localStorage.setItem('speed', '0');
                player.changePlaybackRate(0);
            }
            configSpeed.appendChild(inputSpeed);
            var labelSpeed = document.createElement("label");
            labelSpeed.innerHTML = "低速";
            configSpeed.appendChild(labelSpeed);
            var inputSpeed2 = document.createElement("input");
            inputSpeed2.type = "radio";
            inputSpeed2.name = "speed";
            inputSpeed2.value = "1";
            inputSpeed2.checked = speed === 1;
            inputSpeed2.onclick = function() {
                localStorage.setItem('speed', '1');
                player.changePlaybackRate(1);
            }
            configSpeed.appendChild(inputSpeed2);
            var labelSpeed2 = document.createElement("label");
            labelSpeed2.innerHTML = "正常";
            configSpeed.appendChild(labelSpeed2);
            var inputSpeed3 = document.createElement("input");
            inputSpeed3.type = "radio";
            inputSpeed3.name = "speed";
            inputSpeed3.value = "2";
            inputSpeed3.checked = speed === 2;
            inputSpeed3.onclick = function() {
                localStorage.setItem('speed', '2');
                player.changePlaybackRate(2);
            }
            configSpeed.appendChild(inputSpeed3);
            var labelSpeed3 = document.createElement("label");
            labelSpeed3.innerHTML = "高速";
            configSpeed.appendChild(labelSpeed3);
            var inputSpeed4 = document.createElement("input");
            inputSpeed4.type = "radio";
            inputSpeed4.name = "speed";
            inputSpeed4.value = "3";
            inputSpeed4.checked = speed === 3;
            inputSpeed4.onclick = function() {
                localStorage.setItem('speed', '3');
                player.changePlaybackRate(3);
            }
            configSpeed.appendChild(inputSpeed4);
            var labelSpeed4 = document.createElement("label");
            labelSpeed4.innerHTML = "超高速";
            configSpeed.appendChild(labelSpeed4);
            var speedTip = document.createElement("div");
            speedTip.style.cssText = "font-size:13px;font-weight:bold;";
            speedTip.innerHTML = "提示:基于播放器本身的速度挡位实现,目测最高大概是2倍速。";
            configSpeed.appendChild(speedTip);
            configWrapper.appendChild(configSpeed);

            configDiv.appendChild(configWrapper);

            // 联系方式
            var contactDiv = document.createElement("div");
            contactDiv.style.cssText = "margin-top:10px;font-size:12px;font-weight:bold;line-height: 150%;";
            // 博客园地址
            var blogDiv = document.createElement("div");
            var blog = document.createElement("a");
            blog.href = "https://www.cnblogs.com/ykbb/";
            blog.target = "_blank";
            blog.innerHTML = "博客园地址";
            blogDiv.appendChild(blog);
            contactDiv.appendChild(blogDiv);

            // 意见反馈
            var feedbackDiv = document.createElement("div");
            var feedback = document.createElement("a");
            feedback.href = "https://msg.cnblogs.com/send/ykbb";
            feedback.target = "_blank";
            feedback.innerHTML = "点此意见反馈";
            feedbackDiv.appendChild(feedback);
            contactDiv.appendChild(feedbackDiv);

            configDiv.appendChild(contactDiv);

            document.body.appendChild(configDiv);
            // ==================页面设计结束==========================

            // 测试
            var testBtn = document.createElement("button");
            testBtn.style.position = "fixed";
            testBtn.style.left = "0";
            testBtn.style.top = "0";
            testBtn.innerHTML = "测试";
            // testBtn.style.display = "none";
            testBtn.onclick = function() {
                player.videoSeek(player.getMetaDate().duration - 2);
            }
            document.body.appendChild(testBtn);

            $("video").prop("muted", "muted");

            // 移除讨厌的事件
            window.onfocus = function() {};
            window.onblur = function() {};

            // 移除本课程学习完毕
            attrset.proxyUrl = "";

            function run() {
                // 总是显示播放进度
                player.changeControlBarShow(true);

                // 拖动开关
                player.changeConfig('config', 'timeScheduleAdjust', drag);

                if (mute) {
                    player.videoMute();
                } else {
                    player.videoEscMute();
                }

                player.changePlaybackRate(speed);

                if (autoplay) {
                    player.videoPlay();
                }
            }

            var tmp = setInterval(function() {
                if (player != undefined) {
                    player.addListener('loadedmetadata', run);
                    run();
                    clearInterval(tmp);

                    // 播放结束
                    player.addListener('ended', function() {
                        // 通知父窗体播放结束
                        window.parent.postMessage("ended", '*');
                    });
                }
            }, 500);
        });
    }
}