Convenient SZU

【使用前先看介绍/有问题可反馈】便捷深大 (Convenient SZU):适配深圳大学内部网多个网页的辅助脚本。内部网首页左上角增加 `宿舍用电查询/校园网络续费/登录(不可用)Dr.com/体育场馆预订/百度文库/下载专区/师资队伍` 入口,免去进入 `Blackboard/学业完成查询/办事大厅卡片` 的繁琐步骤,自动登录(不可用) `Blackboard/办事大厅/Dr.com/校园网络续费` 等页面,自动填写需要登陆的页面的账号密码,【办事大厅】页面增加【修读课程统计下载】,【网上评教】页面增加【一键五星+评价】,【成长记录】页面增加【学期专业排名】,【学业完成查询】页面增加【彩虹地毯】,【宿舍用电查询】可自动记忆填写的宿舍信息并可自动显示近 20 天用电记录。

当前为 2021-03-10 提交的版本,查看 最新版本

// ==UserScript==
// @name            Convenient SZU
// @namespace       http://tampermonkey.net/
// @version         1.0.0
// @description     【使用前先看介绍/有问题可反馈】便捷深大 (Convenient SZU):适配深圳大学内部网多个网页的辅助脚本。内部网首页左上角增加 `宿舍用电查询/校园网络续费/登录(不可用)Dr.com/体育场馆预订/百度文库/下载专区/师资队伍` 入口,免去进入 `Blackboard/学业完成查询/办事大厅卡片` 的繁琐步骤,自动登录(不可用) `Blackboard/办事大厅/Dr.com/校园网络续费` 等页面,自动填写需要登陆的页面的账号密码,【办事大厅】页面增加【修读课程统计下载】,【网上评教】页面增加【一键五星+评价】,【成长记录】页面增加【学期专业排名】,【学业完成查询】页面增加【彩虹地毯】,【宿舍用电查询】可自动记忆填写的宿舍信息并可自动显示近 20 天用电记录。
// @author          cc
// @match           https://elearning.szu.edu.cn/*
// @match           https://authserver.szu.edu.cn/*
// @match           https://drcom.szu.edu.cn/*
// @match           https://self.szu.edu.cn/*
// @match           https://www1.szu.edu.cn/*
// @match           http://ehall.szu.edu.cn/*
// @match           http://bkxk.szu.edu.cn/*
// @match           172.30.255.2/*
// @match           http://192.168.84.3:9090/cgcSims/*
// @grant           GM_setValue
// @grant           GM_getValue
// @require         https://cdn.bootcss.com/jquery/3.4.1/jquery.js
// @require         https://gf.qytechs.cn/scripts/418193-coder-utils.js
// @noframes
// ==/UserScript==

