上海大学网站增强 - 刷课助手

<选课系统>1.第二、三轮选课自助刷课,解放双手。【人人有课刷,抵制卖课狗】 2.选课学期自动选择 3.选课排名页面标红排名超过额定人数的课程 4.学分完成情况页面,原始成绩换算绩点,选课学期可标红 5.所有存在显示课程号的页面,支持点击课程号查看课程介绍,右键直接复制课程号 <教务管理>1.教学评估页面可一键赋值,支持全部赋值和单行赋值 2.成绩查询页面在成绩未发布时自动刷新 3.移除主页企业微X广告 <健康之路>1.健康之路未读消息自动阅读 2.移除首页横幅广告

目前为 2022-09-02 提交的版本。查看 最新版本

作者
panghaibin
评分
0 0 0
版本
3.4.4
创建于
2021-10-29
更新于
2022-09-02
大小
21.8 KB
许可证
MIT
适用于

// ==UserScript== // @name 上海大学网站增强 - 刷课助手 // @namespace https://github.com/panghaibin/shu-web-js // @version 3.4.4 // @description <选课系统>1.第二、三轮选课自助刷课,解放双手。【人人有课刷,抵制卖课狗】 2.选课学期自动选择 3.选课排名页面标红排名超过额定人数的课程 4.学分完成情况页面,原始成绩换算绩点,选课学期可标红 5.所有存在显示课程号的页面,支持点击课程号查看课程介绍,右键直接复制课程号 <教务管理>1.教学评估页面可一键赋值,支持全部赋值和单行赋值 2.成绩查询页面在成绩未发布时自动刷新 3.移除主页企业微X广告 <健康之路>1.健康之路未读消息自动阅读 2.移除首页横幅广告 // @author panghaibin // @match ://xk.autoisp.shu.edu.cn/ // @match ://cj.shu.edu.cn/ // @match ://selfreport.shu.edu.cn/ // @grant none // @license MIT // @supportURL https://github.com/panghaibin/shu-web-js/issues // ==/UserScript==

