Ralap_X / ZUST抢课脚本(魔改版)

// ==UserScript==
// @name ZUST抢课脚本(魔改版)
// @namespace none
// @version 0.0.1
// @description 用于浙江科技大学抢课
// @author Ralap_X
// @match *://*newjwxt-443.webvpn.zust.edu.cn/*
// @icon https://tiebapic.baidu.com/forum/w%3D120%3Bh%3D120/sign=5a3b4b849758ccbf1bbcb13829e3d403/b8014a90f603738d4092ee14f51bb051f819ec29.jpg?tbpicau=2024-01-08-05_253f3b8d5cec85018f3a3d87bb8e77e5
// @grant none
// @license MIT
// ==/UserScript==




(function () {
    //如果要多选课程对象,请从dataobjarr的第二个对象开始填起,因为第一个对象是在网页弹出的窗口上保存的
    let dataobjarr = [{
        targetTeacher: "",
        targetTime: "",
        firstmenu: "",
        secondmenu: ""
    }, {
        //这里写上你要选的课程的教师
        targetTeacher: "",
        //这里写上你要选的课程的时间,格式要和下面的一样(就是从我们的选课网站上复制黏贴下来的那个)
        targetTime: "",
        //这里写上一级菜单的名称(无需全名,只需要其中一部分即可)
        firstmenu: "",
        //这里写上二级菜单的名称(不要包含进去前面的课程代码,就是你鼠标悬浮上去,下面会有下划线的那部分复制过来)
        secondmenu: ""
    }];

    //此处是一些公共变量
    let draggableBox;


    //公共函数
    function TextAlert(content) {
        if (draggableBox.querySelector('.isok').classList.contains('graberror')) {
            draggableBox.querySelector('.isok').classList.remove('graberror')
        }
        if (draggableBox.querySelector('.isok').classList.contains('grabsuccess')) {
            draggableBox.querySelector('.isok').classList.remove('grabsuccess')
        }
        draggableBox.querySelector('.isok').textContent = content;

        draggableBox.querySelector('.isok').style.visibility = 'visible';
    }

    function TextError(content) {
        draggableBox.querySelector('.isok').textContent = content;
        draggableBox.querySelector('.isok').style.visibility = 'visible';
        draggableBox.querySelector('.isok').classList.add('graberror');
    }

    function TextSuccess(content) {
        draggableBox.querySelector('.isok').textContent = content;
        draggableBox.querySelector('.isok').style.visibility = 'visible';
        draggableBox.querySelector('.isok').classList.add('grabsuccess');
    }


    //添加相关图形化界面的代码
    (function () {
        const style = document.createElement('style');
        style.textContent =
            `
        .grabclasscontainer {
            width: 350px;
            text-align: center;
            position: fixed;
            right: 0px;
            bottom: 0px;
            height: 350px;
            border: 2px #333 solid;
            background-color: #d5e8fc;
            z-index: 999;
        }

        .grabclasscontainer .form-group {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 10px;
        }

        .grabclasscontainer label {
            flex: 1;
            text-align: right;
            margin-right: 10px;
        }

        .grabclasscontainer input {
            flex: 2;
            padding: 10px;
            width: 100%;
        }

        .grabclasscontainer .submit {
            background-color: #007bff;
            color: #fff;
            padding: 10px 20px;
            border: none;
            cursor: pointer;
            margin-bottom: 10px;
        }

        .grabclasscontainer .clear {
            background-color: #79240c;
            color: #fff;
            padding: 10px 20px;
            border: none;
            cursor: pointer;
            margin-bottom: 6px;
        }

        .grabclasscontainer .dragBar {
            height: 30px;
            line-height: 30px;
            background-color: #505860;
            cursor: move;
            margin-bottom: 9px;
        }

        .grabclasscontainer .isok {
            visibility: hidden;
            margin-bottom: 20px;
        }

        .grabclasscontainer .content {
            overflow-y: auto;
            height: 309px;
        }

        .grabclasscontainer .copyright {
            text-align: left;
        }

        .grabclasscontainer .graberror {
            color: #e91a0b;
        }

        .grabclasscontainer .grabsuccess {
            color: #0be94e;
        }
        `
        document.head.appendChild(style);


        const grabclasscontainer = document.createElement('div');
        grabclasscontainer.className = 'grabclasscontainer';
        grabclasscontainer.id = 'grabclasscontainer';
        grabclasscontainer.innerHTML = `
        <div class="dragBar" id="dragBar">
            🥵拖动框小姐🥵
        </div>
        <div class="content">
            <form id="DataForm">
                <div class="form-group">
                    <label for="teacher">老师:</label>
                    <input type="text" id="teacher" name="teacher" placeholder="杨轩昂" required autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="time">时间:</label>
                    <input type="text" id="time" name="time" placeholder="星期三第3-5节{1-2周,4-15周}" required
                        autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="category1">一级目录:</label>
                    <input type="text" id="category1" name="category1" placeholder="通识选修课" required autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="category2">二级目录:</label>
                    <input type="text" id="category2" name="category2" placeholder="马克思主义基本原理" required
                        autocomplete="off">
                </div>
                <button type="submit" class="submit">确定</button>
            </form>
            <button class="clear">停止</button>
            <div class="isok">提交成功,正在抢课</div>
            <div class="copyright">
                【基本使用方式】“老师”黏贴课程教师,如"楼伟纲"<br>
                “时间”黏贴课程时间,如“星期三第3-5节{1-2周,4-15周}”,如果课程的时间有两行,那么只需要黏贴其中的任意一行即可<br>
                “一级目录”黏贴课程大类,如“通识选修课”<br>
                “二级目录”黏贴课程小类,如"马克思主义基本原理"(鼠标悬浮有下划线的部分)<br><br>
                【进阶使用方式】如何实现多选课程?<br>
                打开代码,找到dataobjarr这个对象数组,按照注释填写相关信息<br>
                若要再选多个,只需于数组中继续定义对象<br><br>
                本脚本使用JS代码操作DOM元素,并未使用任何非法hack手段。<br>
            </div>
        </div>
        `
        document.body.appendChild(grabclasscontainer);


        draggableBox = document.getElementById("grabclasscontainer");
        const dragBar = draggableBox.querySelector(".dragBar");
        let isDragging = false;
        let offsetX, offsetY;

        dragBar.addEventListener("mousedown", (e) => {
            isDragging = true;
            offsetX = e.clientX - draggableBox.getBoundingClientRect().left;
            offsetY = e.clientY - draggableBox.getBoundingClientRect().top;
            draggableBox.style.transition = "none";
        });

        document.addEventListener("mousemove", (e) => {
            if (!isDragging) return;
            let x = e.clientX - offsetX;
            let y = e.clientY - offsetY;
            draggableBox.style.left = x + "px";
            draggableBox.style.top = y + "px";
        });

        document.addEventListener("mouseup", () => {
            isDragging = false;
            draggableBox.style.transition = "all 0.3s ease"; // 添加平滑的过渡效果
        });


        const DataForm = document.querySelector('#DataForm');
        DataForm.addEventListener('submit', function (event) {
            event.preventDefault(); // 阻止默认提交行为
            // 获取表单输入的值
            dataobjarr[0].targetTeacher = document.querySelector('#teacher').value;
            dataobjarr[0].targetTime = document.querySelector('#time').value;
            dataobjarr[0].firstmenu = document.querySelector('#category1').value;
            dataobjarr[0].secondmenu = document.querySelector('#category2').value;
            localStorage.setItem('targetTeacher', dataobjarr[0].targetTeacher);
            localStorage.setItem('targetTime', dataobjarr[0].targetTime);
            localStorage.setItem('firstmenu', dataobjarr[0].firstmenu);
            localStorage.setItem('secondmenu', dataobjarr[0].secondmenu);
            TextAlert('正在抢课');
            location.reload();
            // 执行您的操作,使用上述变量的值
            console.log(`老师: ${dataobjarr[0].targetTeacher}, 时间: ${dataobjarr[0].targetTime}, 一级目录: ${dataobjarr[0].firstmenu}, 二级目录: ${dataobjarr[0].secondmenu}`);
        });
        draggableBox.querySelector('.clear').addEventListener('click', () => {
            localStorage.removeItem('targetTeacher');
            localStorage.removeItem('targetTime');
            localStorage.removeItem('firstmenu');
            localStorage.removeItem('secondmenu');
            TextAlert('停止抢课');
        });
    })();
    //选课相关代码
    (function () {
        let nowdataobj;
        let nowi = 0;
        function getfirstmenu() {
            let issuccess = false;
            const liElements = document.querySelectorAll('.nav-tabs li')
            liElements.forEach(li => {
                const aElement = li.querySelector('a');
                if (aElement && aElement.textContent.includes(nowdataobj.firstmenu)) {
                    issuccess = true;
                    if (!li.classList.contains('active')) {
                        aElement.click();
                    }
                    TextAlert(`查询按钮`);
                    setTimeout(clickquerrybtn, 2000);
                }
            });
            if (issuccess === false) {
                TextError(`错误:找不到一级目录  ${nowdataobj.firstmenu}  ,请核对填写的是否正确`);
            }
        }

        function clickquerrybtn() {
            const querrybtn = document.querySelector('button[name="query"]');
            if (querrybtn) {
                querrybtn.click();
                TextAlert(`更多按钮`);
                setTimeout(getmore, 2000);
            }
        }

        function getmore() {
            const more = document.querySelector('#more');
            if (more.style.display !== 'none') {
                more.querySelector('a').click();
                setTimeout(getmore, 2000);
            } else {
                TextAlert(`二级目录    ${nowdataobj.secondmenu}`);
                setTimeout(getsecondmenu, 2000);
            }
        }

        function getsecondmenu() {
            let issuccess = false;
            const tjxk = document.querySelector('.tjxk_list');
            const liElements = tjxk.querySelectorAll('.panel.panel-info');
            liElements.forEach(li => {
                const clickbox = li.querySelector('.panel-heading.kc_head');
                const secondmenuname = clickbox.querySelector('.kcmc a').textContent;
                if (clickbox && secondmenuname && nowdataobj.secondmenu.includes(secondmenuname)) {
                    issuccess = true;
                    if (clickbox.querySelector('.expand_close').classList.contains('expand1')) {
                        clickbox.click();
                    }
                    TextAlert(`老师${nowdataobj.targetTeacher}   时间${nowdataobj.targetTime}`);
                    setTimeout(findtarget, 2000);
                }
            }
            )
            if (issuccess === false) {
                TextError(`错误:找不到二级目录  ${nowdataobj.secondmenu}  ,请核对二级目录填写的是否正确`);
            }
        }
        function findtarget() {
            let issuccess = false;
            const rows = document.querySelectorAll('.body_tr');
            rows.forEach(row => {
                const teacherCell = row.querySelector('.jsxmzc').textContent;
                const timeCell = row.querySelector('.sksj').textContent;
                if (teacherCell.includes(nowdataobj.targetTeacher) && timeCell.includes(nowdataobj.targetTime)) {
                    issuccess = true;
                    const button = row.querySelector('.btn');
                    if (button) {
                        if (button.textContent === '选课') {
                            button.click();
                            setTimeout(clicksurebtn, 2000);
                        } else if (button.textContent === '退选') {
                            TextSuccess(`课程 ${nowdataobj.secondmenu} 已成功选上`);
                            setTimeout(reloadpage, 2000);
                        }
                    }
                }
            });
            if (issuccess === false) {
                TextError(`错误:找不到课程,请检查老师  ${nowdataobj.targetTeacher}  和时间  ${nowdataobj.targetTime}  填写的是否正确`);
            }
        }

        function clicksurebtn() {
            const confirmButton = document.getElementById('btn_ok');
            if (confirmButton) {
                confirmButton.click();
            }
            setTimeout(reloadpage, 2000);
        }

        function reloadpage() {
            nowi++;
            if (nowi >= dataobjarr.length) {
                location.reload();
            } else {
                start();
            }
        }

        function start() {
            if (nowi === 0 && !(dataobjarr[nowi].targetTeacher && dataobjarr[nowi].targetTime && dataobjarr[nowi].firstmenu && dataobjarr[nowi].secondmenu)) {
                dataobjarr[nowi].targetTeacher = localStorage.getItem('targetTeacher');
                dataobjarr[nowi].targetTime = localStorage.getItem('targetTime');
                dataobjarr[nowi].firstmenu = localStorage.getItem('firstmenu');
                dataobjarr[nowi].secondmenu = localStorage.getItem('secondmenu');
            }
            if (dataobjarr[nowi].targetTeacher && dataobjarr[nowi].targetTime && dataobjarr[nowi].firstmenu && dataobjarr[nowi].secondmenu) {
                nowdataobj = dataobjarr[nowi];
                TextAlert(`一级菜单   ${nowdataobj.firstmenu}`);
                setTimeout(getfirstmenu, 2000);
            } else {
                if (nowi === 0) {
                    TextAlert('请按照提示输入相关内容');
                } else {
                    location.reload();
                }
            }
        }

        start();
    })();

})();