// ==UserScript== // @name 电子科技大学教务助手 // @namespace http://shawroger.gitee.io/ // @version 0.0.3 // @description 电子科技大学教务助手帮你更便捷地使用教务系统 // @author shawroger // @match *://eams.uestc.edu.cn/eams/* // @require https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js // @require https://cdn.bootcdn.net/ajax/libs/highcharts/9.1.2/highcharts.min.js // @icon https://www.uestc.edu.cn/favicon.ico // @downloadURL none // ==/UserScript== const timeConfig = { renderScore: 600, globalListener: 200, }; const STORAGE_KEY = "UESTC_STUDYSYS_HELPER_SHOWBAR_ALL"; const loopVars = { renderPlan: true, renderScore: true, }; const itemConfig = [ { text: "查询平时成绩", img: "https://pic.imgdb.cn/item/60ead7fd5132923bf8f5b136.png", href: "http://eams.uestc.edu.cn/eams/teach/grade/usual/usual-grade-std.action", }, { text: "快速查询成绩", img: "https://pic.imgdb.cn/item/60ead77f5132923bf8f3f56b.png", href: "http://eams.uestc.edu.cn/eams/teach/grade/course/person.action", }, { text: "审阅我的计划", img: "https://pic.imgdb.cn/item/60eadacf5132923bf8ffcca2.png", href: "http://eams.uestc.edu.cn/eams/myPlanCompl.action", }, ]; const scoreColors = [ { range: [80, 101], background: "LightSeaGreen", color: "", bookLevel: 1, }, { range: [70, 80], background: "LawnGreen", color: "", bookLevel: 2, }, { range: [60, 70], background: "NavajoWhite", color: "", bookLevel: 3, }, { range: [-1, 60], background: "IndianRed", color: "white", bookLevel: 4, }, ]; const keywordsColor = [ { words: ["P", "A", "通过"], background: "LightSeaGreen", color: "", index: -3, bookLevel: 1, }, { words: ["否"], background: "IndianRed", color: "white", index: -2, bookLevel: 4, }, ]; function createRecordBook() { const recordBook = { v1: 0, v2: 0, v3: 0, bad: 0, }; recordBook.count = function () { return this.v1 + this.v2 + this.v3 + this.bad; }; recordBook.doneCount = function () { return this.v1 + this.v2 + this.v3; }; recordBook.doneRate = function () { this.doneCount() / this.count(); }; recordBook.addByLevel = function (bookLevel) { if (bookLevel === 1) { this.v1++; } else if (bookLevel === 2) { this.v2++; } else if (bookLevel === 3) { this.v3++; } else { this.bad++; } if (recordBook.onChange) { recordBook.onChange(); } }; recordBook.genCharts = function () { const plotOptions = { pie: { allowPointSelect: true, cursor: "pointer", dataLabels: { enabled: true, format: "{point.name} {point.percentage:.1f} %", style: { color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || "black", }, }, }, }; const series = [ { type: "pie", data: [ ["优秀", this.v1], ["较好", this.v2], ["一般", this.v3], ["未完成", this.bad], ], }, ]; const config = { title: { text: "我的当前学习完成情况表", }, chart: { plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, backgroundColor: "#f2f2f2", }, tooltip: { pointFormat: "共 {point.y} 门课程 {point.percentage:.1f}%", }, }; config.series = series; config.plotOptions = plotOptions; return config; }; return recordBook; } function safeParseInt(val) { if (typeof val === "number") { return val; // Maybe NaN itself } else if (typeof val === "string") { return Number(val); } else { return NaN; } } function initStorage() { const v = window.localStorage.getItem(STORAGE_KEY); const val = safeParseInt(v); if (isNaN(val)) { window.localStorage.setItem(STORAGE_KEY, "1"); return 1; } else { return val; } } function urlContains(url) { return window.location.href.includes(url); } // 跳转首页 function reachHomePage() { window.location.href = `http://eams.uestc.edu.cn/eams`; } // 注入全局 CSS 样式 function injectCSS() { const head = $("head"); const css = ` `; head.append(css); } function bindAction() { const resetBtn = $("#reset_btn"); resetBtn.click(reachHomePage); const closeBtn = $("#close_btn"); closeBtn.click(() => { $(".uestc-helper-box").hide(); window.localStorage.setItem("UESTC_STUDYSYS_HELPER_SHOWBAR_ALL", "0"); reachHomePage(); }); const showBtn = $("#show_btn"); showBtn.click(() => { $(".uestc-helper-box").show(); window.localStorage.setItem("UESTC_STUDYSYS_HELPER_SHOWBAR_ALL", "1"); reachHomePage(); }); $("#position_bar span.secondMenu a").click(() => { $("#ush_chart_box").hide(); loopVars.renderScore = true; }); $(".toolbar-item-ge0 toolbar-item").click(() => { renderScore(); loopVars.renderScore = true; }); $("input[value='切换学期']").click(() => { renderScore(); loopVars.renderScore = true; }); } // 注入 HTML 代码 function injectHTML() { if (initStorage()) { const div = $("body"); const html = `

