// ==UserScript== // @name 韩师(HSTC)自动评课 // @namespace http://tampermonkey.net/ // @version 2.3.5 // @description 摸了一天鱼~修复了一些执行逻辑BUG,优化了UI // @author Dlany-Cohhh // @match *://jw.hstc* // @match *://webvpn.hstc.edu.cn/http-80* // @match *://jw.hstc.edu.cn/* // @match *://*.hstc.edu.cn/* // @match *://webvpn.hstc.edu.cn/* // @icon https://picx.zhimg.com/v2-fab9e4d5ddf148b93df597a86b0525fd_l.jpg?source=32738c0c&needBackground=1 // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // 智能iframe检测:只在包含评教表单的frame中运行 if (window.self !== window.top) { // 如果在iframe中,检查是否包含评教相关元素 const hasEvalForm = () => { return document.querySelector('input[type="radio"]') || document.querySelector('textarea') || document.querySelector('form') || document.querySelector('[name*="option"]') || document.querySelector('[id*="question"]'); }; // 延迟检查,等待DOM加载 setTimeout(() => { if (!hasEvalForm()) { console.log('[评课助手] 当前iframe无评教表单,跳过加载'); return; } }, 1000); } else { // 在父页面中,检查是否有iframe包含评教表单 const hasEvalIframe = () => { const iframes = document.querySelectorAll('iframe'); return iframes.length > 0; // 如果有iframe,让iframe中的脚本处理 }; if (hasEvalIframe()) { console.log('[评课助手] 检测到iframe结构,等待iframe中的脚本处理'); return; } } // --- 配置与库 --- const COMMENT_LIB = [ "老师讲课认真,教学效果优秀,受益匪浅!", "教学内容丰富,讲解深入浅出,课堂氛围好。", "准备充分,条理清晰,是很棒的听课体验。", "教学严谨且不失幽默,能有效调动学生积极性。", "老师非常负责,课后耐心解答问题,点赞!", "对学生要求严格,对待教学工作认真负责,非常敬业。", "备课极其用心,资料准备齐全,是位扎实的好老师。", "课堂互动多,老师专业素养高,非常推荐。", "老师擅长举例,枯燥的理论变得易于理解,效率很高。", "教学节奏把握得很好,重难点突出,听课过程顺畅。" ]; // --- 深度优化后的日志对象 --- const log = { _print: (tag, msg, color) => { console.log( `%c[评课助手] %c${tag}%c ${msg}`, "color: #999; font-size: 10px;", `background: ${color}; color: #fff; padding: 1px 5px; border-radius: 3px; font-weight: bold;`, `color: ${color};` ); }, info: (msg) => log._print("INFO", msg, "#0078d7"), success: (msg) => log._print("DONE", msg, "#28a745"), warn: (msg) => log._print("WARN", msg, "#f39c12"), error: (msg) => log._print("FAIL", msg, "#e74c3c"), step: (num, msg) => { console.log( `%c Step ${num} %c ${msg}`, "background: #34495e; color: #fff; border-radius: 3px 0 0 3px; padding: 1px 6px;", "background: #ecf0f1; color: #34495e; border-radius: 0 3px 3px 0; padding: 1px 6px; font-weight: bold;" ); }, group: (name) => console.group(`%c🚀 评课任务执行: ${name}`, "color: #0078d7; font-weight: bold; font-size: 12px;"), groupEnd: () => console.groupEnd() }; // --- 核心逻辑 --- function autoSelectByStrategy(strategy) { let radios = document.querySelectorAll('input[type="radio"]'); let grouped = {}; radios.forEach(radio => { if (!grouped[radio.name]) grouped[radio.name] = []; grouped[radio.name].push(radio); }); let allGroups = Object.values(grouped); if (allGroups.length === 0) { log.warn("页面上未发现任何单选框"); return false; } // 先尝试查找包含值为0或1的选项组(兼容V1逻辑) let validGroups = allGroups.filter(group => group.some(r => r.value === "0" || r.value === "1") ); // 如果没有0/1值的组,尝试其他常见的评分值 if (validGroups.length === 0) { // 查找包含数字值的组(如1,2,3,4,5 或 5,4,3,2,1) validGroups = allGroups.filter(group => group.some(r => /^\d+$/.test(r.value)) ); } // 如果还是没有,使用所有组(兜底策略) if (validGroups.length === 0) { log.info("未找到标准评分值,使用所有单选框组"); validGroups = allGroups; } log.step(1, `识别到 ${validGroups.length} 个评分项,开始填充...`); // 调试信息:显示找到的值 if (validGroups.length > 0) { let sampleValues = validGroups[0].map(r => r.value).join(', '); log.info(`样本组的值: [${sampleValues}]`); } let randomIndexForGood = (strategy === "excellent") ? Math.floor(Math.random() * validGroups.length) : -1; validGroups.forEach((group, index) => { let targetOption = null; // 检查是否为0/1值系统 let hasZeroOne = group.some(r => r.value === "0" || r.value === "1"); if (hasZeroOne) { let targetValue = "0"; // 默认优秀 if (strategy === "good") targetValue = "1"; else if (strategy === "excellent") targetValue = (index === randomIndexForGood) ? "1" : "0"; else if (strategy === "random") targetValue = Math.random() > 0.15 ? "0" : "1"; targetOption = group.find(r => r.value === targetValue); } else { // 对于其他值系统,选择第一个选项(通常是最好的) if (strategy === "excellent" && index === randomIndexForGood) { // 随机选中的组选择第二个选项(如果存在) targetOption = group[1] || group[0]; } else if (strategy === "good") { // 良好策略选择第二个选项 targetOption = group[1] || group[0]; } else if (strategy === "random") { // 随机策略 let randomIndex = Math.random() > 0.15 ? 0 : (group.length > 1 ? 1 : 0); targetOption = group[randomIndex]; } else { // 默认选择第一个选项 targetOption = group[0]; } } if (targetOption) { targetOption.checked = true; targetOption.dispatchEvent(new Event('change', { bubbles: true })); } }); return true; } function startProcess() { const btn = document.getElementById('auto-eval-btn'); const strategy = document.getElementById('score-strategy').value; const enableSubmit = document.getElementById('auto-submit-toggle').checked; const customComment = document.getElementById('auto-eval-comment').value.trim(); const startTime = performance.now(); log.group(strategy.toUpperCase()); // UI 状态更新 btn.classList.add('processing'); btn.style.setProperty('--progress', '0%'); btn.innerText = "正在处理..."; let progress = 0; const interval = setInterval(() => { progress += 25; btn.style.setProperty('--progress', `${progress}%`); if (progress >= 100) clearInterval(interval); }, 100); // 执行单选逻辑 const hasRadios = autoSelectByStrategy(strategy); if (hasRadios) { // 执行评语逻辑 const finalComment = customComment || COMMENT_LIB[Math.floor(Math.random() * COMMENT_LIB.length)]; const inputs = document.querySelectorAll('textarea, input[type="text"]'); inputs.forEach(el => { el.value = finalComment; el.dispatchEvent(new Event('input', { bubbles: true })); }); log.step(2, `评语填充完成: "${finalComment.substring(0, 12)}..."`); setTimeout(() => { const duration = ((performance.now() - startTime) / 1000).toFixed(2); log.success(`页面填充成功! 耗时: ${duration}s`); btn.innerText = "处理完成 ✓"; btn.style.background = "#e8f5e9"; if (enableSubmit) { log.info("检测到自动提交开启,准备触发提交按钮..."); window.confirm = () => true; window.alert = () => true; const submitBtn = document.querySelector('button[type="submit"], input[value*="提交"], .btn-submit, #submit, a.btn-primary[onclick*="save"]'); if (submitBtn) { setTimeout(() => submitBtn.click(), 500); } else { log.warn("未找到提交按钮,请手动提交"); } } resetButton(btn); }, 600); } else { // 失败逻辑 log.error("未发现可操作的评分项,任务中止"); btn.innerText = "未发现项目"; btn.style.background = "#ffebee"; resetButton(btn); } } function resetButton(btn) { setTimeout(() => { btn.style.setProperty('--progress', '0%'); btn.innerText = "开始执行"; btn.style.background = "#eee"; btn.classList.remove('processing'); log.groupEnd(); }, 1000); } // --- 界面构建 --- function createPopup() { if (document.getElementById('auto-eval-popup')) return; let popup = document.createElement('div'); popup.id = 'auto-eval-popup'; Object.assign(popup.style, { position: 'fixed', top: '15%', right: '20px', background: '#ffffff', borderRadius: '16px', boxShadow: '0 20px 50px rgba(0,0,0,0.15)', zIndex: '2147483647', width: '300px', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', overflow: 'hidden' }); popup.innerHTML = `