// ==UserScript==
// @name Mutx163学习通自动评教
// @namespace http://tampermonkey.net/
// @version v1.28
// @description 学习通自动评价,支持批量评教,默认满分
// @author Mutx163
// @match https://newes.chaoxing.com/pj/newesReception/questionnaireInfo*
// @match http://newes.chaoxing.com/pj/newesReception/questionnaireInfo*
// @match https://newes.chaoxing.com/pj/frontv2/evaluateList/whatIEvaluated*
// @match http://newes.chaoxing.com/pj/frontv2/evaluateList/whatIEvaluated*
// @match https://newes.chaoxing.com/pj/frontv2/whatIEvaluatedDetails*
// @match http://newes.chaoxing.com/pj/frontv2/whatIEvaluatedDetails*
// @icon
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_log
// ==/UserScript==
// ��������������
function log(message, type = 'info') {
const timestamp = new Date().toLocaleTimeString();
const logMessage = `[${timestamp}] ${message}`;
// 更新进度显示
if (window.progressDiv) {
window.progressDiv.innerHTML += `<div class="${type}">${logMessage}</div>`;
// 保持最新消息可见
window.progressDiv.scrollTop = window.progressDiv.scrollHeight;
}
// 控制台输出
switch(type) {
case 'error':
console.error(logMessage);
GM_log('[ERROR] ' + message);
break;
case 'warning':
console.warn(logMessage);
GM_log('[WARNING] ' + message);
break;
default:
console.log(logMessage);
GM_log('[INFO] ' + message);
}
}
window.onload = function() {
'use strict';
try {
log('脚本开始初始化...');
// 创建进度显示元素
const progressDiv = document.createElement('div');
progressDiv.style.position = 'fixed';
progressDiv.style.bottom = '60px';
progressDiv.style.left = '10px';
progressDiv.style.zIndex = '1000';
progressDiv.style.padding = '10px';
progressDiv.style.backgroundColor = '#f0f0f0';
progressDiv.style.border = '1px solid #ccc';
progressDiv.style.borderRadius = '5px';
progressDiv.style.maxHeight = '400px';
progressDiv.style.overflowY = 'auto';
progressDiv.style.width = '300px';
progressDiv.style.fontSize = '12px';
progressDiv.style.lineHeight = '1.5';
document.body.appendChild(progressDiv);
window.progressDiv = progressDiv;
// 添加样式
const style = document.createElement('style');
style.textContent = `
.info { color: black; }
.warning { color: orange; }
.error { color: red; }
.success { color: green; }
`;
document.head.appendChild(style);
// 创建控制按钮
const autoEvaluateButton = document.createElement('button');
autoEvaluateButton.textContent = '启动自动评教';
autoEvaluateButton.style.position = 'fixed';
autoEvaluateButton.style.bottom = '10px';
autoEvaluateButton.style.left = '10px';
autoEvaluateButton.style.zIndex = '1000';
autoEvaluateButton.style.padding = '10px';
autoEvaluateButton.style.backgroundColor = '#4CAF50';
autoEvaluateButton.style.color = 'white';
autoEvaluateButton.style.border = 'none';
autoEvaluateButton.style.borderRadius = '5px';
autoEvaluateButton.style.cursor = 'pointer';
document.body.appendChild(autoEvaluateButton);
// 检查localStorage中的状态
const autoEvaluateEnabled = localStorage.getItem('autoEvaluateEnabled') === 'true';
log(`当前自动评教状态: ${autoEvaluateEnabled ? '已启用' : '未启用'}`);
// 根据存储的状态更新按钮文本
autoEvaluateButton.textContent = autoEvaluateEnabled ? '禁用自动评教' : '启动自动评教';
// 根据当前页面类型执行不同的操作
const currentURL = window.location.href;
log(`当前页面URL: ${currentURL}`);
// 使用 URL 对象解析当前页面 URL
const urlPath = new URL(currentURL).pathname;
if (urlPath.includes('evaluateList/whatIEvaluated')) {
log('检测到评教列表页面');
handleEvaluationList(autoEvaluateButton);
} else if (urlPath.includes('questionnaireInfo')) {
log('检测到具体评教页面');
handleEvaluationPage(autoEvaluateButton);
} else if (urlPath.includes('whatIEvaluatedDetails')) {
log('检测到评教详情页面');
// 如果自动评教已启用,直接执行评教流程
if (autoEvaluateEnabled) {
executeEvaluationDetails();
}
handleEvaluationDetails(autoEvaluateButton);
}
log('脚本初始化完成', 'success');
} catch (error) {
log(`脚本初始化失败: ${error.message}`, 'error');
console.error(error);
}
};
// 处理评教列表
function handleEvaluationList(button) {
// 添加自动执行逻辑
if (localStorage.getItem('autoEvaluateEnabled') === 'true') {
log('检测到自动评教已启用,开始执行...');
startEvaluationProcess();
}
button.addEventListener('click', async function() {
try {
const isEnabled = localStorage.getItem('autoEvaluateEnabled') === 'true';
localStorage.setItem('autoEvaluateEnabled', !isEnabled);
button.textContent = !isEnabled ? '禁用自动评教' : '启动自动评教';
if (!isEnabled) {
startEvaluationProcess();
}
} catch (error) {
log(`评教列表处理出错: ${error.message}`, 'error');
console.error(error);
}
});
}
// 新增函数:等待元素加载
function waitForElement(selector, maxWaitTime = 10000) {
return new Promise((resolve, reject) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(() => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
setTimeout(() => {
observer.disconnect();
reject(new Error(`等待元素 ${selector} 超时`));
}, maxWaitTime);
});
}
// 修改开始评教流程函数
async function startEvaluationProcess() {
try {
log('开始检查未完成的评教任务...');
// 等待表格加载
log('等待评教任务表格加载...');
await waitForElement('.el-table__body-wrapper');
// 确保表格内容完全加载
await new Promise(resolve => setTimeout(resolve, 2000));
// 获取所有行
const rows = document.querySelectorAll('.el-table__row');
log(`找到 ${rows.length} 个评教任务行`);
if (rows.length === 0) {
log('尝试使用备用选择器查找任务行...');
const tableBody = document.querySelector('.el-table__body');
if (tableBody) {
const alternativeRows = tableBody.querySelectorAll('tr');
log(`使用备用选择器找到 ${alternativeRows.length} 个任务行`);
if (alternativeRows.length > 0) {
processRows(Array.from(alternativeRows));
return;
}
}
log('无法找到评教任务行,请检查页面是否正确加载', 'error');
return;
}
processRows(Array.from(rows));
} catch (error) {
log(`评教流程出错: ${error.message}`, 'error');
console.error(error);
}
}
// 新增函数:处理任务行
function processRows(rows) {
// 过滤出未完成的任务行
const unfinishedRows = rows.filter(row => {
const statusTag = row.querySelector('.d_submit_tag');
return statusTag && !statusTag.classList.contains('green');
});
const totalTasks = unfinishedRows.length;
log(`其中有 ${totalTasks} 个未完成的评教任务`);
if (totalTasks === 0) {
log('没有找到未完成的评教任务', 'warning');
return;
}
// 保存任务信息到GM存储
GM_setValue('totalTasks', totalTasks);
GM_setValue('currentTask', 0);
log('已保存任务信息到存储');
// 获取第一个未完成任务的"查看详情"按钮并点击
const firstUnfinishedRow = unfinishedRows[0];
// 查找查看详情按钮
const buttons = firstUnfinishedRow.querySelectorAll('a.d_button_text');
const detailButton = Array.from(buttons).find(btn => btn.textContent.trim() === '查看详情');
if (detailButton) {
log('找到未完成任务的查看详情按钮,准备点击...');
setTimeout(() => {
detailButton.click();
log('已点击查看详情按钮');
}, 1000);
} else {
log(`在未完成任务行中找到 ${buttons.length} 个按钮,但没有找到查看详情按钮`, 'error');
// 输出所有按钮的文本内容以供调试
buttons.forEach((btn, index) => {
log(`按钮 ${index + 1} 的文本内容: "${btn.textContent.trim()}"`, 'info');
});
}
}
// 新增函数:执行评教详情页面的评教流程
function executeEvaluationDetails() {
log('检测到自动评教已启用,准备查找评价按钮...');
// 等待页面加载完成
waitForElement('.d_table_btns').then(() => {
try {
// 查找所有按钮容器
const btnContainers = document.querySelectorAll('.d_table_btns');
log(`找到 ${btnContainers.length} 个按钮容器`);
// 遍历容器查找评价按钮
let evaluateButton = null;
btnContainers.forEach((container, index) => {
const btn = container.querySelector('a.d_button_text');
if (btn && btn.textContent.trim() === '评价') {
evaluateButton = btn;
log(`在第 ${index + 1} 个容器中找到评价按钮`);
}
});
if (evaluateButton) {
log('找到评价按钮,准备点击...');
setTimeout(() => {
evaluateButton.click();
log('已点击评价按钮');
}, 1000);
} else {
// 如果没有找到评价按钮,说明可能已经评价完成,尝试返回
const backButton = document.querySelector('a.d_back');
if (backButton) {
log('找到返回按钮,准备返回上一页...');
setTimeout(() => {
backButton.click();
log('已点击返回按钮');
}, 1000);
} else {
log('未找到返回按钮', 'error');
// 输出所有按钮的文本内容以供调试
btnContainers.forEach((container, index) => {
const btn = container.querySelector('a.d_button_text');
if (btn) {
log(`容器 ${index + 1} 中的按钮文本: "${btn.textContent.trim()}"`, 'info');
}
});
}
}
} catch (error) {
log(`查找评价按钮出错: ${error.message}`, 'error');
}
}).catch(error => {
log(`等待按钮容器加载失败: ${error.message}`, 'error');
// 尝试备用方案
const allButtons = document.querySelectorAll('a.d_button_text');
log(`使用备用选择器找到 ${allButtons.length} 个按钮`);
allButtons.forEach((btn, index) => {
log(`按钮 ${index + 1} 的文本内容: "${btn.textContent.trim()}"`, 'info');
if (btn.textContent.trim() === '评价') {
log('找到评价按钮,准备点击...');
setTimeout(() => {
btn.click();
log('已点击评价按钮');
}, 1000);
}
});
});
}
// 处理评教详情页面
function handleEvaluationDetails(button) {
try {
log('开始处理评教详情页面...');
// 如果自动评教已启用,自动执行评教流程
if (localStorage.getItem('autoEvaluateEnabled') === 'true') {
log('检测到自动评教已启用,准备执行评教流程...');
// 确保页面完全加载后再执行
setTimeout(executeEvaluationDetails, 1000);
}
// 添加按钮点击事件
button.addEventListener('click', function() {
const isEnabled = localStorage.getItem('autoEvaluateEnabled') === 'true';
localStorage.setItem('autoEvaluateEnabled', !isEnabled);
button.textContent = !isEnabled ? '禁用自动评教' : '启动自动评教';
if (!isEnabled) {
executeEvaluationDetails();
}
});
} catch (error) {
log(`评教详情页面处理出错: ${error.message}`, 'error');
console.error(error);
}
}
// 处理具体评教页面
function handleEvaluationPage(button) {
try {
const totalTasks = GM_getValue('totalTasks', 0);
const currentTask = GM_getValue('currentTask', 0);
if (totalTasks > 0) {
log(`正在处理第 ${currentTask + 1}/${totalTasks} 个任务的评教`);
}
button.addEventListener('click', function() {
const isEnabled = localStorage.getItem('autoEvaluateEnabled') === 'true';
localStorage.setItem('autoEvaluateEnabled', !isEnabled);
button.textContent = !isEnabled ? '禁用自动评教' : '启动自动评教';
if (!isEnabled) {
startAutoEvaluation();
}
});
// 果已启用,自动开始评教
if (localStorage.getItem('autoEvaluateEnabled') === 'true') {
startAutoEvaluation();
}
} catch (error) {
log(`评教页面处理出错: ${error.message}`, 'error');
console.error(error);
}
}
function triggerEvent(element, eventType) {
try {
const event = new Event(eventType, {
bubbles: true,
cancelable: true
});
element.dispatchEvent(event);
log(`触发事件 ${eventType} 成功`);
} catch (error) {
log(`触发事件 ${eventType} 失败: ${error.message}`, 'error');
console.error(error);
}
}
function startAutoEvaluation() {
setTimeout(() => {
try {
log('开始自动评教...');
// 查找所有打分题输入框并填写满分
const scoreInputs = document.querySelectorAll('input.dafen');
log(`找到 ${scoreInputs.length} 个打分输入框`);
if (scoreInputs.length > 0) {
scoreInputs.forEach((input, index) => {
try {
const maxScore = input.getAttribute('maxscore');
input.value = maxScore;
log(`设置第 ${index + 1} 个评分为满分: ${maxScore}`);
// 触发所有必要的事件
triggerEvent(input, 'input');
triggerEvent(input, 'propertychange');
triggerEvent(input, 'keyup');
triggerEvent(input, 'blur');
if (typeof window.allScore === 'function') {
window.allScore();
log('调用计分函数成功');
}
} catch (error) {
log(`处理第 ${index + 1} 个评分出错: ${error.message}`, 'error');
}
});
}
// 查找所有文本框并填写"无"
const textareas = document.querySelectorAll('textarea.blueTextarea');
log(`找到 ${textareas.length} 个文本框`);
if (textareas.length > 0) {
textareas.forEach((textarea, index) => {
try {
textarea.value = '无';
log(`设置第 ${index + 1} 个文本框内容为"无"`);
triggerEvent(textarea, 'input');
triggerEvent(textarea, 'propertychange');
triggerEvent(textarea, 'keyup');
} catch (error) {
log(`处理第 ${index + 1} 个文本框出错: ${error.message}`, 'error');
}
});
}
// 延迟提交
setTimeout(() => {
log('准备提交评教...');
// 查找提交按钮
const submitButton = document.querySelector('a[onclick*="save(2)"]');
if (submitButton) {
log('找到提交按钮,准备点击...');
// 直接调用save函数
if (typeof window.save === 'function') {
window.save(2);
log('已调用提交函数');
} else {
// 如果找不到save函数,尝试点击按钮
submitButton.click();
log('已点击提交按钮');
}
// 处理确认弹窗
setTimeout(() => {
try {
const confirmButtons = document.querySelectorAll('.layui-layer-btn0');
log(`找到 ${confirmButtons.length} 个确认按钮`);
if (confirmButtons.length > 0) {
confirmButtons.forEach(button => button.click());
log('已点击确认按钮');
// 更新任务计数并返回列表页
const currentTask = GM_getValue('currentTask', 0);
const totalTasks = GM_getValue('totalTasks', 0);
if (currentTask < totalTasks - 1) {
GM_setValue('currentTask', currentTask + 1);
log(`更新任务进度: ${currentTask + 1}/${totalTasks}`);
setTimeout(() => {
log('返回上一页...');
window.location.href = document.referrer;
}, 1000);
} else {
// 所有任务完成,清除存储的任务信息
GM_deleteValue('totalTasks');
GM_deleteValue('currentTask');
log('所有评教任务已完成!', 'success');
setTimeout(() => {
log('返回列表页...');
window.location.href = document.referrer;
}, 1000);
}
} else {
log('未找到确认按钮', 'error');
}
} catch (error) {
log(`处理确认弹窗出错: ${error.message}`, 'error');
}
}, 1000);
} else {
log('未找到提交按钮', 'error');
}
}, 1000);
} catch (error) {
log(`自动评教过程出错: ${error.message}`, 'error');
console.error(error);
}
}, 1000);
}