您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
需要手动提交并切换至下一个老师。
// ==UserScript== // @name SCNU学生评价辅助工具 // @namespace https://github.com/FaterYU/SCNU-Evaluation-Helper-Anti-Detection // @version 1.0 // @description 需要手动提交并切换至下一个老师。 // @author FaterYU (Enhanced by Gemini) // @match https://jwxt.scnu.edu.cn/xspjgl/xspj_cxXspjIndex.html* // @icon https://www.google.com/s2/favicons?sz=64&domain=scnu.edu.cn // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; const PROCESSED_MARKER = 'data-script-processed'; // 生成一个在min和max之间的随机延迟时间(毫秒) function randomDelay(min = 500, max = 1500) { return Math.floor(Math.random() * (max - min + 1) + min); } /** * 模拟人类行为,逐个填充选项,然后提交 * @param {HTMLElement} formElement - 评价表单的 <form> 元素 */ async function humanizedFillAndSubmit(formElement) { console.log("检测到评价表单,开始模拟人类行为填充...", formElement); const radioButtons = Array.from(formElement.querySelectorAll('input.radio-pjf')); if (radioButtons.length === 0) { console.error("未找到任何 .radio-pjf 按钮,操作中断。"); return; } console.log(`找到 ${radioButtons.length} 个评分项,开始逐个选择...`); const questionNames = [...new Set(radioButtons.map(radio => radio.name))]; // 模拟逐个问题进行回答 for (const name of questionNames) { const firstOption = formElement.querySelector(`input.radio-pjf[name="${name}"]`); if (firstOption) { firstOption.click(); // 使用 .click() 来模拟点击,更能触发相关事件 } // 在回答每个问题后加入一个短暂的随机停顿 await new Promise(resolve => setTimeout(resolve, randomDelay(50, 150))); } // 找到提交按钮 const submitButton = formElement.querySelector('#btn_xspj_tj'); if (submitButton) { console.log("所有选项填充完毕,等待一个随机延迟后点击提交..."); // 在点击提交前也加入一个明显的停顿 await new Promise(resolve => setTimeout(resolve, randomDelay(800, 1800))); submitButton.click(); console.log("已点击提交按钮。"); } else { console.warn("未在表单内找到提交按钮 #btn_xspj_tj"); } } /** * 查找并点击下一个未评价课程 */ function findAndClickNextCourse() { console.log("开始查找下一个未评价的课程..."); const courseListContainer = document.getElementById('gbox_tempGrid'); if (!courseListContainer) { console.log("未找到课程列表容器。"); return false; } const courses = courseListContainer.querySelectorAll('tr.jqgrow'); for (const course of courses) { const statusCell = course.querySelector('td[title="未评"]'); if (statusCell) { console.log("找到未评价课程,延迟后点击:", course.innerText.trim().replace(/\s+/g, ' ')); // 点击前增加延迟 setTimeout(() => course.click(), randomDelay(1000, 2000)); return true; // 表示已找到并安排点击 } } console.log("所有课程均已评价完毕,脚本任务结束。"); return false; // 表示没有未评课程了 } /** * 主循环,持续监控页面状态 */ function mainLoop() { // --- 任务1: 处理新加载的“评价”表单 --- const panelContent = document.getElementById('panel_content'); if (panelContent) { const evalForm = panelContent.querySelector(`form#ajaxForm1:not([${PROCESSED_MARKER}])`); if (evalForm && evalForm.querySelector('input.radio-pjf')) { console.log("检测到新的评价表单,准备进行人性化填充。"); evalForm.setAttribute(PROCESSED_MARKER, 'true'); humanizedFillAndSubmit(evalForm); // 调用增加了延迟的新函数 } } // --- 任务2: 处理“提交成功”的弹窗 --- const successAlert = document.querySelector("#tip_alert"); if (successAlert && successAlert.offsetParent !== null) { const okButton = successAlert.querySelector('#btn_ok'); if (okButton) { console.log("检测到'提交成功'弹窗,延迟后点击确定。"); // 在自动关闭成功提示前也加上延迟 setTimeout(() => { okButton.click(); console.log("成功弹窗已关闭,准备评价下一个课程..."); findAndClickNextCourse(); }, randomDelay()); // 为防止重复处理,可以临时隐藏它 successAlert.style.display = 'none'; } } // --- 任务3: 处理“请勿使用脚本”的警告弹窗 --- const warningAlert = document.querySelector(".bootbox-alert"); if (warningAlert && warningAlert.offsetParent !== null && warningAlert.innerText.includes('请勿使用类似脚本')) { const warningOkButton = warningAlert.querySelector('#btn_ok'); if (warningOkButton) { console.warn("检测到'反脚本'警告!将自动关闭并减慢速度重试。"); // 立即关闭警告框 warningOkButton.click(); // 由于被检测到了,我们可以在这里采取一些策略,比如等待更长时间再继续 // 这里我们简单地让主循环在下一次迭代时重新查找课程 console.log("已关闭警告弹窗,脚本将在下次循环时继续。"); } } } // --- 脚本启动入口 --- window.addEventListener('load', () => { console.log("SCNU评价辅助脚本已启动。"); // 首次运行时,更长的延迟,更像人类 setTimeout(findAndClickNextCourse, randomDelay(2000, 3000)); // 启动核心的循环监视器,将检查间隔也设为一个随机值 setInterval(mainLoop, randomDelay(1000, 1500)); }); })();