(function() {
    'use strict';
    // 在此修改您的账号密码
    var CARD_ID = 'Your card id';
    var STUDENT_ID = 'Your student id';
    var PASSWORD = 'Your password';
    // 往后的代码不需要修改
    var account = GM_getValue('account');
    if (account) {
        if (CARD_ID != 'Your card id' && STUDENT_ID != 'Your student id' && PASSWORD != 'Your password' && (CARD_ID != account.CARD_ID || STUDENT_ID != account.STUDENT_ID || PASSWORD != account.PASSWORD)) {
            GM_setValue('account', {
                'CARD_ID': CARD_ID,
                'STUDENT_ID': STUDENT_ID,
                'PASSWORD': PASSWORD,
            });
            account = GM_getValue('account');
        };
    } else {
        if (CARD_ID == 'Your card id' || STUDENT_ID == 'Your student id' || PASSWORD == 'Your password') {
            alert('【来自 Convenient SZU】:\n欢迎使用 Convenient SZU\n为了后续自动登录(不可用),接下来会出现弹窗需要你输入特定信息\n你的信息只会保存在本地,因此请放心填写');
            CARD_ID = prompt('请输入六位数字的卡号:');
            while (!CARD_ID || !CARD_ID.match(/^\d{6}$/))
                CARD_ID = prompt('请输入合法的六位数字的卡号:');
            STUDENT_ID = prompt('请输入十位数字的学号:');
            while (!STUDENT_ID || !STUDENT_ID.match(/^\d{10}$/))
                STUDENT_ID = prompt('请输入合法的十位数字的学号:');
            PASSWORD = prompt('请输入统一认证登录(不可用)密码:');
            while (!PASSWORD)
                PASSWORD = prompt('请输入合法的统一认证登录(不可用)密码:');
            alert('你的信息已经填写完毕,若信息需要修改,请重新安装脚本,或前往 Tampermonkey 的脚本管理页面对该脚本进行编辑,代码中会有注释指引你进行修改。');
        };
        GM_setValue('account', {
            'CARD_ID': CARD_ID,
            'STUDENT_ID': STUDENT_ID,
            'PASSWORD': PASSWORD,
        });
        account = GM_getValue('account');
    };
    CARD_ID = account.CARD_ID;
    STUDENT_ID = account.STUDENT_ID;
    PASSWORD = account.PASSWORD;
    function run () {
        if (location.host == 'elearning.szu.edu.cn') {
            if (location.href == 'https://elearning.szu.edu.cn/' || location.href == 'https://elearning.szu.edu.cn/webapps/login/') {
                let span = document.querySelector('table table table tr td a span');
                if (span) {
                    span.click();
                };
            } else if (location.href.includes('webapps/portal/')) {
                let observer = document.body.$monitor({ childList: true }, (events) => {
                    for (let event of events) {
                        for (let node of event.addedNodes) {
                            if (node instanceof HTMLElement && node.classList.contains('lb-wrapper')) {
                                (function rec () {
                                    let agree_button = node.querySelector('#agree_button');
                                    if (agree_button) {
                                        agree_button.click();
                                        observer.disconnect();
                                    } else {
                                        setTimeout(rec, 50);
                                    };
                                })();
                            };
                        };
                    };
                });
            };
        } else if (location.host == 'authserver.szu.edu.cn') {
            let username = document.getElementById('username');
            let password = document.getElementById('password');
            let captchaResponse = document.querySelector('p#cpatchaDiv #captchaResponse');
            let button = document.querySelector('button');
            if (username && password && button && !captchaResponse) {
                username.value = CARD_ID;
                password.value = PASSWORD;
                button.click();
            };
        } else if (location.host == 'ehall.szu.edu.cn') {
            function setfunc () {
                function courseClassSorted(courses) {
                    function getCourseClassPriority(course) {
                        let priority = ['基本通识', '专业核心', '专业限选', '专业选修', '扩展通识', '自然科学', '生命科学', '社会科学', '中华文化', '人文艺术', '创新创业', '个性课程', '基本实践'];
                        for (let i = 0; i < priority.length; i++)
                            if (course.indexOf(priority[i]) >= 0)
                                return i;
                        return priority.length;
                    };
                    let courseInfo = courses.map(c => {
                        return {
                            course: c,
                            priority: getCourseClassPriority(c),
                        };
                    });
                    return courseInfo.$sorted('priority').$map('course');
                };
                function exec() {
                    $.ajax({
                        method: 'POST',
                        url: 'http://ehall.szu.edu.cn/jwapp/sys/xywccx/modules/xywccx/cxscfakz.do',
                        data: {
                            BYNJDM: '-',
                        },
                    }).then(res => {
                        let extendedCourseClasses = ['自然科学类', '生命科学类', '社会科学类', '中华文化类', '人文艺术类', '创新创业类'];
                        let numChinese = ['一', '二', '三', '四', '五', '六', '七', '八'];
                        let courseClassesObj = res.datas.cxscfakz.rows;
                        courseClassesObj = courseClassesObj.$map(['KZM', 'KZH', 'PYFADM', 'YQXF', 'WCXF', 'YQMS', 'WCMS', 'YQWCKZS', 'WCKZS', 'FKZH']);
                        let allCourseClasses = courseClassesObj.filter(c => c.FKZH !== '-1').$map('KZM');
                        let statCourseClasses = allCourseClasses.filter(c => !extendedCourseClasses.includes(c));
                        let extendedCourseClass = allCourseClasses.$where(c => c.indexOf('扩展通识') >= 0, true);
                        let cmap = Object.fromEntries([[extendedCourseClass, courseClassesObj.$where(c => c.KZM.indexOf('扩展通识') >= 0, true)]]);
                        allCourseClasses = allCourseClasses.filter(c => c.indexOf('扩展通识') < 0);
                        let recommendClasses = statCourseClasses.filter(c => c.indexOf('个性课程') < 0);
                        courseClassesObj = courseClassesObj.filter(c => allCourseClasses.includes(c.KZM) && c.FKZH !== '-1');
                        cmap = Object.assign(cmap, Object.fromEntries(courseClassesObj.map(c => [c.KZM, c])));
                        let keys = ['课程类型', '要求学分', '已修学分', '要求门数', '已修门数', '要求类别数', '已修类别数'];
                        let progressContent = '课程类型,要求学分,已修学分,要求门数,已修门数,要求类别数,已修类别数\n';
                        statCourseClasses = courseClassSorted(statCourseClasses);
                        statCourseClasses.map(statCourseClass => {
                            let c = cmap[statCourseClass];
                            return {
                                '课程类型': statCourseClass,
                                '要求学分': c.YQXF,
                                '已修学分': c.WCXF,
                                '要求门数': c.YQMS === null ? '0' : String(c.YQMS),
                                '已修门数': c.WCMS === null ? '0' : String(c.WCMS),
                                '要求类别数': c.YQWCKZS === null ? '0' : String(c.YQWCKZS),
                                '已修类别数': c.WCKZS === null ? '0' : String(c.WCKZS),
                            };
                        }).forEach(p => progressContent += keys.map(k => p[k]).join(',') + '\n');
                        let reqs = [];
                        courseClassesObj.forEach(courseClass => {
                            reqs.push($.ajax({
                                method: 'POST',
                                url: 'http://ehall.szu.edu.cn/jwapp/sys/xywccx/modules/xywccx/cxscfakzkc.do',
                                data: {
                                    BYNJDM: '-',
                                    KZH: courseClass.KZH,
                                    PYFADM: courseClass.PYFADM,
                                    pageSize: 999,
                                    pageNumber: 1,
                                },
                            }).then(res => {
                                let courseList = res.datas.cxscfakzkc.rows;
                                courseList = courseList.$map(['KCM', 'CJ', 'XF', 'SFTG_DISPLAY', 'XNXQDM', 'KCXZDM_DISPLAY', 'KCH', 'BZ']);
                                courseList = courseList.$reindex({'KCM': '课程名', 'CJ': '成绩', 'XF': '学分', 'SFTG_DISPLAY': '是否通过', 'XNXQDM': '学年学期', 'KCXZDM_DISPLAY': '课程性质', 'BZ': '备注'});
                                let clreqs = [];
                                courseList.forEach(course => {
                                    course['课程类型'] = courseClass.KZM;
                                    course['成绩'] = course['成绩'] || '';
                                    course['学年学期'] = course['学年学期'] || '';
                                    course['备注'] = course['备注'] || '';
                                    if (course['备注'].match(/[^\d\s\:a-zA-z\-]/g) === null || course['备注'].match(/见.*?备注.*/) !== null)
                                        course['备注'] = '';
                                    clreqs.push($.ajax({
                                        method: 'POST',
                                        url: 'http://ehall.szu.edu.cn/jwapp/sys/qxfacx/modules/pyfacxepg/kzkccx.do',
                                        data: {
                                            KZH: courseClass.KZH,
                                            PYFADM: courseClass.PYFADM,
                                            KCH: course.KCH,
                                            pageSize: 1,
                                            pageNumber: 1,
                                        },
                                    }).then(res => {
                                        let recSem = '';
                                        if (res.datas.kzkccx.rows.length > 0) {
                                            let remark = res.datas.kzkccx.rows[0].BZ;
                                            recSem = res.datas.kzkccx.rows[0].XDXQ || '';
                                            if (typeof remark === 'string' && remark.length > 0 && !course['备注'].length && (remark.match(/[^\d\s\:a-zA-z\-]/g) !== null && remark.match(/见.*?备注.*/) === null)) {
                                                course['备注'] = remark;
                                            };
                                        };
                                        course['建议修读学期'] = recSem;
                                        delete course.KCH;
                                        return course;
                                    }).fail(err => {
                                        console.info(err);
                                    }));
                                });
                                return Promise.all(clreqs).then(res => {
                                    return [courseClass.KZM, res];
                                });
                            }).fail(err => {
                                console.info(err);
                            }));
                        });
                        Promise.all(reqs).then(res => {
                            let courses = Object.fromEntries(res);
                            let gradeMap = {'A+': 4.5, 'A': 4.0, 'B+': 3.5, 'B': 3.0, 'C+': 2.5, 'C': 2.0, 'D': 1.0, 'F': 0.0};
                            let semester = Array.from(new Set(Object.values(courses).$merge().$map('学年学期'))).filter(s => Boolean(s));
                            semester.sort();
                            let earliestYear = new Date().getFullYear();
                            if (semester.length)
                                earliestYear = Number(semester[0].slice(0, 4));
                            let semesterIndexToDate = (year, semesterIndex) => {
                                semesterIndex = Number(semesterIndex);
                                let reccommendYear = year + ((semesterIndex - 1) >> 1);
                                let reccommendGrade = 2 - (semesterIndex & 1);
                                return `${reccommendYear}-${reccommendYear + 1}-${reccommendGrade}`;
                            };
                            let semesterDateToChinese = (year, semesterDate) => {
                                let allNums = semesterDate.match(/\d+/g);
                                let yearIndex = Number(allNums[0]) - year;
                                let gradeChinese = `大${numChinese[yearIndex]}${['上', '下'][Number(allNums[2]) - 1]}`;
                                return `${semesterDate} (${gradeChinese})`;
                            };
                            let semesterGrade = {};
                            semester.forEach(s => semesterGrade[s] = {semester: s, allScore: 0, getScore: 0, avgScore: 0, acaScore: 0, acgScore: 0, acvScore: 0});
                            Object.values(courses).$merge().forEach(course => {
                                if (course['学年学期']) {
                                    semesterGrade[course['学年学期']]['allScore'] += course['学分'];
                                    semesterGrade[course['学年学期']]['getScore'] += course['学分'] * gradeMap[course['成绩']];
                                };
                            });
                            semesterGrade = Object.values(semesterGrade).$sorted('semester');
                            for (let i = 0; i < semesterGrade.length; i++) {
                                semesterGrade[i].avgScore = parseFloat(semesterGrade[i].getScore / semesterGrade[i].allScore).toFixed(2);
                                semesterGrade[i].acaScore = semesterGrade[i].allScore;
                                semesterGrade[i].acgScore = semesterGrade[i].getScore;
                                for (let j = 0; j < i; j++) {
                                    semesterGrade[i].acaScore += semesterGrade[j].allScore;
                                    semesterGrade[i].acgScore += semesterGrade[j].getScore;
                                };
                                semesterGrade[i].acvScore = parseFloat(semesterGrade[i].acgScore / semesterGrade[i].acaScore).toFixed(2);
                                semesterGrade[i].semester = semesterDateToChinese(earliestYear, semesterGrade[i].semester);
                            };
                            recommendClasses.forEach(recommendClass => {
                                let courseClassesIndex = courseClassesObj.$where(x => x.KZM === recommendClass);
                                if (courseClassesIndex >= 0) {
                                    courses[recommendClass].forEach(c => {
                                        let reccommendSemester = '';
                                        if (c['建议修读学期'])
                                            reccommendSemester = semesterIndexToDate(earliestYear, c['建议修读学期']);
                                        c['建议修读学期'] = reccommendSemester;
                                    });
                                };
                            });
                            let orderedCourses = [];
                            allCourseClasses = courseClassSorted(allCourseClasses);
                            allCourseClasses.forEach(courseClass => {
                                if (ut.type.$isIterable(courses[courseClass]) && courses[courseClass].length > 0) {
                                    courses[courseClass] = courses[courseClass].$sorted(['课程名', '建议修读学期', '学年学期', '是否通过'], [false, false, false, true]);
                                    orderedCourses = orderedCourses.concat(courses[courseClass]);
                                };
                            });
                            let suggestCourses = [];
                            let notPassCourses = orderedCourses.filter(c => c['是否通过'] !== '通过');
                            recommendClasses = courseClassSorted(recommendClasses);
                            recommendClasses.forEach(recommendClass => {
                                let tmpCourseList = notPassCourses.filter(c => c['课程类型'] === recommendClass);
                                tmpCourseList = tmpCourseList.$sorted('建议修读学期');
                                if (recommendClass === '专业选修课') {
                                    let tmpLimitCourseList = tmpCourseList.filter(c => c['备注'].indexOf('限选') >= 0);
                                    let tmpFreeCourseList = tmpCourseList.filter(c => c['备注'].indexOf('限选') < 0);
                                    tmpCourseList = tmpLimitCourseList.concat(tmpFreeCourseList);
                                };
                                suggestCourses = suggestCourses.concat(tmpCourseList);
                            });
                            orderedCourses.forEach(c => {
                                if (c['学年学期'])
                                    c['学年学期'] = semesterDateToChinese(earliestYear, c['学年学期']);
                                if (c['建议修读学期'])
                                    c['建议修读学期'] = semesterDateToChinese(earliestYear, c['建议修读学期']);
                            });
                            let gradeContent = '学年学期,学期学分,学期GPA,累计学分,累计GPA\n';
                            for (let grade of semesterGrade)
                                gradeContent += `${grade.semester},${grade.allScore},${grade.avgScore},${grade.acaScore},${grade.acvScore}\n`;
                            let courseContent = '课程名,学分,成绩,是否通过,学年学期,建议修读学期,课程类型,课程性质,备注\n';
                            for (let course of orderedCourses)
                                courseContent += `${course['课程名']},${course['学分']},${course['成绩']},${course['是否通过']},${course['学年学期']},${course['建议修读学期']},${course['课程类型']},${course['课程性质']},${course['备注']}\n`;
                            let suggestContent = '以下是根据数据自动生成的推荐修读课程,仅供参考\n';
                            suggestContent += '课程名,学分,成绩,是否通过,学年学期,建议修读学期,课程类型,课程性质,备注\n';
                            for (let course of suggestCourses)
                                suggestContent += `${course['课程名']},${course['学分']},${course['成绩']},${course['是否通过']},${course['学年学期']},${course['建议修读学期']},${course['课程类型']},${course['课程性质']},${course['备注']}\n`;
                            let prompts = [
                                `【通知】修读课程统计表格生成成功`,
                                `【提示】通过 Excel 打开表格后,选中多列(即选中多个连续的字母索引),点击 "开始"->"单元格选项卡"->"样式"->"自动调整列宽" 就能更清楚地查看表格的整体内容。`,
                                `【提示】通过 Excel 打开表格后,选中单个表格的数据(即选中多行多列的单元格),点击 "开始"->"编辑选项卡"->"排序和筛选"->"筛选" 就能对表格的内容进行排序和筛选。`
                            ];
                            let csvContent = `${courseContent}\n${gradeContent}\n${progressContent}\n${suggestContent}\n`;
                            csvContent.$toCsv('修读课程统计.csv');
                            prompts.forEach(p => console.warn(p));
                            alert(prompts.join('\n'));
                        });
                    }).fail(err => {
                        console.info(err);
                    });
                };
                (function () {
                    let ampDesktopNav = $('#ampDesktopNav')[0];
                    if (!ampDesktopNav) return ;
                    function setTab () {
                        let stuServeCenter = ampDesktopNav.firstElementChild;
                        let div = HTMLElement.$mkel('div', {
                            id: 'download-training-program',
                            class: stuServeCenter.className.replace(/\s?amp\-active/, ''),
                            title: '修读课程统计下载',
                        }, {innerHTML: '修读课程统计下载'}, {}, {
                            click: function() {
                                $.ajax({
                                    method: 'POST',
                                    url: 'http://ehall.szu.edu.cn/jwapp/sys/xywccx/modules/xywccx/cxscfakz.do',
                                    data: {
                                        BYNJDM: '-',
                                    },
                                }).then(res => {
                                    let rows = res.datas.cxscfakz.rows;
                                    let i = 0;
                                    while (rows[i].KZM.indexOf('基本通识课') < 0 && i < rows.length)
                                        i++;
                                    let courseClass = rows[i];
                                    $.ajax({
                                        method: 'POST',
                                        url: 'http://ehall.szu.edu.cn/jwapp/sys/qxfacx/modules/pyfacxepg/kzkccx.do',
                                        data: {
                                            KZH: courseClass.KZH,
                                            PYFADM: courseClass.PYFADM,
                                            pageSize: 10,
                                            pageNumber: 1,
                                            BYNJDM: '-',
                                        },
                                    }).then(res => {
                                        setTimeout(() => {
                                            $('#ampDesktopNav')[0].firstElementChild.click();
                                        }, 50);
                                        exec();
                                    }).fail(err => {
                                        console.log('fail (code: -2)');
                                        alert(`将跳转至"全校培养方案查询",跳转后请手动关闭打开的页面`);
                                        let btn = $('[amp-title=全校培养方案查询]')[0];
                                        btn.setAttribute('amp-unviewabledescription', 'true');
                                        btn.click();
                                        setTimeout(() => {
                                            div.click();
                                        }, 50);
                                    });
                                }).fail(err => {
                                    console.log('fail (code: -1)');
                                    alert(`将跳转至"学业完成查询",跳转后请手动关闭打开的页面`);
                                    let btn = $('.card-bus-content [amp-title=学业完成查询]')[0];
                                    btn.setAttribute('amp-unviewabledescription', 'true');
                                    btn.click();
                                    setTimeout(() => {
                                        div.click();
                                    }, 50);
                                });
                            },
                        });
                        stuServeCenter.$before(div, -1);
                    };
                    (function rec () {
                        let child = ampDesktopNav.firstElementChild;
                        if (child) {
                            setTab();
                        } else {
                            setTimeout(rec, 50);
                        }
                    })();
                })();
            };
            let ampHasNoLogin = document.getElementById('ampHasNoLogin');
            if (ampHasNoLogin && sessionStorage.ampUserId === 'guest') {
                ampHasNoLogin.click();
                setfunc();
            };
            if (sessionStorage.ampUserId !== 'guest') {
                if (location.href.indexOf('/jwapp/sys/czjl') >= 0) {
                    (function rec () {
                        let el = document.getElementsByClassName('czjl-sixItem-container')[0];
                        if (el) {
                            el.innerHTML = el.innerHTML.replace(/<!\-\-\s*/g, '').replace(/\s*\-\->+/g, '');
                        } else {
                            setTimeout(rec, 50);
                        };
                    })();
                };
                if (location.href.indexOf('/jwapp/sys/jwwspj') >= 0) {
                    if (document.getElementsByClassName('timu-title')[0] && !document.getElementById('quick-set')) {
                        let title = document.getElementsByClassName('timu-title')[0];
                        let btn = HTMLElement.$mkel('button', {id: 'quick-set'}, {innerHTML: '一键五星+评价'}, {
                            'border': '0',
                            'width': '300px',
                            'height': '40px',
                            'margin-left': '10px',
                            'fontW-weight': 'bold',
                            'font-size': '16px',
                            'color': 'white',
                            'background-color': '#d22e2e',
                        }, {
                            'click': function(event) {
                                let rotate = document.getElementsByClassName('rotate')[0];
                                if (rotate && rotate.innerHTML.indexOf('已') >= 0) {
                                    alert('你已经评教过了');
                                    return false;
                                };
                                $('[data-x-bl=100]').toArray().forEach(s => s.firstElementChild.click());
                                $('textarea').val(prompt('请提供一个默认的教师评价'));
                                return false;
                            },
                        });
                        title.$before(btn);
                    };
                };
                if (location.href.indexOf('/new/index.html') >= 0) {
                    if ($('#ampDesktopNav')[0] && !$('#download-training-program')[0]) {
                        setfunc();
                    };
                };
                if (location.href.indexOf('/jwapp/sys/xywccx') >= 0) {
                    function setFunc () {
                        let scoreMaps = {
                            'A+': 4.5,
                            'A': 4.0,
                            'B+': 3.5,
                            'B': 3.0,
                            'C+': 2.5,
                            'C': 2.0,
                            'D': 1.0,
                            'F': 0.0,
                        };
                        function setList(courses, sem) {
                            function createInfo() {
                                let studentName = sessionStorage.ampUserName;
                                let weightedScore = courses.map(c => parseFloat(c['学分']) * scoreMaps[c['成绩']]);
                                let score = courses.map(c => parseFloat(c['学分']));
                                let avgScore = parseFloat(weightedScore.$sum() / score.$sum()).toFixed(2);
                                let info = HTMLElement.$mkel(
                                    'div', {}, {
                                        innerHTML: `
                                            <p style="margin-top: 40px;">${studentName} 同学,你本学期的绩点是:</p>
                                            <p style="font-size: 120px; color: #fff306; height: 120px; margin-top: 30px;"><i>${avgScore}</i></p>
                                            <p style="margin: 70px 0 60px;">下学期再接再厉哦!</p>
                                        `,
                                    }, {
                                        'font-size': '30px',
                                        'background-color': '#fe5f5e',
                                        'margin-bottom': '20px',
                                        'width': '640px',
                                        'display': 'flex',
                                        'flex-direction': 'column',
                                        'align-items': 'center',
                                        'color': 'white',
                                    }
                                );
                                return info;
                            };
                            function createTable() {
                                let table = HTMLElement.$mkel(
                                    'div', {id: 'rainbow-grade-table'}, {}, {
                                        'width': 'max-content',
                                        'height': 'max-content',
                                        'display': 'flex',
                                        'flex-direction': 'column',
                                        'margin': '200px',
                                        'align-items': 'center',
                                        'background-color': 'white',
                                        'line-height': 'normal',
                                    }
                                );
                                return table;
                            };
                            function createItem(course) {
                                function createText() {
                                    let text = HTMLElement.$mkel(
                                        'div', {}, {
                                            innerHTML: `
                                                <p style="
                                                    overflow: hidden;
                                                    text-overflow: ellipsis;
                                                    white-space: nowrap;
                                                ">课程名:${course['课程名']}</p>
                                                <p>课程号:${course['课程号']}</p>
                                                <p>学分:${course['学分']}</p>
                                                <p>课程类别:${course['课程类别']}</p>
                                            `,
                                        }, {
                                            'width': '400px',
                                            'font-size': '28px',
                                            'padding-left': '20px',
                                        }
                                    );
                                    let container = HTMLElement.$mkel(
                                        'div', {}, {}, {
                                            'display': 'flex',
                                            'flex-direction': 'column',
                                            'align-items': 'center',
                                            'justify-content': 'center',
                                        }
                                    );
                                    container.appendChild(text);
                                    return container;
                                };
                                function createScore() {
                                    let text = HTMLElement.$mkel(
                                        'div', {}, {innerHTML: course['成绩']}, {
                                            'font-size': '90px',
                                        },
                                    );
                                    let container = HTMLElement.$mkel(
                                        'div', {}, {}, {
                                            'display': 'flex',
                                            'flex-direction': 'column',
                                            'align-items': 'center',
                                            'justify-content': 'center',
                                            'width': '160px',
                                        }
                                    );
                                    container.appendChild(text);
                                    return container;
                                };
                                function createCard() {
                                    let cmap = {
                                        'A+': '#e7322f',
                                        'A': '#fe5f5e',
                                        'B+': '#7648d9',
                                        'B': '#4d89d7',
                                        'C+': '#ff7905',
                                        'C': '#ffa303',
                                        'D': '#219b3e',
                                        'F': '#4e4e4e',
                                    };
                                    let bgc = cmap[course['成绩']];
                                    let card = HTMLElement.$mkel('div', {}, {}, {
                                        'display': 'flex',
                                        'flex-direction': 'row',
                                        'align-items': 'center',
                                        'justify-content': 'space-between',
                                        'width': '600px',
                                        'height': '200px',
                                        'margin-bottom': '20px',
                                        'border-radius': '12px',
                                        'background-color': bgc,
                                        'color': 'white',
                                    });
                                    let text = createText();
                                    let score = createScore();
                                    card.appendChild(text);
                                    card.appendChild(score);
                                    return card;
                                };
                                let item = createCard();
                                return item;
                            };
                            let semList = Array.from(new Set(courses.map(c => c['学年学期']).filter(c => c)));
                            if (sem && !semList.includes(sem)) {
                                alert('输入不合法,默认生成最新学期的彩虹地毯');
                                sem = semList.$max();
                            };
                            if (!sem)
                                sem = semList.$max();
                            courses = courses.filter(c => c['学年学期'] === sem);
                            courses = courses.$sorted([c => parseFloat(c['学分']), c => scoreMaps[c['成绩']]], [true, true]);
                            let table = createTable();
                            table.appendChild(createInfo());
                            courses.forEach(course => table.appendChild(createItem(course)));
                            $('.bh-paper-pile-body')[0].$before(table);
                        };
                        function downloadList() {
                            function callbackfn(canvas) {
                                let a = HTMLElement.$mkel(
                                    'a', {
                                        href: canvas.toDataURL('image/png', 1.0),
                                        download: '彩虹地毯.png',
                                    }
                                );
                                document.body.appendChild(a);
                                a.click();
                                document.body.removeChild(a);
                            };
                            if (typeof html2canvas !== 'undefined') {
                                $.getScript('https://html2canvas.hertzen.com/dist/html2canvas.js', function() {
                                    html2canvas($('#rainbow-grade-table')[0], {dpi: window.devicePixelRatio}).then(callbackfn);
                                });
                            } else {
                                html2canvas($('#rainbow-grade-table')[0], {dpi: window.devicePixelRatio}).then(callbackfn);
                            };

                        };
                        function setBar(courses) {
                            if (!$('#xywcqk_chdt')[0]) {
                                let bar = $('.bh-paper-pile-dialog-container')[0];
                                if (bar) {
                                    bar.style.width = `${bar.offsetWidth + 100}px`;
                                    let a = HTMLElement.$mkel(
                                        'a', {
                                            id: 'xywcqk_chdt'
                                        }, {
                                            innerHTML: '彩虹地毯',
                                        }, {
                                            'font-size': '14px',
                                            'margin-left': '20px',
                                            'cursor': 'pointer',
                                        }
                                    );
                                    let last = $('#xywcqk_bxqxk')[0];
                                    last.$before(a);
                                    a.$before(last);
                                    a.addEventListener('click', function(event) {
                                        if (!$('#rainbow-grade-table')[0]) {
                                            let semester = prompt(`请输入需要生成彩虹地毯的学年学期,格式为 'yyyy-yyyy-n' ,如 '2020-2021-2' 表示2020学年至2021学年第2学期,若输入不合法或不输入,将默认生成最新学期的彩虹地毯`);
                                            while (semester && !/^\d{4}-\d{4}-\d$/.exec(semester))
                                                semester = prompt(`输入格式必须为 'yyyy-yyyy-n'`);
                                            if (!semester) {
                                                alert('未输入,默认生成最新学期的彩虹地毯');
                                                semester = undefined;
                                            } else {
                                                let [yearStart, yearEnd, num] = semester.match(/\d+/g);
                                                if (parseInt(yearEnd) - parseInt(yearStart) !== 1 || !parseInt(num).$in(1, 2, true)) {
                                                    alert('输入不合法,默认生成最新学期的彩虹地毯');
                                                    semester = undefined;
                                                };
                                            };
                                            setList(courses, semester);
                                            downloadList();
                                        };
                                    });
                                };
                            };
                        };
                        if (!window.courseClasses) {
                            $.ajax({
                                method: 'POST',
                                url: 'http://ehall.szu.edu.cn/jwapp/sys/xywccx/modules/xywccx/cxscfakz.do',
                                data: {
                                    BYNJDM: '-',
                                },
                            }).then(res => {
                                let courseClasses = res.datas.cxscfakz.rows;
                                window.courseClasses = courseClasses;
                                courseClasses = courseClasses.$map(['KZM', 'KZH', 'PYFADM', 'YQXF', 'WCXF', 'YQMS', 'WCMS', 'YQWCKZS', 'WCKZS', 'FKZH']).filter(c => c.FKZH !== '-1');
                                Promise.all(courseClasses.map(courseClass => {
                                    return $.ajax({
                                        method: 'POST',
                                        url: 'http://ehall.szu.edu.cn/jwapp/sys/xywccx/modules/xywccx/cxscfakzkc.do',
                                        data: {
                                            BYNJDM: '-',
                                            KZH: courseClass.KZH,
                                            PYFADM: courseClass.PYFADM,
                                            pageSize: 999,
                                            pageNumber: 1,
                                        },
                                    }).then(res => {
                                        let courseList = res.datas.cxscfakzkc.rows;
                                        courseList = courseList.$map(['KCM', 'KCH', 'CJ', 'XF', 'KCLBDM_DISPLAY', 'SFTG_DISPLAY', 'XNXQDM']);
                                        courseList = courseList.$reindex({'KCM': '课程名', 'KCH': '课程号','CJ': '成绩', 'XF': '学分', 'KCLBDM_DISPLAY': '课程类别', 'SFTG_DISPLAY': '是否通过', 'XNXQDM': '学年学期'});
                                        courseList.forEach(c => {
                                            c['成绩'] = c['成绩'] || 'F';
                                            c['学分'] = parseFloat(c['学分']).toFixed(2)
                                        });
                                        return courseList;
                                    });
                                })).then(res => {
                                    setBar(res.$merge());
                                    window.courseClasses = undefined;
                                });
                            });
                        };
                    };
                    (function rec () {
                        let closeButton = $('.jqx-window-close-button')[0];
                        if (closeButton) {
                            closeButton.click();
                            $('.bh-tag.bh-tag-round')[0].click();
                        } else {
                            setTimeout(rec, 500);
                        };
                    })();
                    let fn = (events) => {
                        for (let event of events) {
                            for (let node of event.addedNodes) {
                                if (node.classList.contains('bh-paper-pile-dialog')) {
                                    console.log(event);
                                    setFunc();
                                };
                            };
                        };
                    };
                    document.body.$monitor({ childList: true }, fn);
                };
            };
            (function rec () {
                if ($('#ampTabContentItem0')[0]) {
                    $('#ampTabContentItem0')[0].$monitor({ childList: true, subtree: true }, (events) => {
                        $('.appFlag.widget-app-item').attr('amp-unviewabledescription', 'true');
                        $('.appFlag.amp-app-card-hover-big').attr('amp-unviewabledescription', 'true');
                    });
                } else {
                    setTimeout(rec, 50);
                };
            })();
            $('#ampServiceCenterSearchApps')[0].$monitor({ childList: true, subtree: true }, (events) => {
                $('.appFlag.widget-app-item').attr('amp-unviewabledescription', 'true');
                $('.appFlag.amp-app-card-hover-big').attr('amp-unviewabledescription', 'true');
            });
        } else if (location.host == '172.30.255.2') {
            if (location.href.includes('.htm')) {
                let username = document.getElementById('username');
                let password = document.getElementById('password');
                let submit = document.querySelector('#submit[type=submit]');
                if (username && password && submit) {
                    username.value = CARD_ID;
                    password.value = PASSWORD;
                    submit.click();
                };
            };
        } else if (location.host == '192.168.84.3:9090') {
            let client = document.querySelector('[name=client]');
            let buildingName = document.querySelector('[name=buildingId]');
            let roomName = document.querySelector('[name=roomName]');
            let beginTime = document.querySelector('#beginTime');
            let endTime = document.querySelector('#endTime');
            if (client && buildingName && roomName) {
                if (account.clientSelectedIndex !== client.selectedIndex) {
                    account.clientSelectedIndex = client.selectedIndex;
                    account.client = client.value;
                    delete account.buildingNameSelectedIndex;
                    delete account.buildingId;
                    delete account.roomName;
                    GM_setValue('account', account);
                };
                if (account.buildingId) buildingName.selectedIndex = account.buildingNameSelectedIndex;
                buildingName.removeAttribute('onchange');
                buildingName.onchange = function () {
                    account.buildingNameSelectedIndex = this.selectedIndex;
                    account.buildingId = this.options[this.selectedIndex].value;
                    GM_setValue('account', account);
                };
                if (account.roomName) roomName.value = account.roomName;
                roomName.oninput = function () {
                    account.roomName = this.value;
                    GM_setValue('account', account);
                };
            } else if (beginTime && endTime && location.href.indexOf('login.do') >= 0) {
                let toDate = (date) => date.toLocaleDateString().replace(/\//g, '-');
                let now = new Date();
                let twentyDaysAgo = new Date(now.getTime() - 1000 * 86400 * 19);
                beginTime.value = toDate(twentyDaysAgo);
                endTime.value = toDate(now);
                document.querySelector('[name=type]').selectedIndex = 1;
                document.querySelector('[type=submit]').click();
            };
        } else if (location.host == 'drcom.szu.edu.cn') {
            if (location.href.includes('.htm')) {
                let username = document.querySelector('input[name=DDDDD]');
                let password = document.querySelector('input[name=upass]');
                let submit = document.querySelector('input[type=submit]');
                if (username && password && submit) {
                    username.value = CARD_ID;
                    password.value = PASSWORD;
                    submit.click();
                };
            };
        } else if (location.host == 'www1.szu.edu.cn') {
            if (location.href == 'https://www1.szu.edu.cn/') {
                let td = document.querySelector('table table table tbody tr td');
                let a_drcom_dom = document.getElementById('drcom_dom');
                if (td && !a_drcom_dom) {
                    td.querySelectorAll('img').forEach(e => e.remove());
                    td.firstChild.remove();
                    td.firstChild.remove();
                    td.style.padding = '5px 20px';
                    td.innerHTML += '<br>';
                    let a;
                    a = HTMLElement.$mkel('a', {
                        href: 'http://192.168.84.3:9090/cgcSims/',
                        id: 'electricity',
                    }, {innerHTML: '宿舍用电查询'});
                    td.appendChild(a);
                    a = HTMLElement.$mkel('a', {
                        href: 'https://self.szu.edu.cn/self/',
                        id: 'network',
                    }, {innerHTML: '|校园网络续费'});
                    td.appendChild(a);
                    a = HTMLElement.$mkel('a', {
                        href: 'http://172.30.255.2/0.htm',
                        id: 'drcom_dom',
                    }, {innerHTML: '|登录(不可用) Dr.com'});
                    td.appendChild(a);
                    td.innerHTML += '<br>';
                    a = HTMLElement.$mkel('a', {
                        href: 'http://ehall.szu.edu.cn/publicapp/sys/tycgyyxt/index.do',
                        id: 'venue_yh',
                    }, {innerHTML: '体育场馆预订(粤海校区)'});
                    td.appendChild(a);
                    a = HTMLElement.$mkel('a', {
                        href: 'http://ehall.szu.edu.cn/publicappxl/sys/xlxqtycgyy/index.do',
                        id: 'venue_lh',
                    }, {innerHTML: '|体育场馆预订(丽湖校区)'});
                    td.appendChild(a);
                    td.innerHTML += '<br>';
                    a = HTMLElement.$mkel('a', {
                        href: 'http://www.lib.szu.edu.cn/zh-hans/er/baidu-wenku',
                        id: 'wenku',
                    }, {innerHTML: '百度文库'});
                    td.appendChild(a);
                    a = HTMLElement.$mkel('a', {
                        href: 'https://www1.szu.edu.cn/nc/view.asp?id=64',
                        id: 'download',
                    }, {innerHTML: '|下载专区'});
                    td.appendChild(a);
                    a = HTMLElement.$mkel('a', {
                        href: 'http://xzfc.szu.edu.cn/rsfw/sys/szdxxzfc/login/index.do',
                        id: 'teacher',
                    }, {innerHTML: '|师资队伍'});
                    td.appendChild(a);
                    let tbody = document.querySelectorAll('table table table tbody')[4];
                    tbody.querySelector('tr:nth-child(2)').style.height = '415px';
                };
            };
        } else if (location.host == 'bkxk.szu.edu.cn') {
            let loginName = document.getElementById('loginName');
            let loginPwd = document.getElementById('loginPwd');
            if (loginName && loginPwd) {
                loginName.value = STUDENT_ID;
                loginPwd.value = PASSWORD;
            };
        } else if (location.host == 'self.szu.edu.cn') {
            let account = document.getElementById('account');
            let pass = document.getElementById('pass');
            let submit = document.querySelector('input[type=submit]');
            if (account && pass && submit) {
                account.value = CARD_ID;
                pass.value = PASSWORD;
                submit.click();
            };
        };
    };
    $(document).ready(run);
})();

QingJ © 2025

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