// ==UserScript== // @name 上大选课优化 // @namespace http://r-ay.cn/ // @version 0.4 // @description 对上海大学本硕博一体化选课网进行了优化 // @author Ray // @match http://xk.autoisp.shu.edu.cn/* // @exclude http://xk.autoisp.shu.edu.cn/Scripts/DatePicker/My97DatePicker.htm // @icon https://www.google.com/s2/favicons?sz=64&domain=shu.edu.cn // @grant none // @license MIT // @downloadURL none // ==/UserScript== function log (...data) { console.log("[shuxkhelper]", new Date().toLocaleTimeString(), ...data) } function gotoXK (CID, TeachNo, tkFirst, tkCid, tkTeachNo) { log("called func gotoXK", CID, TeachNo, tkFirst, tkCid, tkTeachNo) localStorage.removeItem("jumpXK") let jumpXK = {} jumpXK.tkFirst = tkFirst jumpXK.tkCid = tkCid jumpXK.tkTeachNo = tkTeachNo jumpXK.Cid = CID jumpXK.TeachNo = TeachNo localStorage.setItem('jumpXK', JSON.stringify(jumpXK)) window.location.pathname = `${jumpXK.tkFirst ? '/CourseReturnStudent/CourseReturn' : '/CourseSelectionStudent/FuzzyQuery'}` } document.getElementsByClassName("main-footer")[0].getElementsByTagName("span")[0].innerText = "上大选课优化 v0.4" const base = 'http://xk.autoisp.shu.edu.cn' let path = window.location.pathname let termId = localStorage.getItem('termId') log(`shuxkhelper loaded at ${path} in ${termId}.`) /* 学期选择页 /Home/TermIndex - 读入学期代码, 存入缓存 */ if (path === '/Home/TermIndex') { termId = document.getElementsByTagName("tbody")[0].getElementsByTagName("tr")[0].getAttribute("value"); localStorage.setItem('termId', termId) log(`in ${path}, got termId ${termId}.`) document.getElementsByTagName("tbody")[0].getElementsByTagName("tr")[0].click() document.getElementsByTagName("button")[0].click() return; } /* 起始页 /Home/TermSelect - 自动关闭 */ if (path === '/Home/TermSelect') { if (localStorage.getItem("close") === 'true') { localStorage.removeItem("close") window.close() return; } } /* base - 每分钟刷新选课学期, 实现保活 - 替换错误页跳转 - 优化网络请求函数 */ if (termId === null) { log('unknown termId, jumping to fetch..') window.location.pathname = "/Home/TermIndex" } else { // 刷新学期 http://xk.autoisp.shu.edu.cn/Home/TermSelect window.keepAlive = () => { window.aliveInterval = setInterval(() => { log(`started to keep alive(id ${window.aliveInterval}).`) let tempA = document.createElement("a"); tempA.target = "_blank"; tempA.href = "http://xk.autoisp.shu.edu.cn/Login"; localStorage.setItem("close", true); tempA.click(); }, 600000) document.getElementById("aliveBtn").innerHTML = `Alive[ON]` } window.delAlive = () => { clearInterval(window.aliveInterval) document.getElementById("aliveBtn").innerHTML = `Alive[OFF]` } window.handleAliveClick = () => { if (document.getElementById("aliveBtn") === null) { let aliveBtn = document.createElement("li") aliveBtn.innerHTML = `Alive[ON]` aliveBtn.id = "aliveBtn" document.getElementsByClassName("nav navbar-nav")[0].appendChild(aliveBtn) if (localStorage.getItem('alive') === null) { window.keepAlive() localStorage.setItem('alive', true) } else if (localStorage.getItem('alive') === 'true') { window.keepAlive() } else { window.delAlive() } } else if (document.getElementById("aliveBtn")?.innerHTML === `Alive[OFF]`) { window.keepAlive() localStorage.setItem('alive', true) } else { window.delAlive() localStorage.setItem('alive', false) } } window.handleAliveClick() // 替换错误页跳转 window.ShowError = (request, status, error, url) => log(`caught error:\nrequest: ${JSON.stringify(request)}\nstatus: ${status}\nerror: ${error}\nurl: ${url}`) // 优化网络请求函数 window.submitAjax = opt => { defaults = { form: null, url: '', type: 'POST', async: false, cache: false, dataType: '', traditional: false, resetForm: false, beforeSend: null, success: null, error: null }; options = $.extend({}, defaults, opt); $(options.form).ajaxSubmit({ type: options.type, url: ParseUrl(options.url), resetForm: options.resetForm, async: options.async, cache: options.cache, dataType: options.dataType, traditional: options.traditional, beforeSubmit: options.beforeSend, success: function (data) { if (options.success) options.success(data); }, error: function (request, status, e) { ShowError(request, status, e, options.url); if (options.error) options.error(e); } }); } } /* 选课排名查询 /StudentQuery/QueryEnrollRank - 提供可视化按钮, 根据选课排名标出颜色 */ if (path === '/StudentQuery/QueryEnrollRank') { log('applied btn customColor.') window.customColor = () => document .getElementsByName('rowclass') .forEach(tr => { if (tr.getElementsByTagName('td')[6].innerText.indexOf("-") === -1) { // 单人间 if (parseInt(tr.getElementsByTagName('td')[6].innerText) <= parseInt(tr.getElementsByTagName('td')[4].innerText)) { tr.style.backgroundColor = '#2ecc71' } else if (parseInt(tr.getElementsByTagName('td')[6].innerText) < parseInt(tr.getElementsByTagName('td')[4].innerText)) { tr.style.backgroundColor = '#e74c3c' } } else if (parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[1]) <= parseInt(tr.getElementsByTagName('td')[4].innerText)) { // 可中 tr.style.backgroundColor = '#2ecc71' } else if (parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[0]) < parseInt(tr.getElementsByTagName('td')[4].innerText)) { // 随机中 tr.style.backgroundColor = '#f1c40f'; tr.getElementsByTagName('td')[6].innerText = `${parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[0]).toString()}-${parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[1]).toString()} (${(Math.floor((parseInt(tr.getElementsByTagName('td')[4].innerText) - parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[0]) + 1) / (parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[1]) - parseInt(tr.getElementsByTagName('td')[6].innerText.split('-')[0]) + 1) * 10000) / 100).toString()}%)`; } else { tr.style.backgroundColor = '#e74c3c'; } }) let newLi = document.createElement('li'); newLi.className = "active"; newLi.innerHTML = `可视化`; document.getElementsByClassName("breadcrumb")[0].appendChild(newLi); } /* 课程查询 /StudentQuery/QueryCourse - 重写请求函数, 在查询指定课程与老师时自动提交选课或刷新排名 */ if (path === "/StudentQuery/QueryCourse") { log('replaced function query.') window.Query = function Query (PageIndex, PageSize, interval = 2000) { $("#coursefilterPageIndex").val(PageIndex); $("#coursefilterPageSize").val(PageSize); submitAjax({ form: $("#formcoursefilter"), url: "/StudentQuery/QueryCourseList", dataType: "html", beforeSend: function () { //$("#divMainContent").html(loadinggif); }, success: function (html) { document.getElementById("divMainContent").innerHTML = html; if (document.getElementsByClassName("tbllist")[0]?.getElementsByTagName("tr").length === 2) { document.getElementsByName('rowclass').forEach(tr => { if (parseInt(tr.getElementsByTagName("td")[9].innerText) < parseInt(tr.getElementsByTagName("td")[8].innerText)) { //当前可选 tr.style.backgroundColor = "#2ecc71"; // 判断是否由不可选转来 if (document.getElementsByClassName("tblop")[1].getElementsByTagName("td")[1]?.getElementsByTagName("button").length === 1) { document.getElementsByClassName("tblop")[1].getElementsByTagName("td")[0].getElementsByTagName("button")[2].remove() document.getElementById("tktable").remove() } if (document.getElementById("XKChecker")?.checked === true) { gotoXK( document.getElementsByName("CID")[0].value, document.getElementsByName("TeachNo")[0].value, document.getElementById("TKChecker").checked, document.getElementById("TKCID").value, document.getElementById("TKTeachNo").value ) } //添加一键去选课 window.oneClickXK = () => { gotoXK( document.getElementsByName("CID")[0].value, document.getElementsByName("TeachNo")[0].value, false) } document.getElementsByClassName("tblop")[1].getElementsByTagName("td")[1]?.remove(); let newBtn = document.createElement("button"); newBtn.className = "btn btn-primary btn-sm"; newBtn.type = "button"; newBtn.setAttribute("onClick", `window.oneClickXK();document.getElementsByClassName("tblop")[1].getElementsByTagName("td")[1].remove();`); newBtn.innerHTML = ` 去选课(当前可选,未知是否课满锁课)`; let newTd = document.createElement("td") newTd.appendChild(newBtn) document.getElementsByClassName("tblop")[1].getElementsByTagName("tr")[0].appendChild(newTd); } else if (tr.getElementsByTagName("td")[11].innerText.indexOf("人数已满") !== -1) { // 人数已满 先到先得的课程状态 tr.style.backgroundColor = "#e74c3c"; let timeOutId = setTimeout(() => Query(PageIndex, PageSize), 1000); if (document.getElementById("tktable") === null) { log('queried course can not be selected, started refreshing..') document.getElementsByClassName("tblop")[1].getElementsByTagName("td")[1]?.remove(); let newBtn = document.createElement("button"); newBtn.className = "btn btn-primary btn-sm"; newBtn.type = "button"; newBtn.setAttribute("onClick", `clearTimeout(${timeOutId});document.getElementsByClassName("tblop")[1].getElementsByTagName("td")[1].remove();document.getElementById("tktable").remove();`); newBtn.innerHTML = ` 取消自动查询`; let newTd = document.createElement("td") newTd.appendChild(newBtn) document.getElementsByClassName("tblop")[1].getElementsByTagName("tr")[0].appendChild(newTd); let tktable = document.createElement("tr") tktable.id = "tktable" tktable.innerHTML = `