电子科技大学教务助手

`; div.prepend(html); } else { const div = $("form[action='/eams/home.action']"); const html = ``; div.append(html); } } // 监听教务系统是否显示不正常 function listenBrokenFrame() { const bar = $("#position_bar"); if ( bar.length === 0 && !urlContains("stdElectCourse") && !urlContains("teach/grade/usual/usual-grade-std!usualInfo.action") ) { $("#helper-text").text("教务系统页面显示异常,即将自动重置"); $("#helper-text").css("color", "red"); // 等待 0.2秒 后跳回 setTimeout(reachHomePage, 200); } } // 重整布局 function resetLayout() { $("img[src = '/eams/avatar/my.action']").hide(); if (urlContains("home!submenus.action?")) { const node = $("div.list_box_1 li.li_1").last().clone(true); itemConfig.forEach(({ text, img, href }) => { node.find("h3").text(text); node.find("a").attr("href", href); node.find("div").css("background", `url("${img}") no-repeat 50% 50%`); $("div.list_box_1 li.li_1") .last() .parent() .append(`
  • ` + node.html() + `
  • `); }); } } function addBottomText() { const footer = $("#BottomBg"); footer.html( footer.text() + `

    页面启用了 电子科技大学教务助手 made by shawroger` ); } // 通过分数区间来染色 function paintColorByScore(recordBook, tr, text) { const score = parseInt(text); for (const { color, range, background, bookLevel } of scoreColors) { if (range[0] <= score && score < range[1]) { recordBook.addByLevel(bookLevel); tr.css("background", background); if (color.length > 1) { tr.find("td").each((_, e) => { $(e).css("color", color); if ($(e).children("a").length > 0) { $(e).children("a").css("color", color); } }); } return true; } } return false; } // 通过关键字来染色 function paintColorByKeyword(recordBook, tr, text) { function textContainAny(words, text) { for (const word of words) { if (text === word) { return true; } } return false; } for (const { color, words, background, index, bookLevel } of keywordsColor) { const safeText = text || tr.find("td").eq(index).text().trim(); if (textContainAny(words, safeText)) { tr.css("background", background); recordBook.addByLevel(bookLevel); if (color.length > 1) { tr.find("td").each((_, e) => { $(e).css("color", color); if ($(e).children("font").length > 0) { $(e).children("font").attr("color", color); } if ($(e).children("a").length > 0) { $(e).children("a").css("color", color); } }); } return true; } } return false; } // 渲染 计划完成情况 页面 function renderPlan() { if (!urlContains("myPlanCompl.action")) { return; } $("#ush_chart_box").show(); loopVars.renderPlan = false; $("#main").before(`
    `); const recordBook = createRecordBook(); const table = $("table.formTable"); table.find("tr").each((_, e) => { const tr = $(e); const text = tr.find("td").eq(-3).text().trim(); if (!paintColorByScore(recordBook, tr, text)) { paintColorByKeyword(recordBook, tr); } }); $("#ush_chart_box").highcharts(recordBook.genCharts()); } // 渲染 我的成绩 页面 function renderScore() { if ( !urlContains("teach/grade/course/person") && !urlContains("teach/grade/usual") ) { return; } $("#ush_chart_box").show(); if ($("#ush_chart_box").length === 0) { $("#main").before(`
    `); } $("div[title='所有学期成绩']").click(() => { loopVars.renderScore = true; console.log("loopVars.renderScore = true"); }); const recordBook = createRecordBook(); const table = $("table.gridtable").last(); table.find("tr").each((_, e) => { const tr = $(e); const text = urlContains("historyCourseGrade") ? tr.find("td").last().text().trim() : tr.find("td").eq(-2).text().trim(); if (!paintColorByScore(recordBook, tr, text)) { paintColorByKeyword(recordBook, tr, text); } }); // 0.6秒 后停止监听 setTimeout(() => { loopVars.renderScore = false; if ($("#ush_chart_box").length > 0) { $("#ush_chart_box").highcharts(recordBook.genCharts()); } }, timeConfig.renderScore); } (function () { "use strict"; initStorage(); injectCSS(); injectHTML(); resetLayout(); addBottomText(); listenBrokenFrame(); renderPlan(); renderScore(); Highcharts.setOptions({ colors: scoreColors.map(({ background }) => background), }); setInterval(() => { bindAction(); listenBrokenFrame(); if (loopVars.renderPlan) { renderPlan(); } if (loopVars.renderScore) { renderScore(); } }, timeConfig.globalListener); })();