(function () { 'use strict';

//--------刷课配置 开始--------
// 任意参数留空将不执行

// 输入课程号
let course_id = ''
// 输入对应的教师号
let teacher_id = ''
// 刷课间隔,默认 8000 ,单位毫秒 一般不需要修改
let delay_time = 8000
//--------刷课配置 结束--------

if (location.host === 'xk.autoisp.shu.edu.cn') {
    if (location.pathname === '/CourseSelectionStudent/PlanQuery') {
        plan_query_page();
    } else if (location.pathname === '/StudentQuery/QueryEnrollRank') {
        rclick_copy_course_id();
        red_rank();
    } else if (location.pathname === '/CourseSelectionStudent/FuzzyQuery'
        && course_id.length === 8 && teacher_id.length === 4 && delay_time > 0) {
        select_course_helper();
    } else if (location.pathname === '/Home/TermIndex' && location.search !== '?auto_select=0') {
        auto_select_term();
    } else if (location.pathname === '/StudentQuery/QueryCourse'
        || location.pathname === '/StudentQuery/QueryCourseTable'
        || location.pathname === '/StudentQuery/QueryDeleteCourse'
    ) {
        rclick_copy_course_id();
    }
    if (location.pathname !== '/Home/TermIndex') {
        manual_select_term();
        add_xk_footer();
    }
} else if (location.host === 'cj.shu.edu.cn') {
    if (location.pathname === '/StudentPortal/Evaluate') {
        evaluate_helper();
    } else if (location.pathname === '/Home/StudentIndex') {
        remove_cj_ad();
    } else if (location.pathname === '/StudentPortal/ScoreQuery') {
        auto_fresh_score();
    }
} else if (location.host === 'selfreport.shu.edu.cn') {
    if (location.pathname === '/Default.aspx' || location.pathname === '/') {
        remove_sr_ad();
    } else if (location.pathname === '/MyMessages.aspx') {
        read_all_msg();
    }
}

function score_conversion(item) {
    let score_num = item.innerText * 1;
    let score_raw = item.innerText;
    if (score_raw.length > 0) {
        if (score_num >= 90 && score_num <= 100 || score_raw === "A") {
            item.innerText = score_raw + ' / 4.0';
        } else if (score_num >= 85 && score_num <= 89.9 || score_raw === "A-") {
            item.innerText = score_raw + ' / 3.7';
        } else if (score_num >= 82 && score_num <= 84.9 || score_raw === "B+") {
            item.innerText = score_raw + ' / 3.3';
        } else if (score_num >= 78 && score_num <= 81.9 || score_raw === "B") {
            item.innerText = score_raw + ' / 3.0';
        } else if (score_num >= 75 && score_num <= 77.9 || score_raw === "B-") {
            item.innerText = score_raw + ' / 2.7';
        } else if (score_num >= 72 && score_num <= 74.9 || score_raw === "C+") {
            item.innerText = score_raw + ' / 2.3';
        } else if (score_num >= 68 && score_num <= 71.9 || score_raw === "C") {
            item.innerText = score_raw + ' / 2.0';
        } else if (score_num >= 66 && score_num <= 67.9 || score_raw === "C-") {
            item.innerText = score_raw + ' / 1.7';
        } else if (score_num >= 64 && score_num <= 65.9 || score_raw === "D") {
            item.innerText = score_raw + ' / 1.5';
        } else if (score_num >= 60 && score_num <= 63.9 || score_raw === "D-") {
            item.innerText = score_raw + ' / 1.0';
        } else if ((score_num >= 0 && score_num <= 59.9 || score_raw === "F")) {
            item.innerText = score_raw + ' / 0.0';
        } else if (score_raw === "P" || score_raw === "L") {
            item.innerText = score_raw + ' / 不计';
        }
        // 标红压线绩点 暂时不使用
        // if (score_num === 89 || score_num === 84 || score_num === 81 || score_num === 77 || score_num === 74 ||
        //     score_num === 71 || score_num === 67 || score_num === 65 || score_num === 63 || score_num === 59) {
        //     item.style.color = 'red';
        // }
    }
}

function red_rank() {
    let elements;
    elements = document.getElementsByName('rowclass');
    for (let i = 0; i < elements.length; ++i) {
        let row = elements[i];
        let room = row.children[4].innerText * 1;
        let _rank = row.children[6].innerText.split('-');
        let rank = _rank[_rank.length - 1] * 1;
        if (rank > room) {
            for (let j = 0; j < row.children.length; ++j) {
                elements[i].children[j].style.color = 'red';
                elements[i].children[j].style.fontWeight = 'bold';
            }
        }
    }
}

function select_course_helper() {
    document.getElementsByName('CID')[0].defaultValue = course_id;
    document.getElementsByName('TeachNo')[0].defaultValue = teacher_id;
    let i = 0;
    let select_id = setInterval(function () {
        document.getElementById('QueryAction').click();
        setTimeout(function () {
            let tbllist = document.getElementsByClassName('tbllist');
            let room = tbllist[0].children[0].children[1].children[9].innerText * 1;
            let num = tbllist[0].children[0].children[1].children[10].innerText * 1;
            console.log('第' + ++i + '次 课程号' + course_id + ' 教师号' + teacher_id + ' 容量' + room + ' 人数' + num);
            if (room > num) {
                tbllist[0].children[0].children[1].children[0].children[0].checked = true;
                document.getElementById('CourseCheckAction').click();
                let across_campus = document.getElementById('NotCollegeAction');
                if (across_campus != null) {
                    setTimeout(function () {
                        across_campus.click();
                    }, 1000);
                }
                tbllist = document.getElementsByClassName('tbllist');
                let callback_msg = tbllist[1].children[0].children[1].children[5].innerText
                if (callback_msg.includes('成功')) {
                    clearInterval(select_id);
                } else {
                    // 关闭选课失败的窗口
                    CloseDialog('divOperationResult');
                }
                console.log(callback_msg);
            }
        }, 1000);
    }, delay_time);
}

function evaluate_helper() {
    let tbllist = document.getElementsByClassName('tbllist');
    let th = document.createElement('TH');
    th.innerText = '一键评估';
    let heading = tbllist[0].children[0].children[0];
    heading.insertBefore(th, heading.children[4]);

    let evaluate_list = ['结果', '非常大', '比较大', '一般', '很少'];
    let course_count = tbllist[0].children[0].childElementCount - 2;
    for (let i = 1; i <= course_count; ++i) {
        let select = document.createElement('SELECT');
        select.style.backgroundColor = '#ffc';
        for (let j = 0; j < evaluate_list.length; j++) {
            let option = document.createElement('OPTION');
            option.innerText = evaluate_list[j];
            option.value = j;
            if (j === 0) {
                option.innerText = '单行' + option.innerText;
                option.selected = true;
            }
            select.appendChild(option);
        }
        select._params = {'row': i - 1};
        select.addEventListener('change', function () {
            let row = event.target._params['row']
            for (let j = 0; j < 4; ++j) {
                let evaluate_name = 'classlist[' + row + '].ItemValue[' + j + ']';
                let raw_select = document.getElementsByName(evaluate_name);
                raw_select[0].children[this.value].selected = true;
            }
        }, false);
        let td = document.createElement('TD');
        td.appendChild(select);
        let cource = tbllist[0].children[0].children[i];
        cource.insertBefore(td, cource.children[4]);
    }

    let all_select = document.createElement('SELECT');
    all_select.style.backgroundColor = '#ffc';
    all_select.style.marginRight = '15px';
    for (let i = 0; i < evaluate_list.length; i++) {
        let option = document.createElement('OPTION');
        option.innerText = evaluate_list[i];
        option.value = i;
        if (i === 0) {
            option.innerText = '全部' + option.innerText;
            option.selected = true;
        }
        all_select.appendChild(option);
    }
    all_select.addEventListener('change', function () {
        let selects = document.getElementsByTagName('SELECT');
        for (let i = 0; i < selects.length; ++i) {
            selects[i].children[this.value].selected = true;
        }
    }, false);
    let row = tbllist[0].children[0].children;
    let last_row = row[row.length - 1].children[0].children[0];
    let save_btn = last_row.children[0];
    last_row.insertBefore(all_select, save_btn);
}

function remove_cj_ad() {
    document.getElementsByClassName('div_master_content')[0].remove();
}

function auto_select_term() {
    let term_list = document.getElementsByName('rowterm');
    document.getElementById('termId').value = term_list[term_list.length - 1].getAttribute('value');
    document.getElementsByTagName('button')[0].click();
}

function manual_select_term() {
    let menu = document.querySelector('.term-menu');
    if (menu !== null) {
        let a_tag = menu.getElementsByTagName('a')[0];
        a_tag.href = a_tag.href + '?auto_select=0';
    }
}

function add_xk_footer() {
    setInterval(() => {
        let footer = document.getElementsByClassName('main-footer')[0];
        if (typeof (footer) !== "undefined") {
            let footer_div = footer.children[1];
            if (!footer_div.innerHTML.includes('刷课助手')) {
                let skzs = document.createElement('A');
                skzs.innerText = '刷课助手已加载';
                skzs.href = 'https://gf.qytechs.cn/zh-CN/scripts/434613';
                skzs.target = '_blank';
                footer_div.innerHTML = footer_div.innerHTML + ' - ' + skzs.outerHTML;
            }
        }
    }, 0)
}

function remove_sr_ad() {
    document.getElementsByClassName('pic slick-initialized slick-slider')[0].remove();
    document.getElementById('countdown').remove();
}

function read_all_msg() {
    // 为了兼容 Firefox
    let tips_interval = setInterval(function () {
        let tips = document.getElementsByClassName('f-panel-title-text')[0];
        if (typeof (tips) !== "undefined") {
            tips.innerText = '即将开始自动阅读所有未读消息【点击此处停止】';
            let msg_list = document.getElementsByClassName('f-datalist-list')[0];
            let i = 0;
            let unread_count = 0;
            let interval_id = setTimeout(function () {
                interval_id = setInterval(function () {
                    tips.innerText = '【点击停止】正在检索第' + (i + 1) + '条消息';
                    if (i < msg_list.childElementCount) {
                        let msg_item = msg_list.children[i].children[0];
                        let msg_title = msg_item.children[0];
                        let msg_url = msg_item.href;
                        if (msg_title.style.color !== '') {
                            let xhr = new XMLHttpRequest();
                            xhr.open('GET', msg_url);
                            xhr.send(null);

                            msg_title.innerText = msg_title.innerText.replace('(未读)', '');
                            tips.innerText = '【点击停止】' + msg_title.innerText;
                            msg_title.style = '';
                            unread_count++;
                        }
                    } else {
                        clearInterval(interval_id);
                        tips.innerText = '自动阅读所有未读消息完成,共' + unread_count + '条';
                    }
                    ++i;
                }, 0);
            }, 1000);
            tips.onclick = function () {
                clearInterval(interval_id);
                tips.innerText = '已停止,刷新继续';
            }
            clearInterval(tips_interval);
        }
    }, 1);
}

function get_current_grade_term() {
    let term_name = document.getElementsByClassName('dropdownterm')[0].children[0].children[1].innerText;
    let term_year = /(\d{2})学年/.exec(term_name)[1] * 1;
    let term_type = /(.)季学期/.exec(term_name)[1];
    let id_num = document.getElementsByClassName('nav-function-text')[0].innerText;
    let enroll_year = /(\d{2})\d{6}/.exec(id_num)[1] * 1;
    let term_list = {'秋': 1, '冬': 2, '春': 3, '夏': 4};
    let term_num = term_list[term_type];
    let grade_num = term_year - enroll_year;
    return {'class': 'gt-' + grade_num + term_num, 'grade': grade_num, 'term': term_num};
}

function onchange_grade_term_select() {
    let all_gt = document.getElementsByClassName('gt');
    for (let i = 0; i < all_gt.length; i++) {
        all_gt[i].style.color = '';
    }
    let grade_choice = document.getElementsByClassName('grade-select')[0].value;
    let term_choice = document.getElementsByClassName('term-select')[0].value;
    let choice_gt = document.getElementsByClassName('gt-' + grade_choice + term_choice);
    for (let i = 0; i < choice_gt.length; i++) {
        choice_gt[i].style.color = 'red';
    }
}

function plan_query_page() {
    let grade_list = {'一': 1, '二': 2, '三': 3, '四': 4, '五': 5};
    let term_list = {'秋': 1, '冬': 2, '春': 3, '夏': 4};
    let td_list = document.getElementsByTagName('TD');
    for (let i = 0; i < td_list.length; i++) {
        if (td_list[i].innerText.includes('学期')) {
            td_list[i].innerHTML = td_list[i].innerHTML.replaceAll(/(.)年级(.)季学期/g,
                function ($0, $1, $2) {
                    let span = document.createElement('SPAN');
                    span.className = 'gt gt-' + grade_list[$1] + '0 gt-' + grade_list[$1] + term_list[$2];
                    span.innerText = $0;
                    return span.outerHTML;
                });
        } else if (is_cource_id_td(td_list[i])) {
            edit_cource_id_td(td_list[i]);
        } else if (typeof (td_list[i].attributes.name) !== "undefined"
            && ['tdscorecnotpass', 'tdscore', 'tdscorecpass'].includes(td_list[i].attributes.name.value)) {
            score_conversion(td_list[i]);
        }
    }

    let reverse_grade_list = {1: '一', 2: '二', 3: '三', 4: '四', 5: '五'};
    let reverse_term_list = {1: '秋季', 2: '冬季', 3: '春季', 4: '夏季', 0: '全部'};
    let current_grade_term = get_current_grade_term();

    let grade_select = document.createElement('SELECT');
    grade_select.className = 'grade-select';
    grade_select.style.backgroundColor = '#ffc';
    grade_select.addEventListener('change', onchange_grade_term_select);
    let grade_val = current_grade_term['grade'];
    for (let i = 1; i <= 5; i++) {
        let option = document.createElement('OPTION');
        option.innerText = reverse_grade_list[i] + '年级';
        option.value = i;
        if (grade_val === i) {
            option.selected = true;
        }
        grade_select.appendChild(option);
    }

    let term_select = document.createElement('SELECT');
    term_select.className = 'term-select';
    term_select.style.backgroundColor = '#ffc';
    term_select.addEventListener('change', onchange_grade_term_select);
    let term_val = current_grade_term['term'];
    for (let i = 0; i <= 4; i++) {
        let option = document.createElement('OPTION');
        option.innerText = reverse_term_list[i] + '学期';
        option.value = i;
        if (term_val === i) {
            option.selected = true;
        }
        term_select.appendChild(option);
    }

    let th_list = document.getElementsByTagName('TH');
    for (let i = 0; i < th_list.length; i++) {
        if (th_list[i].innerText.includes('教学计划')) {
            th_list[i].appendChild(grade_select);
            th_list[i].appendChild(term_select);
            break;
        }
    }

    let gt_class = document.getElementsByClassName(current_grade_term['class']);
    for (let i = 0; i < gt_class.length; i++) {
        gt_class[i].style.color = 'red';
    }
}

function fresh_score(interval_id) {
    let score_table = document.getElementById('divList');
    if (score_table.innerText.includes('学号') && !score_table.innerText.includes('未提交')) {
        if (interval_id !== null) {
            let title = '成绩已发布';
            blink_title(title);
            clearInterval(interval_id);
        }
        return false;
    } else if (score_table.innerText.includes('评估')) {
        let title = '成绩已发布,教学评估完成后可查看';
        blink_title(title);
        clearInterval(interval_id);
        return false;
    } else {
        score_table.innerHTML = score_table.innerHTML + '<br>8秒后自动刷新';
        return true;
    }
}

function auto_fresh_score() {
    let interval_id = null;
    if (fresh_score(interval_id)) {
        let i = 0;
        interval_id = setInterval(function () {
            document.title = '已刷新' + ++i + '次成绩';
            document.getElementsByTagName('INPUT')[0].click();
            setTimeout(fresh_score, 2000, interval_id);
        }, 8000);
    }
}

function rclick_copy_course_id() {
    setInterval(function () {
        let td_list = document.getElementsByTagName('TD');
        for (let i = 0; i < td_list.length; i++) {
            if (is_cource_id_td(td_list[i])) {
                edit_cource_id_td(td_list[i]);
            }
        }
    }, 500);
}

function is_cource_id_td(item) {
    return item.innerText.length === 8 && /\d.{6}\d/.test(item.innerText);
}

function edit_cource_id_td(item) {
    let course_id = item.innerText;
    item.className = 'course-id';
    item.style.cursor = 'pointer';
    item.title = '点击查看课程简介,右键复制课程号';
    item.oncontextmenu = function (e) {
        e.preventDefault();
        copy_to_clipboard(course_id)
            .then(() => toast_msg(item, '已复制'))
            .catch(() => toast_msg(item, '复制失败'));
    }
    item.onclick = function () {
        window.open("../DataQuery/QueryCourseIntro?courseNo=" + course_id);
    }
}

function copy_to_clipboard(text) {
    // From https://stackoverflow.com/a/65996386
    if (navigator.clipboard && window.isSecureContext) {
        return navigator.clipboard.writeText(text);
    } else {
        let textArea = document.createElement("textarea");
        textArea.value = text;
        textArea.style.position = "fixed";
        textArea.style.left = "-999999px";
        textArea.style.top = "-999999px";
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        return new Promise((res, rej) => {
            document.execCommand('copy') ? res() : rej();
            textArea.remove();
        });
    }
}

function toast_msg(item, msg) {
    let toast = document.createElement('span');
    toast.className = 'toast';
    toast.style.fontSize = '0.8em';
    toast.innerText = '\n' + msg;
    item.appendChild(toast);
    setTimeout(function () {
        toast.remove();
    }, 500);
}

function blink_title(title_text, times = 0) {
    let space = ('—').repeat(title_text.length);
    if (times === 0) {
        document.title = space;
    } else if (times === 1) {
        document.title = title_text;
    }
    times = (times + 1) % 2;
    setTimeout(function () {
        blink_title(title_text, times);
    }, 800);
}

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址