您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
支持功能:跳过5s等待并自动确认,计算小数点后三位绩点、百分制成绩和学分,始终保持所有课程展示在同一页,新增快捷查分入口,选择学年学期自动更新数据,无需点击查询
// ==UserScript== // @name SCNU教务系统绩点计算 // @namespace http://tampermonkey.net/ // @version 3.5.0 // @description 支持功能:跳过5s等待并自动确认,计算小数点后三位绩点、百分制成绩和学分,始终保持所有课程展示在同一页,新增快捷查分入口,选择学年学期自动更新数据,无需点击查询 // @author Ruofan Liao & Jkey & Dandelion // @github https://github.com/LLLLLrf/GPA-Calculate/tree/main // @match https://jwxt.scnu.edu.cn/xtgl/index_initMenu.html // @match https://jwxt.scnu.edu.cn/xtgl/index_initMenu.html?jsdm=* // @match https://jwxt.scnu.edu.cn/cjcx* // @match https://jwxt.scnu.edu.cn/cdjy* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant GPL // @license GPL // ==/UserScript== (function () { 'use strict'; const skipWaiting = function(clickFun) { $("#badge_text").remove(); const btn = $("#btn_yd"); btn.removeAttr("disabled"); btn.addClass("btn-primary"); btn.click(clickFun); } var localAddress = location.href; // if (localAddress.indexOf("initMenu") > -1 && document.getElementByClassName('navbar-nav')){ if (document.getElementsByClassName('navbar-nav')){ var searchButton = document.createElement("span"); // 设置成绩查询按钮样式 searchButton.style.backgroundColor="#ffb300ff"; searchButton.style.padding='14px'; searchButton.style.color='white'; searchButton.style.fontWeight='bold'; searchButton.style.borderRadius='6px'; searchButton.style.cursor='pointer'; searchButton.onclick = function() { clickMenu('N305005', '/cjcx/cjcx_cxDgXscj.html', '学生成绩查询', 'null'); return false; }; searchButton.innerText=" 成绩查询 "; $(".navbar-nav:eq(2)").append(searchButton); } // 登录界面跳过5秒 if (localAddress.indexOf("initMenu") > -1 && document.getElementById('btn_yd')) { if (document.getElementById('btn_yd')) { skipWaiting(() => { window.location.href = _path + '/xtgl/login_loginIndex.html'; }); document.getElementById('btn_yd').click(); } } // 预约教室页面跳过5秒等待 else if (localAddress.indexOf("cdjy") > -1 && document.getElementById('btn_yd')) { skipWaiting(() => { let gnmkdmKey = $('input#gnmkdmKey').val(); //全局文档添加参数 $(document).data("offDetails", "1"); //加载功能主页:且添加不再进入提示信息页面的标记字段 onClickMenu.call(this, '/cdjy/cdjy_cxCdjyIndex.html?doType=details', gnmkdmKey, { "offDetails": "1" }); }); } // 成绩查询界面加入自动计算绩点 else if (localAddress.indexOf("cjcx") > -1) { // 添加绩点span var newTextNode = document.createElement("span"); var newTextNode2 = document.createElement("span"); newTextNode.innerText = "平均绩点:加载中"; newTextNode.id = "avgGPA"; newTextNode2.innerText="总学分:加载中"; newTextNode2.id="sumCredit"; newTextNode2.style.marginLeft='10px'; $("#yhgnPage").append(newTextNode); $("#yhgnPage").append(newTextNode2); // 添加百分制成绩显示 var newTextNode3 = document.createElement("span"); newTextNode3.innerText = "百分制成绩:加载中"; newTextNode3.id = "avgScore"; newTextNode3.style.marginLeft = '10px'; $("#yhgnPage").append(newTextNode3); // 设置每页最多显示1000条并触发刷新 var pgs = $('.ui-pg-selbox'); if (pgs.length) { pgs.val('1000').trigger('change'); } // 监听加载状态,当从加载中切换为加载完成时触发计算 const observeChange = function() { const loadDiv = document.getElementById("load_tabGrid"); if (!loadDiv) return; let prev = loadDiv.style.display; const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.attributeName === 'style') { const curr = loadDiv.style.display; if (prev === 'block' && curr === 'none') { setGPA(); } prev = curr; } }); }); observer.observe(loadDiv, { attributes: true, attributeFilter: ['style'] }); } // 首次进入 observeChange(); document.getElementById("search_go").onclick = function () { // 点击查询时,显示加载中状态 newTextNode.innerText = '平均绩点:加载中'; newTextNode2.innerText = '总学分:加载中'; newTextNode3.innerText = '百分制成绩:加载中'; observeChange(); } $("#xnm").on("change", function () { document.getElementById("search_go").click(); }); $("#xqm").on("change", function () { document.getElementById("search_go").click(); }); } function setGPA() { var page = Number(document.getElementById('sp_1_pager').innerText); if (page <= 0) { $("span#avgGPA").text('平均绩点:暂无成绩'); $("span#sumCredit").text('总学分:暂无'); $("span#avgScore").text('百分制成绩:暂无'); return; } else if (page === 1) { var sumCredit = 0, GPA = 0; // 加权成绩总和 var weightedScoreSum = 0; var credits_grades = $("td[aria-describedby='tabGrid_xfjd']"); var credits = $("td[aria-describedby='tabGrid_xf']"); var courseList=new Array(); var cj = $("td[aria-describedby='tabGrid_cj']"); var course=$("td[aria-describedby='tabGrid_kcmc']"); for (let i = 0; i < credits.length; i++) { if (Number(credits[i].innerText)!==0.00 && Number(credits_grades[i].innerText)!==0.00){ if(cj[i].innerText=="缓考"||cj[i].innerText=="通过"||cj[i].innerText=="免修"){ continue; }else{ sumCredit += Number(credits[i].innerText); GPA += Number(credits_grades[i].innerText); courseList[i] = course[i].innerText; // 按学分加权成绩 var scoreText = cj[i].innerText.trim(); if (/^\d+(\.\d+)?$/.test(scoreText)) { var score = parseFloat(scoreText); weightedScoreSum += score * Number(credits[i].innerText); } } } } GPA /= sumCredit; // 加权百分制成绩 var avgScore = sumCredit > 0 ? weightedScoreSum / sumCredit : 0; $("span#avgGPA").text('平均绩点:' + GPA.toFixed(3)); $("span#sumCredit").text('总学分:' + sumCredit.toFixed(2)); $("span#avgScore").text('百分制成绩:' + avgScore.toFixed(2)); return; } var gnmkdm = $('input#gnmkdmKey').val(); var user = $('input#sessionUserKey').val(); var nd = Date.now(); var xqm = document.getElementById("xqm"); var xqm_val = xqm[xqm.selectedIndex].value; var xnm = document.getElementById("xnm"); var xnm_val = xnm[xnm.selectedIndex].value; // 发送请求并获取所有数据,计算绩点和总学分 fetch('https://jwxt.scnu.edu.cn' + ($("#jsxx").val() === "xs" ? '/cjcx/cjcx_cxXsgrcj.html' : '/cjcx/cjcx_cxDgXscj.html') + '?doType=query&gnmkdm=' + gnmkdm + '&su=' + user, { headers: { 'content-type': 'application/x-www-form-urlencoded;charset=UTF-8' }, body: 'xnm=' + xnm_val + '&xqm=' + xqm_val + '&_search=false&nd=' + nd + '&queryModel.showCount=1000&queryModel.currentPage=1&queryModel.sortName=&queryModel.sortOrder=asc', method: 'POST' }) .then(response => response.json()) .then(data => { var sumCredit = 0, totalGPA = 0; var sumScore = 0, countScore = 0; if (data && data.rows) { data.rows.forEach(function(row) { var xf = parseFloat(row.xf); var xfjd = parseFloat(row.xfjd); var cj = row.cj; if (!isNaN(xf) && xf > 0 && !isNaN(xfjd) && xfjd > 0) { if (cj === '缓考' || cj === '通过' || cj === '免修') return; sumCredit += xf; totalGPA += xfjd; // 累计成绩 var scoreText = String(row.cj).trim(); if (/^\d+(\.\d+)?$/.test(scoreText)) { var score = parseFloat(scoreText); sumScore += score; countScore++; } } }); } var avg = sumCredit > 0 ? totalGPA / sumCredit : 0; var avgScore = countScore > 0 ? sumScore / countScore : 0; $("span#avgGPA").text('平均绩点:' + avg.toFixed(3)); $("span#sumCredit").text('总学分:' + sumCredit.toFixed(2)); $("span#avgScore").text('百分制成绩:' + avgScore.toFixed(2)); }); } })();