// ==UserScript== // @name NWAFU-评教 // @namespace http://tampermonkey.net/ // @version 0.5//能用但还未完善 // @description 辅助完成西北农林科技大学的教学评价,选择“完全赞同”,填写“无意见”,提交后点击确认.需要用户手动刷新页面并点击下一个评教页面来启动脚本。 // @author 小白羊羊 // @match https://newehall.nwafu.edu.cn/jwapp/sys/jwwspj/*default/index.do* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; console.log("【NWAFU自动评教脚本】脚本已启动 (v0.5)"); // --- 用户配置 --- const COMMENT_TEXT = "无意见"; // 定义要填写的评语内容 const AUTO_SUBMIT = true; // !!! 重要:是否自动点击“提交”按钮 (true: 自动提交, false: 只填写不提交) const AUTO_CONFIRM = true; // !!! 重要:是否自动点击提交后的“确认”按钮 const AUTO_NAVIGATE_BACK = false; // !!! 重要:是否自动返回评教列表页(此功能待完善,请根据实际情况配置) const SUBMIT_DELAY_MS = 500; // 点击“提交”前的额外延迟(毫秒) const CONFIRM_DELAY_MS = 500; // 点击“确认”前的额外延迟(毫秒) const CHECK_INTERVAL_MS = 500; // 检查页面元素是否加载的间隔(毫秒) const MAX_CHECK_TIME_MS = 30000; // 最大等待页面加载时间(毫秒),防止无限等待 const MAX_CONFIRM_WAIT_TIME_MS = 10000; // 最大等待确认对话框出现的时间(毫秒) // --- 用户配置结束 --- // --- 警告 --- if (AUTO_SUBMIT) { console.warn("【NWAFU自动评教脚本】警告:已启用自动提交功能!脚本将在填写完成后自动点击提交按钮。"); } else { console.log("【NWAFU自动评教脚本】提示:自动提交功能已禁用。脚本将只填写表单,你需要手动检查并提交。"); } if (AUTO_CONFIRM) { console.warn("【NWAFU自动评教脚本】警告:已启用自动点击“确认”功能!"); } else { console.log("【NWAFU自动评教脚本】提示:自动点击“确认”功能已禁用。"); } if (AUTO_NAVIGATE_BACK) { console.warn("【NWAFU自动评教脚本】警告:已启用自动返回功能!请确保页面返回操作已正确配置。"); } else { console.log("【NWAFU自动评教脚本】提示:自动返回功能已禁用。"); } // --- 警告结束 --- // --- 第一步:选择所有单选题的第一个选项(完全赞同) --- function selectFirstRadioOption() { console.log("【NWAFU自动评教脚本】正在尝试选择“完全赞同”..."); try { const allRadios = document.querySelectorAll('input[type="radio"]'); if (allRadios.length === 0) { console.log("【NWAFU自动评教脚本】未找到任何单选按钮,跳过此步骤。"); return false; } const radioGroups = {}; allRadios.forEach(radio => { const name = radio.name; if (!name) return; if (!radioGroups[name]) { radioGroups[name] = []; } radioGroups[name].push(radio); }); console.log(`【NWAFU自动评教脚本】找到 ${Object.keys(radioGroups).length} 个单选题组。`); let selectedCount = 0; for (const name in radioGroups) { if (radioGroups[name].length > 0) { if (!radioGroups[name][0].disabled) { radioGroups[name][0].checked = true; radioGroups[name][0].dispatchEvent(new Event('change', { bubbles: true })); radioGroups[name][0].dispatchEvent(new Event('input', { bubbles: true })); selectedCount++; } else { console.warn(`【NWAFU自动评教脚本】单选题组 "${name}" 的第一个选项被禁用,跳过。`); } } } console.log(`【NWAFU自动评教脚本】“完全赞同”选项选择完成,共选择 ${selectedCount} 个。`); return true; } catch (error) { console.error("【NWAFU自动评教脚本】选择“完全赞同”时出错:", error); return false; } } // --- 第二步:填写所有文本框 --- function fillTextBoxes() { console.log(`【NWAFU自动评教脚本】正在尝试填写评语:“${COMMENT_TEXT}”...`); try { const textAreas = document.querySelectorAll('textarea'); if (textAreas.length === 0) { console.log("【NWAFU自动评教脚本】未找到需要填写的文本框 (textarea),跳过此步骤。"); return true; } console.log(`【NWAFU自动评教脚本】找到 ${textAreas.length} 个文本框。`); let filledCount = 0; textAreas.forEach((textarea, index) => { if (!textarea.disabled && !textarea.readOnly) { textarea.value = COMMENT_TEXT; textarea.dispatchEvent(new Event('input', { bubbles: true })); textarea.dispatchEvent(new Event('change', { bubbles: true })); filledCount++; } else { console.warn(`【NWAFU自动评教脚本】文本框 ${index} 被禁用或只读,跳过填写。`); } }); console.log(`【NWAFU自动评教脚本】评语填写完成,共填写 ${filledCount} 个。`); return true; } catch (error) { console.error("【NWAFU自动评教脚本】填写评语时出错:", error); return false; } } // --- 第三步:点击提交按钮 --- /** * 查找并点击“提交”按钮。 * 使用 'a[data-action="提交"]' 选择器定位。 */ function clickSubmitButton() { console.log("【NWAFU自动评教脚本】正在尝试查找并点击“提交”按钮..."); const submitButtonSelector = 'a[data-action="提交"]'; try { const submitButton = document.querySelector(submitButtonSelector); if (submitButton) { console.log(`【NWAFU自动评教脚本】找到“提交”按钮 (元素: ${submitButton.outerHTML.substring(0, 100)}...),准备点击...`); submitButton.click(); console.log("【NWAFU自动评教脚本】“提交”按钮已点击。"); // 提交后,开始等待确认对话框 if (AUTO_CONFIRM) { console.log("【NWAFU自动评教脚本】已启用自动确认,开始等待确认对话框..."); waitForConfirmationDialog(); } else { console.log("【NWAFU自动评教脚本】自动确认已禁用。评教流程(无自动确认)结束。"); displayMessage("【NWAFU自动评教脚本】填写完成,提交按钮已点击。自动确认已禁用,请手动确认。", 'info'); } } else { console.error(`【NWAFU自动评教脚本】错误:未能找到“提交”按钮!请检查选择器 "${submitButtonSelector}" 是否仍然有效,或者按钮是否已加载。自动提交失败。`); displayMessage("【NWAFU自动评教脚本】错误:未能找到“提交”按钮!请手动提交。", 'error'); } } catch (error) { console.error("【NWAFU自动评教脚本】点击“提交”按钮时发生错误:", error); displayMessage("【NWAFU自动评教脚本】点击“提交”按钮时发生错误,请手动提交。\n错误信息:" + error.message, 'error'); } } // --- 第四步:等待并点击确认按钮 --- /** * 等待确认对话框出现,并点击其中的“确认”按钮。 */ function waitForConfirmationDialog() { const confirmButtonSelector = 'a.bh-dialog-btn.bh-bg-primary.bh-color-primary-5'; // 根据你提供的元素信息定制的选择器 let confirmCheckAttempts = 0; const maxConfirmAttempts = MAX_CONFIRM_WAIT_TIME_MS / CHECK_INTERVAL_MS; function checkConfirmationButton() { confirmCheckAttempts++; console.log(`【NWAFU自动评教脚本】正在检查确认按钮加载状态... 尝试次数: ${confirmCheckAttempts}`); const confirmButton = document.querySelector(confirmButtonSelector); if (confirmButton) { console.log(`【NWAFU自动评教脚本】找到“确认”按钮 (元素: ${confirmButton.outerHTML.substring(0, 100)}...),将在 ${CONFIRM_DELAY_MS} 毫秒后点击...`); displayMessage("【NWAFU自动评教脚本】找到确认按钮,准备点击..."); // 添加延迟后点击确认按钮 setTimeout(() => { try { confirmButton.click(); console.log("【NWAFU自动评教脚本】“确认”按钮已点击。"); // 确认后,根据配置决定是否返回 if (AUTO_NAVIGATE_BACK) { console.log("【NWAFU自动评教脚本】已启用自动返回,尝试返回上一个页面..."); // TODO: 调用返回页面的函数,需要用户提供具体方法 navigateBack(); // 这是一个占位函数,待实现 } else { console.log("【NWAFU自动评教脚本】自动返回已禁用。请手动返回评教列表。"); displayMessage("【NWAFU自动评教脚本】确认完成。自动返回已禁用,请手动返回评教列表。", 'info'); } } catch (error) { console.error("【NWAFU自动评教脚本】点击“确认”按钮时发生错误:", error); displayMessage("【NWAFU自动评教脚本】点击“确认”按钮时发生错误,请手动处理。\n错误信息:" + error.message, 'error'); } }, CONFIRM_DELAY_MS); } else if (confirmCheckAttempts * CHECK_INTERVAL_MS < MAX_CONFIRM_WAIT_TIME_MS) { // 确认按钮未加载且未超时,继续等待 setTimeout(checkConfirmationButton, CHECK_INTERVAL_MS); } else { // 等待确认按钮超时 console.error(`【NWAFU自动评教脚本】错误:等待“确认”按钮加载超时 (${MAX_CONFIRM_WAIT_TIME_MS}ms)。请检查页面或手动确认。`); displayMessage(`【NWAFU自动评教脚本】错误:等待“确认”按钮超时。请检查页面或手动确认。`, 'error'); } } // 开始检查确认按钮 checkConfirmationButton(); } // --- 第五步:返回评教列表(待实现) --- /** * 返回到评教项目列表页面。 * 此函数需要根据实际页面返回操作进行实现。 */ function navigateBack() { console.log("【NWAFU自动评教脚本】正在尝试返回评教列表页面..."); // TODO: 在这里添加返回页面的具体代码 // 可能的方式: // 1. history.back(); // 返回浏览器历史记录中的上一页 // 2. window.location.href = "评教列表页面的URL"; // 直接跳转到列表页面URL // 3. 点击页面上的返回按钮:document.querySelector('返回按钮的选择器').click(); console.warn("【NWAFU自动评教脚本】自动返回功能尚未实现!请根据实际情况补充 navigateBack 函数的代码。"); displayMessage("【NWAFU自动评教脚本】自动返回功能尚未实现。请手动返回评教列表。", 'warning'); } // --- 辅助函数:显示消息给用户 --- function displayMessage(message, type = 'info') { console[type === 'error' ? 'error' : 'log'](message); const messageBoxId = 'nwafu-evaluation-script-message'; let messageBox = document.getElementById(messageBoxId); if (!messageBox) { messageBox = document.createElement('div'); messageBox.id = messageBoxId; messageBox.style.position = 'fixed'; messageBox.style.top = '10px'; messageBox.style.right = '10px'; messageBox.style.padding = '10px'; messageBox.style.backgroundColor = type === 'error' ? '#fdd' : (type === 'warning' ? '#ffc' : '#dfd'); messageBox.style.border = `1px solid ${type === 'error' ? '#f00' : (type === 'warning' ? '#fc0' : '#0f0')}`; messageBox.style.zIndex = '10000'; messageBox.style.borderRadius = '5px'; messageBox.style.fontSize = '14px'; messageBox.style.color = type === 'error' ? '#c00' : (type === 'warning' ? '#c80' : '#080'); messageBox.style.maxWidth = '300px'; messageBox.style.wordBreak = 'break-word'; messageBox.style.boxShadow = '2px 2px 5px rgba(0,0,0,0.2)'; document.body.appendChild(messageBox); } messageBox.textContent = message; messageBox.style.display = 'block'; // 自动隐藏消息框 (错误消息除外) if (type !== 'error' && type !== 'warning') { // 错误和警告消息不自动隐藏 setTimeout(() => { messageBox.style.display = 'none'; }, 5000); // 5秒后隐藏 } } // --- 脚本执行主流程:等待元素加载 --- let checkAttempts = 0; const maxAttempts = MAX_CHECK_TIME_MS / CHECK_INTERVAL_MS; /** * 检查页面是否已加载评教所需的关键元素 * @returns {boolean} 如果找到关键元素则返回 true */ function areElementsLoaded() { // 检查单选按钮、文本框和提交按钮是否存在 const radios = document.querySelectorAll('input[type="radio"]'); const textareas = document.querySelectorAll('textarea'); const submitButton = document.querySelector('a[data-action="提交"]'); // 认为页面加载完成的条件是:找到至少一个单选按钮 和 找到至少一个文本框 和 找到提交按钮 return radios.length > 0 && textareas.length > 0 && submitButton !== null; } /** * 执行所有评教自动化步骤 */ function runAutoEvaluation() { console.log("【NWAFU自动评教脚本】检测到评教元素加载完成,开始执行自动评教步骤..."); displayMessage("【NWAFU自动评教脚本】检测到评教页面,开始自动填写..."); // 执行选择和填写 const step1Success = selectFirstRadioOption(); const step2Success = fillTextBoxes(); // 检查是否启用自动提交,并且前两步没有报告明显错误 if (AUTO_SUBMIT) { if (step1Success && step2Success) { console.log(`【NWAFU自动评教脚本】填写完成,将在 ${SUBMIT_DELAY_MS} 毫秒后尝试自动提交...`); displayMessage(`【NWAFU自动评教脚本】填写完成,${SUBMIT_DELAY_MS}ms后自动提交...`); setTimeout(clickSubmitButton, SUBMIT_DELAY_MS); } else { console.error("【NWAFU自动评教脚本】由于之前的步骤出错或未找到必要元素,自动提交已取消。请手动检查并提交。"); displayMessage("【NWAFU自动评教脚本】填写步骤中遇到问题,自动提交已取消。请手动检查并提交。", 'error'); } } else { if (step1Success && step2Success) { console.log("【NWAFU自动评教脚本】所有自动填写步骤已执行。自动提交已禁用,请手动检查并提交。"); displayMessage("【NWAFU自动评教脚本】填写完成。自动提交已禁用,请手动检查并提交。"); } else { console.warn("【NWAFU自动评教脚本】填写步骤中遇到问题,请检查页面。自动提交已禁用。"); displayMessage("【NWAFU自动评教脚本】填写步骤中遇到问题,请检查页面。自动提交已禁用。", 'error'); } } } /** * 定时检查页面元素是否加载,加载完成后执行主逻辑 */ function checkPageLoadStatus() { checkAttempts++; console.log(`【NWAFU自动评教脚本】正在检查页面元素加载状态... 尝试次数: ${checkAttempts}`); if (areElementsLoaded()) { // 元素已加载,执行主逻辑 runAutoEvaluation(); } else if (checkAttempts * CHECK_INTERVAL_MS < MAX_CHECK_TIME_MS) { // 元素未加载且未超时,继续等待 setTimeout(checkPageLoadStatus, CHECK_INTERVAL_MS); } else { // 超时 console.error(`【NWAFU自动评教脚本】错误:等待评教元素加载超时 (${MAX_CHECK_TIME_MS}ms)。请检查页面结构或手动评教。`); displayMessage(`【NWAFU自动评教脚本】错误:等待评教元素超时。请检查页面或手动评教。`, 'error'); } } // 脚本启动后,开始检查页面加载状态 console.log(`【NWAFU自动评教脚本】开始等待评教元素加载,最大等待 ${MAX_CHECK_TIME_MS}ms...`); checkPageLoadStatus(); })();