您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
没有任何引流和诱导,不需要手动输入代码,安装后访问学校教务系统,然后进入"学籍预警查询"或查分助手即可查询成绩信息。同时在主菜单添加快速入口。
// ==UserScript== // @name 惠州学院 HZU | 教务系统查分助手 // @namespace http://tampermonkey.net/ // @version 1.2.1 // @description 没有任何引流和诱导,不需要手动输入代码,安装后访问学校教务系统,然后进入"学籍预警查询"或查分助手即可查询成绩信息。同时在主菜单添加快速入口。 // @author [email protected] // @license Apache License 2.0 // @match https://jwxt.hzu.edu.cn/xjyj/* // @match https://jwxt.hzu.edu.cn/xtgl/* // @homepage https://greasyfork.org/en/scripts/500594 // @homepage https://github.com/Ckrvxr // ==/UserScript== (function() { 'use strict'; function addMainMenuItem() { // 电脑版菜单添加 const navMenu = document.querySelector('#cdNav .nav.navbar-nav'); if (navMenu) { const navItem = document.createElement('li'); navItem.className = 'dropdown'; navItem.style.marginLeft = '8px'; navItem.innerHTML = ` <a href="https://jwxt.hzu.edu.cn/xjyj/xjyj_cxXjyjIndex.html?gnmkdm=N105505&layout=default" style="font-weight:bold;color:#8fbda0;box-shadow:inset 0 0 0 3px #8fbda0"> 查分助手 </a>`; navMenu.appendChild(navItem); } // 手机版菜单添加 const infoQuerySection = [...document.querySelectorAll('#app-page .app')].find(app => app.querySelector('.title span')?.textContent === '信息查询'); if (infoQuerySection) { const boxs = infoQuerySection.querySelector('.boxs'); if (boxs && !boxs.querySelector('a[href*="xjyj_cxXjyjIndex"]')) { const newBox = document.createElement('div'); newBox.className = 'box app-box'; newBox.style.margin = '8px'; newBox.innerHTML = ` <a href="https://jwxt.hzu.edu.cn/xjyj/xjyj_cxXjyjIndex.html?gnmkdm=N105505&layout=default" style="text-decoration:none;color:#333;display:block;text-align:center"> <img src="https://em-content.zobj.net/source/animated-noto-color-emoji/427/hundred-points_1f4af.gif" alt="💯"> <p>查分助手</p> </a>`; boxs.appendChild(newBox); } } } function handleScoreQuery() { const SCORE_API_URL = "https://jwxt.hzu.edu.cn/xjyj/xjyj_cxXjyjjdlb.html"; // 获取表单数据 function getFormData() { const formData = { jg_id: document.getElementById("jg_id")?.value || null, njdm_id: document.getElementById("njdm_id")?.value || null, zyh_id: document.getElementById("zyh_id")?.value || null }; console.log("[教务系统查分助手] 表单数据:", formData); return formData; } // 发起成绩请求 function fetchScores(formData) { const queryParams = new URLSearchParams(formData).toString(); console.log("[教务系统查分助手] 请求地址:", SCORE_API_URL); console.log("[教务系统查分助手] 请求参数:", queryParams); return fetch(SCORE_API_URL, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" }, body: queryParams }).then(response => { if (!response.ok) { throw new Error(`HTTP 错误! 状态码: ${response.status}`); } return response.json(); }).then(data => { console.log("[教务系统查分助手] API 响应数据:", data); return data; }); } // 处理成绩数据 function processScoreData(scoreData) { console.log("[教务系统查分助手] 开始处理原始数据:", scoreData); let courses = []; try { scoreData.forEach(semester => { semester.kcList && semester.kcList.forEach(course => { if (course.kcmc && course.bfzcj) { courses.push({ name: course.kcmc, score: parseFloat(course.bfzcj) }); } }); }); } catch (e) { console.error("[教务系统查分助手] 解析成绩数据失败:", e); } console.log("[教务系统查分助手] 解析完成,共找到课程数:", courses.length); console.log("[教务系统查分助手] 解析后的课程列表:", courses); return courses.sort((a, b) => a.name.localeCompare(b.name, "zh-CN")); } // 生成 HTML 显示内容 function generateScoreHTML(courses) { return courses.map(course => ` <div class="course-score ${course.score < 60 ? "fail" : "pass"}"> <span class="course-name">${course.name}</span> <span class="course-score-value">${course.score}</span> </div> `).join(""); } // 显示模态框 function showScoreModal(htmlContent, isError = false, coursesData = null) { let allCount = 0, passCount = 0, failCount = 0; for (let course of coursesData) { const score = parseFloat(course.score); if (!isNaN(score)) { allCount++; if (score >= 60) { passCount++; } else { failCount++; } } } console.log("[教务系统查分助手] 显示模态框:", { allCount, passCount, failCount }); const modal = document.createElement("div"); modal.id = "custom-modal"; modal.innerHTML = ` <div class="modal-content"> <h2 class="modal-title">${isError ? "错误" : "您的成绩"}</h2> <div class="filter-buttons"> <button class="filter-btn active" data-filter="all">全部 (${allCount})</button> <button class="filter-btn" data-filter="pass">及格 (${passCount})</button> <button class="filter-btn" data-filter="fail">不及格 (${failCount})</button> </div> <div class="scores-container">${htmlContent}</div> <button class="close-btn">×</button> </div> `; document.body.appendChild(modal); const closeButton = modal.querySelector(".close-btn"); closeButton.onclick = () => modal.remove(); if (!isError) { const filterButtons = modal.querySelectorAll(".filter-btn"); filterButtons.forEach(button => { button.onclick = () => { filterButtons.forEach(btn => btn.classList.remove("active")); button.classList.add("active"); const filter = button.dataset.filter; modal.querySelectorAll(".course-score").forEach(courseElement => { courseElement.style.display = filter === "all" ? "flex" : filter === "pass" ? (courseElement.classList.contains("pass") ? "flex" : "none") : (courseElement.classList.contains("fail") ? "flex" : "none"); }); }; }); } } // 添加样式 function addModalStyles() { const styleElement = document.createElement("style"); styleElement.textContent = ` #custom-modal { position: fixed; left: 0; top: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; z-index: 10000; backdrop-filter: blur(10px) saturate(180%); } .modal-content { background-color: #fff; border-radius: 10px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); width: 90%; max-width: 500px; max-height: 80vh; display: flex; flex-direction: column; overflow: hidden; position: relative; } .modal-title { font-size: 24px; color: #333; margin: 0; padding: 20px; background-color: #fff; border-bottom: 2px solid #f0f0f0; text-align: center; position: sticky; top: 0; z-index: 2; } .filter-buttons { display: flex; justify-content: center; gap: 10px; padding: 10px 20px; background-color: #f8f9fa; border-bottom: 1px solid #e9ecef; } .filter-btn { padding: 6px 12px; border: none; border-radius: 4px; background-color: #e9ecef; color: #495057; cursor: pointer; transition: all 0.3s ease; font-size: 14px; } .filter-btn:hover { background-color: #dee2e6; } .filter-btn.active { background-color: #8fbda0; color: white; font-weight: bold; } .scores-container { padding: 20px; overflow-y: auto; flex-grow: 1; } .course-score { display: flex; justify-content: space-between; align-items: center; padding: 12px 15px; margin-bottom: 10px; border-radius: 5px; transition: all 0.3s ease; } .course-score:hover { transform: translateY(-3px); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); } .course-score.pass { background-color: #e8f5e9; border-left: 4px solid #4caf50; } .course-score.fail { background-color: #ffebee; border-left: 4px solid #f44336; } .course-name { font-weight: bold; color: #333; flex-grow: 1; margin-right: 10px; } .course-score-value { font-weight: bold; font-size: 18px; } .pass .course-score-value { color: #4caf50; } .fail .course-score-value { color: #f44336; } .close-btn { position: absolute; top: 10px; right: 10px; border: none; background: none; font-size: 48px; color: #999; cursor: pointer; transition: color 0.3s ease; z-index: 20020; } .close-btn:hover { color: #fc4e4e; } .scores-container::-webkit-scrollbar { width: 8px; } .scores-container::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 4px; } .scores-container::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; } .scores-container::-webkit-scrollbar-thumb:hover { background: #555; } `; document.head.appendChild(styleElement); } // 初始化查分逻辑 function ScoreQuery() { console.log("[教务系统查分助手] 开始查分"); // 🧪 调试输出 const formData = getFormData(); fetchScores(formData) .then(processScoreData) .then(courses => { const htmlContent = generateScoreHTML(courses); showScoreModal(htmlContent, false, courses); }) .catch(error => { console.error("[教务系统查分助手] 请求或处理出错:", error); // 🧪 调试输出 showScoreModal(`错误: ${error.message}`, true); }); } addModalStyles(); ScoreQuery(); } if (window.location.href.includes('xtgl/')) { addMainMenuItem(); } else if (window.location.href.includes('xjyj/')) { window.addEventListener("load", handleScoreQuery); } })();